aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRouli <rouli.net@gmail.com>2013-01-17 17:33:29 +0200
committerRouli <rouli.net@gmail.com>2013-01-17 17:33:29 +0200
commit446f9f0a0fc12159ba663d3b8bdc8f1206a197c7 (patch)
tree9cb474c3154fb4146cce41e40e25b4a8e3e57d46
parent20fa6a30839500207d7d509fe3b8697dbd22a33e (diff)
parent280dd94198931bcd819848a70d68f6f5d9f3270b (diff)
downloadmitmproxy-446f9f0a0fc12159ba663d3b8bdc8f1206a197c7.tar.gz
mitmproxy-446f9f0a0fc12159ba663d3b8bdc8f1206a197c7.tar.bz2
mitmproxy-446f9f0a0fc12159ba663d3b8bdc8f1206a197c7.zip
Merge remote-tracking branch 'upstream/master'
-rw-r--r--CHANGELOG44
-rw-r--r--README.mkd23
-rw-r--r--README.txt83
-rw-r--r--doc-src/01-bootstrap.min.css940
-rw-r--r--doc-src/01-reset-fonts-grids-base.css8
-rw-r--r--doc-src/02-docstyle.css131
-rw-r--r--doc-src/_explicit.graffle/data.plist572
-rw-r--r--doc-src/_explicit.graffle/image3.icnsbin0 -> 97327 bytes
-rw-r--r--doc-src/_explicit.graffle/image6.tiffbin0 -> 5075704 bytes
-rw-r--r--doc-src/_explicit_https.graffle/data.plist1054
-rw-r--r--doc-src/_explicit_https.graffle/image3.icnsbin0 -> 97327 bytes
-rw-r--r--doc-src/_explicit_https.graffle/image6.tiffbin0 -> 5075704 bytes
-rw-r--r--doc-src/_layout.html104
-rw-r--r--doc-src/_transparent.graffle/data.plist771
-rw-r--r--doc-src/_transparent.graffle/image3.icnsbin0 -> 97327 bytes
-rw-r--r--doc-src/_transparent.graffle/image6.tiffbin0 -> 5075704 bytes
-rw-r--r--doc-src/_transparent_https.graffle/data.plist1096
-rw-r--r--doc-src/_transparent_https.graffle/image3.icnsbin0 -> 97327 bytes
-rw-r--r--doc-src/_transparent_https.graffle/image6.tiffbin0 -> 5075704 bytes
-rw-r--r--doc-src/admin.html7
-rw-r--r--doc-src/anticache.html10
-rw-r--r--doc-src/certinstall/android-proxydroidinstall.pngbin124917 -> 0 bytes
-rw-r--r--doc-src/certinstall/android-proxydroidsettings.pngbin54150 -> 0 bytes
-rw-r--r--doc-src/certinstall/android.html58
-rw-r--r--doc-src/explicit.pngbin0 -> 65305 bytes
-rw-r--r--doc-src/explicit_https.pngbin0 -> 78951 bytes
-rw-r--r--doc-src/features/anticache.html18
-rw-r--r--doc-src/features/clientreplay.html (renamed from doc-src/clientreplay.html)16
-rw-r--r--doc-src/features/filters.html (renamed from doc-src/filters.html)4
-rw-r--r--doc-src/features/index.py14
-rw-r--r--doc-src/features/proxyauth.html25
-rw-r--r--doc-src/features/replacements.html (renamed from doc-src/replacements.html)19
-rw-r--r--doc-src/features/reverseproxy.html (renamed from doc-src/reverseproxy.html)15
-rw-r--r--doc-src/features/serverreplay.html (renamed from doc-src/serverreplay.html)0
-rw-r--r--doc-src/features/setheaders.html18
-rw-r--r--doc-src/features/sticky.html (renamed from doc-src/sticky.html)44
-rw-r--r--doc-src/features/upstreamcerts.html21
-rw-r--r--doc-src/howmitmproxy.html341
-rw-r--r--doc-src/index.html51
-rw-r--r--doc-src/index.py49
-rw-r--r--doc-src/install.html61
-rw-r--r--doc-src/intro.html4
-rw-r--r--doc-src/scripting/inlinescripts.html5
-rw-r--r--doc-src/transparent.pngbin0 -> 69375 bytes
-rw-r--r--doc-src/transparent/index.py1
-rw-r--r--doc-src/transparent/openbsd.html0
-rw-r--r--doc-src/transparent_https.pngbin0 -> 79758 bytes
-rw-r--r--doc-src/upstreamcerts.html15
-rwxr-xr-xexamples/iframe_injector50
-rw-r--r--libmproxy/authentication.py79
-rw-r--r--libmproxy/cmdline.py38
-rwxr-xr-xlibmproxy/flow.py6
-rw-r--r--libmproxy/platform/osx.py114
-rw-r--r--libmproxy/platform/pf.py16
-rwxr-xr-xlibmproxy/proxy.py65
-rw-r--r--setup.py3
-rw-r--r--test/data/pf014
-rw-r--r--test/test_authentication.py58
-rw-r--r--test/test_dump.py9
-rw-r--r--test/test_flow.py18
-rw-r--r--test/test_platform_pf.py13
-rwxr-xr-xtest/tools/getcert2
-rwxr-xr-xtest/tools/getcn17
-rw-r--r--test/tutils.py4
64 files changed, 5426 insertions, 692 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a260fdb6..a421c129 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,48 @@
+x January 2013: mitmproxy 0.9:
+
+ * Upstream certs mode is now the default.
+
+ * Add a WSGI container that lets you host in-proxy web applications.
+
+ * Full transparent proxy support for Linux and OSX.
+
+ * Introduce netlib, a common codebase for mitmproxy and pathod
+ (http://github.com/cortesi/netlib).
+
+ * Full support for SNI.
+
+ * Color palettes for mitmproxy, tailored for light and dark terminal
+ backgrounds.
+
+ * Stream flows to file as responses arrive with the "W" shortcut in
+ mitmproxy.
+
+ * Extend the filter language, including ~d domain match operator, ~a to
+ match asset flows (js, images, css).
+
+ * Follow mode in mitmproxy ("F" shortcut) to "tail" flows as they arrive.
+
+ * --dummy-certs option to specify and preserve the dummy certificate
+ directory.
+
+ * Server replay from the current captured buffer.
+
+ * Huge improvements in content views. We now have viewers for AMF, HTML,
+ JSON, Javascript, images, XML, URL-encoded forms, as well as hexadecimal
+ and raw views.
+
+ * Add Set Headers, analagous to replacement hooks. Defines headers that are set
+ on flows, based on a matching pattern.
+
+ * A graphical editor for path components in mitmproxy.
+
+ * A small set of standard user-agent strings, which can be used easily in
+ the header editor.
+
+ * Proxy authentication to limit access to mitmproxy
+
+
5 April 2012: mitmproxy 0.8:
* Detailed tutorial for Android interception. Some features that land in
diff --git a/README.mkd b/README.mkd
index a239eb29..b7d5f4ee 100644
--- a/README.mkd
+++ b/README.mkd
@@ -1,9 +1,9 @@
-__mitmproxy__ is an SSL-capable man-in-the-middle proxy for HTTP. It provides a
-console interface that allows traffic flows to be inspected and edited on the
-fly.
+__mitmproxy__ is an interactive, SSL-capable man-in-the-middle proxy for HTTP
+with a console interface.
-__mitmdump__ is the command-line version of mitmproxy, with the same
-functionality but without the user interface. Think tcpdump for HTTP.
+__mitmdump__ is the command-line version of mitmproxy. Think tcpdump for HTTP.
+
+__libmproxy__ is the library that mitmproxy and mitmdump are built on.
Complete documentation and a set of practical tutorials is included in the
distribution package, and is also available at
@@ -18,14 +18,15 @@ Features
- Replay the client-side of an HTTP conversations.
- Replay HTTP responses of a previously recorded server.
- Reverse proxy mode to forward traffic to a specified server.
+- Transparent proxy mode on OSX and Linux.
- Make scripted changes to HTTP traffic using Python.
- SSL certificates for interception are generated on the fly.
-
+- And much, much more.
Download
--------
-Releases and rendered documentation can be found on the mitmproxy website:
+Releases and documentation can be found on the mitmproxy website:
[mitmproxy.org](http://mitmproxy.org)
@@ -42,7 +43,7 @@ Come join us in the #mitmproxy channel on the OFTC IRC network
We also have a mailing list, hosted here:
- http://groups.google.com/group/mitmproxy
+[groups.google.com/group/mitmproxy](http://groups.google.com/group/mitmproxy)
Requirements
@@ -51,17 +52,17 @@ Requirements
* [Python](http://www.python.org) 2.7.x.
* [PyOpenSSL](http://pypi.python.org/pypi/pyOpenSSL) 0.13 or newer.
* [pyasn1](http://pypi.python.org/pypi/pyasn1) 0.1.2 or newer.
-* [urwid](http://excess.org/urwid/) version 0.9.8 or newer.
+* [urwid](http://excess.org/urwid/) version 1.1 or newer.
* [PIL](http://www.pythonware.com/products/pil/) version 1.1 or newer.
* [lxml](http://lxml.de/) version 2.3 or newer.
-* [netlib](http://pypi.python.org/pypi/netlib) 0.1 or newer.
+* [netlib](http://pypi.python.org/pypi/netlib) 0.2.2 or newer.
The following auxiliary components may be needed if you plan to hack on
mitmproxy:
* The test suite uses the [nose](http://readthedocs.org/docs/nose/en/latest/) unit testing
framework and requires [human_curl](https://github.com/Lispython/human_curl) and
- [pathod](http://pypi.python.org/pypi/pathod).
+ [pathod](http://pathod.org).
* Rendering the documentation requires [countershape](http://github.com/cortesi/countershape).
__mitmproxy__ is tested and developed on OSX, Linux and OpenBSD. Windows is not
diff --git a/README.txt b/README.txt
index ba9b4323..7a86dca0 100644
--- a/README.txt
+++ b/README.txt
@@ -1,84 +1,11 @@
-**mitmproxy** is an SSL-capable man-in-the-middle proxy for HTTP. It provides a
-console interface that allows traffic flows to be inspected and edited on the
-fly.
+**mitmproxy** is an interactive, SSL-capable man-in-the-middle proxy for HTTP
+with a console interface.
-**mitmdump** is the command-line version of mitmproxy, with the same
-functionality but without the user interface. Think tcpdump for HTTP.
+**mitmdump** is the command-line version of mitmproxy. Think tcpdump for HTTP.
+
+**libmproxy** is the library that mitmproxy and mitmdump are built on.
Complete documentation and a set of practical tutorials is included in the
distribution package, and is also available at mitmproxy.org_.
-
-Features
---------
-
-- Intercept HTTP requests and responses and modify them on the fly.
-- Save complete HTTP conversations for later replay and analysis.
-- Replay the client-side of an HTTP conversations.
-- Replay HTTP responses of a previously recorded server.
-- Reverse proxy mode to forward traffic to a specified server.
-- Make scripted changes to HTTP traffic using Python.
-- SSL certificates for interception are generated on the fly.
-
-
-Download
---------
-
-Releases and rendered documentation can be found on the mitmproxy website:
-
-mitmproxy.org_
-
-Source is hosted on github:
-
-`github.com/cortesi/mitmproxy`_
-
-
-Community
----------
-
-Come join us in the #mitmproxy channel on the OFTC IRC network
-(irc.oftc.net, port 6667).
-
-We also have a mailing list, hosted here:
-
-http://groups.google.com/group/mitmproxy
-
-
-Requirements
-------------
-
-* Python_ 2.7.x.
-* PyOpenSSL_ 0.13 or newer.
-* pyasn1_ 0.1.2 or newer.
-* urwid_ version 0.9.8 or newer.
-* PIL_ version 1.1 or newer.
-* lxml_ version 2.3 or newer.
-
-The following auxiliary components may be needed if you plan to hack on
-mitmproxy:
-
-* The test suite uses the nose_ unit testing
- framework.
-* Rendering the documentation requires countershape_.
-
-**mitmproxy** is tested and developed on OSX, Linux and OpenBSD. Windows is not
-supported at the moment.
-
-You should also make sure that your console environment is set up with the
-following:
-
-* EDITOR environment variable to determine the external editor.
-* PAGER environment variable to determine the external pager.
-* Appropriate entries in your mailcap files to determine external
- viewers for request and response contents.
-
.. _mitmproxy.org: http://mitmproxy.org
-.. _github.com/cortesi/mitmproxy: http://github.com/cortesi/mitmproxy
-.. _python: http://www.python.org
-.. _PyOpenSSL: http://pypi.python.org/pypi/pyOpenSSL
-.. _pyasn1: http://pypi.python.org/pypi/pyasn1
-.. _PIL: http://www.pythonware.com/products/pil/
-.. _lxml: http://lxml.de/
-.. _urwid: http://excess.org/urwid/
-.. _nose: http://readthedocs.org/docs/nose/en/latest/
-.. _countershape: http://github.com/cortesi/countershape
diff --git a/doc-src/01-bootstrap.min.css b/doc-src/01-bootstrap.min.css
new file mode 100644
index 00000000..34d8b87d
--- /dev/null
+++ b/doc-src/01-bootstrap.min.css
@@ -0,0 +1,940 @@
+@import url('https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700');
+article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
+audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
+audio:not([controls]){display:none;}
+html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
+a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
+a:hover,a:active{outline:0;}
+sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
+sup{top:-0.5em;}
+sub{bottom:-0.25em;}
+img{max-width:100%;width:auto\9;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}
+#map_canvas img,.google-maps img{max-width:none;}
+button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}
+button,input{*overflow:visible;line-height:normal;}
+button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
+button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}
+label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer;}
+input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;}
+input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
+textarea{overflow:auto;vertical-align:top;}
+@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important;} a,a:visited{text-decoration:underline;} a[href]:after{content:" (" attr(href) ")";} abbr[title]:after{content:" (" attr(title) ")";} .ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:"";} pre,blockquote{border:1px solid #999;page-break-inside:avoid;} thead{display:table-header-group;} tr,img{page-break-inside:avoid;} img{max-width:100% !important;} @page {margin:0.5cm;}p,h2,h3{orphans:3;widows:3;} h2,h3{page-break-after:avoid;}}.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
+.clearfix:after{clear:both;}
+.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
+.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
+body{margin:0;font-family:"Open Sans",Calibri,Candara,Arial,sans-serif;font-size:14px;line-height:20px;color:#555555;background-color:#ffffff;}
+a{color:#007fff;text-decoration:none;}
+a:hover{color:#0066cc;text-decoration:underline;}
+.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
+.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);}
+.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px;}
+.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;}
+.row:after{clear:both;}
+[class*="span"]{float:left;min-height:1px;margin-left:20px;}
+.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
+.span12{width:940px;}
+.span11{width:860px;}
+.span10{width:780px;}
+.span9{width:700px;}
+.span8{width:620px;}
+.span7{width:540px;}
+.span6{width:460px;}
+.span5{width:380px;}
+.span4{width:300px;}
+.span3{width:220px;}
+.span2{width:140px;}
+.span1{width:60px;}
+.offset12{margin-left:980px;}
+.offset11{margin-left:900px;}
+.offset10{margin-left:820px;}
+.offset9{margin-left:740px;}
+.offset8{margin-left:660px;}
+.offset7{margin-left:580px;}
+.offset6{margin-left:500px;}
+.offset5{margin-left:420px;}
+.offset4{margin-left:340px;}
+.offset3{margin-left:260px;}
+.offset2{margin-left:180px;}
+.offset1{margin-left:100px;}
+.row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;}
+.row-fluid:after{clear:both;}
+.row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;}
+.row-fluid [class*="span"]:first-child{margin-left:0;}
+.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%;}
+.row-fluid .span12{width:100%;*width:99.94680851063829%;}
+.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%;}
+.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%;}
+.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%;}
+.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%;}
+.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%;}
+.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%;}
+.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%;}
+.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%;}
+.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%;}
+.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%;}
+.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%;}
+.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%;}
+.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%;}
+.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%;}
+.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%;}
+.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%;}
+.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%;}
+.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%;}
+.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%;}
+.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%;}
+.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%;}
+.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%;}
+.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%;}
+.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%;}
+.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%;}
+.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%;}
+.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%;}
+.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%;}
+.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%;}
+.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%;}
+.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%;}
+.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%;}
+.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%;}
+.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%;}
+.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%;}
+[class*="span"].hide,.row-fluid [class*="span"].hide{display:none;}
+[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right;}
+.container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";line-height:0;}
+.container:after{clear:both;}
+.container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";line-height:0;}
+.container-fluid:after{clear:both;}
+p{margin:0 0 10px;}
+.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}
+small{font-size:85%;}
+strong{font-weight:bold;}
+em{font-style:italic;}
+cite{font-style:normal;}
+.muted{color:#dfdfdf;}
+a.muted:hover{color:#c6c6c6;}
+.text-warning{color:#ffffff;}
+a.text-warning:hover{color:#e6e6e6;}
+.text-error{color:#ffffff;}
+a.text-error:hover{color:#e6e6e6;}
+.text-info{color:#ffffff;}
+a.text-info:hover{color:#e6e6e6;}
+.text-success{color:#ffffff;}
+a.text-success:hover{color:#e6e6e6;}
+h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:300;line-height:20px;color:#080808;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#dfdfdf;}
+h1,h2,h3{line-height:40px;}
+h1{font-size:38.5px;}
+h2{font-size:31.5px;}
+h3{font-size:24.5px;}
+h4{font-size:17.5px;}
+h5{font-size:14px;}
+h6{font-size:11.9px;}
+h1 small{font-size:24.5px;}
+h2 small{font-size:17.5px;}
+h3 small{font-size:14px;}
+h4 small{font-size:14px;}
+.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eeeeee;}
+ul,ol{padding:0;margin:0 0 10px 25px;}
+ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
+li{line-height:20px;}
+ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}
+ul.inline,ol.inline{margin-left:0;list-style:none;}ul.inline >li,ol.inline >li{display:inline-block;padding-left:5px;padding-right:5px;}
+dl{margin-bottom:20px;}
+dt,dd{line-height:20px;}
+dt{font-weight:bold;}
+dd{margin-left:10px;}
+.dl-horizontal{*zoom:1;}.dl-horizontal:before,.dl-horizontal:after{display:table;content:"";line-height:0;}
+.dl-horizontal:after{clear:both;}
+.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
+.dl-horizontal dd{margin-left:180px;}
+hr{margin:20px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}
+abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #dfdfdf;}
+abbr.initialism{font-size:90%;text-transform:uppercase;}
+blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px;}
+blockquote small{display:block;line-height:20px;color:#dfdfdf;}blockquote small:before{content:'\2014 \00A0';}
+blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
+blockquote.pull-right small:before{content:'';}
+blockquote.pull-right small:after{content:'\00A0 \2014';}
+q:before,q:after,blockquote:before,blockquote:after{content:"";}
+address{display:block;margin-bottom:20px;font-style:normal;line-height:20px;}
+code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap;}
+pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}pre.prettyprint{margin-bottom:20px;}
+pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0;}
+.pre-scrollable{max-height:340px;overflow-y:scroll;}
+form{margin:0 0 20px;}
+fieldset{padding:0;margin:0;border:0;}
+legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#999999;border:0;border-bottom:1px solid #e5e5e5;}legend small{font-size:15px;color:#dfdfdf;}
+label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px;}
+input,button,select,textarea{font-family:"Open Sans",Calibri,Candara,Arial,sans-serif;}
+label{display:block;margin-bottom:5px;}
+select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#bbbbbb;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;vertical-align:middle;}
+input,textarea,.uneditable-input{width:206px;}
+textarea{height:auto;}
+textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#ffffff;border:1px solid #bbbbbb;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82, 168, 236, 0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);}
+input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal;}
+input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;}
+select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px;}
+select{width:220px;border:1px solid #bbbbbb;background-color:#ffffff;}
+select[multiple],select[size]{height:auto;}
+select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
+.uneditable-input,.uneditable-textarea{color:#dfdfdf;background-color:#fcfcfc;border-color:#bbbbbb;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
+.uneditable-input{overflow:hidden;white-space:nowrap;}
+.uneditable-textarea{width:auto;height:auto;}
+input:-moz-placeholder,textarea:-moz-placeholder{color:#bbbbbb;}
+input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#bbbbbb;}
+input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#bbbbbb;}
+.radio,.checkbox{min-height:20px;padding-left:20px;}
+.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px;}
+.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;}
+.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle;}
+.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
+.input-mini{width:60px;}
+.input-small{width:90px;}
+.input-medium{width:150px;}
+.input-large{width:210px;}
+.input-xlarge{width:270px;}
+.input-xxlarge{width:530px;}
+input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0;}
+.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block;}
+input,textarea,.uneditable-input{margin-left:0;}
+.controls-row [class*="span"]+[class*="span"]{margin-left:20px;}
+input.span12, textarea.span12, .uneditable-input.span12{width:926px;}
+input.span11, textarea.span11, .uneditable-input.span11{width:846px;}
+input.span10, textarea.span10, .uneditable-input.span10{width:766px;}
+input.span9, textarea.span9, .uneditable-input.span9{width:686px;}
+input.span8, textarea.span8, .uneditable-input.span8{width:606px;}
+input.span7, textarea.span7, .uneditable-input.span7{width:526px;}
+input.span6, textarea.span6, .uneditable-input.span6{width:446px;}
+input.span5, textarea.span5, .uneditable-input.span5{width:366px;}
+input.span4, textarea.span4, .uneditable-input.span4{width:286px;}
+input.span3, textarea.span3, .uneditable-input.span3{width:206px;}
+input.span2, textarea.span2, .uneditable-input.span2{width:126px;}
+input.span1, textarea.span1, .uneditable-input.span1{width:46px;}
+.controls-row{*zoom:1;}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0;}
+.controls-row:after{clear:both;}
+.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left;}
+.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px;}
+input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eeeeee;}
+input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent;}
+.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#ffffff;}
+.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#ffffff;}
+.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;}
+.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#ffffff;background-color:#ff7518;border-color:#ffffff;}
+.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#ffffff;}
+.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#ffffff;}
+.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;}
+.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#ffffff;background-color:#ff0039;border-color:#ffffff;}
+.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#ffffff;}
+.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#ffffff;}
+.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;}
+.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#ffffff;background-color:#3fb618;border-color:#ffffff;}
+.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#ffffff;}
+.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#ffffff;}
+.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ffffff;}
+.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#ffffff;background-color:#9954bb;border-color:#ffffff;}
+input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
+.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1;}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0;}
+.form-actions:after{clear:both;}
+.help-block,.help-inline{color:#7b7b7b;}
+.help-block{display:block;margin-bottom:10px;}
+.help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px;}
+.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap;}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px;}
+.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 0px 0px 0;-moz-border-radius:0 0px 0px 0;border-radius:0 0px 0px 0;}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2;}
+.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#eeeeee;border:1px solid #ccc;}
+.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.input-append .active,.input-prepend .active{background-color:#96ed7a;border-color:#3fb618;}
+.input-prepend .add-on,.input-prepend .btn{margin-right:-1px;}
+.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:0px 0 0 0px;-moz-border-radius:0px 0 0 0px;border-radius:0px 0 0 0px;}
+.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:0px 0 0 0px;-moz-border-radius:0px 0 0 0px;border-radius:0px 0 0 0px;}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 0px 0px 0;-moz-border-radius:0 0px 0px 0;border-radius:0 0px 0px 0;}
+.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px;}
+.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 0px 0px 0;-moz-border-radius:0 0px 0px 0;border-radius:0 0px 0px 0;}
+.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 0px 0px 0;-moz-border-radius:0 0px 0px 0;border-radius:0 0px 0px 0;}
+.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:0px 0 0 0px;-moz-border-radius:0px 0 0 0px;border-radius:0px 0 0 0px;}
+.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 0px 0px 0;-moz-border-radius:0 0px 0px 0;border-radius:0 0px 0px 0;}
+.input-prepend.input-append .btn-group:first-child{margin-left:0;}
+input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
+.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
+.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
+.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
+.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
+.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle;}
+.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;}
+.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block;}
+.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0;}
+.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle;}
+.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0;}
+.control-group{margin-bottom:10px;}
+legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate;}
+.form-horizontal .control-group{margin-bottom:20px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0;}
+.form-horizontal .control-group:after{clear:both;}
+.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right;}
+.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0;}.form-horizontal .controls:first-child{*padding-left:180px;}
+.form-horizontal .help-block{margin-bottom:0;}
+.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px;}
+.form-horizontal .form-actions{padding-left:180px;}
+table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}
+.table{width:100%;margin-bottom:20px;}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #dddddd;}
+.table th{font-weight:bold;}
+.table thead th{vertical-align:bottom;}
+.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0;}
+.table tbody+tbody{border-top:2px solid #dddddd;}
+.table .table{background-color:#ffffff;}
+.table-condensed th,.table-condensed td{padding:4px 5px;}
+.table-bordered{border:1px solid #dddddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}.table-bordered th,.table-bordered td{border-left:1px solid #dddddd;}
+.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
+.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;}
+.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;}
+.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;}
+.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;}
+.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;}
+.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;}
+.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9;}
+.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#e8f8fd;}
+table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0;}
+.table td.span1,.table th.span1{float:none;width:44px;margin-left:0;}
+.table td.span2,.table th.span2{float:none;width:124px;margin-left:0;}
+.table td.span3,.table th.span3{float:none;width:204px;margin-left:0;}
+.table td.span4,.table th.span4{float:none;width:284px;margin-left:0;}
+.table td.span5,.table th.span5{float:none;width:364px;margin-left:0;}
+.table td.span6,.table th.span6{float:none;width:444px;margin-left:0;}
+.table td.span7,.table th.span7{float:none;width:524px;margin-left:0;}
+.table td.span8,.table th.span8{float:none;width:604px;margin-left:0;}
+.table td.span9,.table th.span9{float:none;width:684px;margin-left:0;}
+.table td.span10,.table th.span10{float:none;width:764px;margin-left:0;}
+.table td.span11,.table th.span11{float:none;width:844px;margin-left:0;}
+.table td.span12,.table th.span12{float:none;width:924px;margin-left:0;}
+.table tbody tr.success td{background-color:#3fb618;}
+.table tbody tr.error td{background-color:#ff0039;}
+.table tbody tr.warning td{background-color:#ff7518;}
+.table tbody tr.info td{background-color:#9954bb;}
+.table-hover tbody tr.success:hover td{background-color:#379f15;}
+.table-hover tbody tr.error:hover td{background-color:#e60033;}
+.table-hover tbody tr.warning:hover td{background-color:#fe6600;}
+.table-hover tbody tr.info:hover td{background-color:#8d46b0;}
+[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px;}
+.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png");}
+.icon-glass{background-position:0 0;}
+.icon-music{background-position:-24px 0;}
+.icon-search{background-position:-48px 0;}
+.icon-envelope{background-position:-72px 0;}
+.icon-heart{background-position:-96px 0;}
+.icon-star{background-position:-120px 0;}
+.icon-star-empty{background-position:-144px 0;}
+.icon-user{background-position:-168px 0;}
+.icon-film{background-position:-192px 0;}
+.icon-th-large{background-position:-216px 0;}
+.icon-th{background-position:-240px 0;}
+.icon-th-list{background-position:-264px 0;}
+.icon-ok{background-position:-288px 0;}
+.icon-remove{background-position:-312px 0;}
+.icon-zoom-in{background-position:-336px 0;}
+.icon-zoom-out{background-position:-360px 0;}
+.icon-off{background-position:-384px 0;}
+.icon-signal{background-position:-408px 0;}
+.icon-cog{background-position:-432px 0;}
+.icon-trash{background-position:-456px 0;}
+.icon-home{background-position:0 -24px;}
+.icon-file{background-position:-24px -24px;}
+.icon-time{background-position:-48px -24px;}
+.icon-road{background-position:-72px -24px;}
+.icon-download-alt{background-position:-96px -24px;}
+.icon-download{background-position:-120px -24px;}
+.icon-upload{background-position:-144px -24px;}
+.icon-inbox{background-position:-168px -24px;}
+.icon-play-circle{background-position:-192px -24px;}
+.icon-repeat{background-position:-216px -24px;}
+.icon-refresh{background-position:-240px -24px;}
+.icon-list-alt{background-position:-264px -24px;}
+.icon-lock{background-position:-287px -24px;}
+.icon-flag{background-position:-312px -24px;}
+.icon-headphones{background-position:-336px -24px;}
+.icon-volume-off{background-position:-360px -24px;}
+.icon-volume-down{background-position:-384px -24px;}
+.icon-volume-up{background-position:-408px -24px;}
+.icon-qrcode{background-position:-432px -24px;}
+.icon-barcode{background-position:-456px -24px;}
+.icon-tag{background-position:0 -48px;}
+.icon-tags{background-position:-25px -48px;}
+.icon-book{background-position:-48px -48px;}
+.icon-bookmark{background-position:-72px -48px;}
+.icon-print{background-position:-96px -48px;}
+.icon-camera{background-position:-120px -48px;}
+.icon-font{background-position:-144px -48px;}
+.icon-bold{background-position:-167px -48px;}
+.icon-italic{background-position:-192px -48px;}
+.icon-text-height{background-position:-216px -48px;}
+.icon-text-width{background-position:-240px -48px;}
+.icon-align-left{background-position:-264px -48px;}
+.icon-align-center{background-position:-288px -48px;}
+.icon-align-right{background-position:-312px -48px;}
+.icon-align-justify{background-position:-336px -48px;}
+.icon-list{background-position:-360px -48px;}
+.icon-indent-left{background-position:-384px -48px;}
+.icon-indent-right{background-position:-408px -48px;}
+.icon-facetime-video{background-position:-432px -48px;}
+.icon-picture{background-position:-456px -48px;}
+.icon-pencil{background-position:0 -72px;}
+.icon-map-marker{background-position:-24px -72px;}
+.icon-adjust{background-position:-48px -72px;}
+.icon-tint{background-position:-72px -72px;}
+.icon-edit{background-position:-96px -72px;}
+.icon-share{background-position:-120px -72px;}
+.icon-check{background-position:-144px -72px;}
+.icon-move{background-position:-168px -72px;}
+.icon-step-backward{background-position:-192px -72px;}
+.icon-fast-backward{background-position:-216px -72px;}
+.icon-backward{background-position:-240px -72px;}
+.icon-play{background-position:-264px -72px;}
+.icon-pause{background-position:-288px -72px;}
+.icon-stop{background-position:-312px -72px;}
+.icon-forward{background-position:-336px -72px;}
+.icon-fast-forward{background-position:-360px -72px;}
+.icon-step-forward{background-position:-384px -72px;}
+.icon-eject{background-position:-408px -72px;}
+.icon-chevron-left{background-position:-432px -72px;}
+.icon-chevron-right{background-position:-456px -72px;}
+.icon-plus-sign{background-position:0 -96px;}
+.icon-minus-sign{background-position:-24px -96px;}
+.icon-remove-sign{background-position:-48px -96px;}
+.icon-ok-sign{background-position:-72px -96px;}
+.icon-question-sign{background-position:-96px -96px;}
+.icon-info-sign{background-position:-120px -96px;}
+.icon-screenshot{background-position:-144px -96px;}
+.icon-remove-circle{background-position:-168px -96px;}
+.icon-ok-circle{background-position:-192px -96px;}
+.icon-ban-circle{background-position:-216px -96px;}
+.icon-arrow-left{background-position:-240px -96px;}
+.icon-arrow-right{background-position:-264px -96px;}
+.icon-arrow-up{background-position:-289px -96px;}
+.icon-arrow-down{background-position:-312px -96px;}
+.icon-share-alt{background-position:-336px -96px;}
+.icon-resize-full{background-position:-360px -96px;}
+.icon-resize-small{background-position:-384px -96px;}
+.icon-plus{background-position:-408px -96px;}
+.icon-minus{background-position:-433px -96px;}
+.icon-asterisk{background-position:-456px -96px;}
+.icon-exclamation-sign{background-position:0 -120px;}
+.icon-gift{background-position:-24px -120px;}
+.icon-leaf{background-position:-48px -120px;}
+.icon-fire{background-position:-72px -120px;}
+.icon-eye-open{background-position:-96px -120px;}
+.icon-eye-close{background-position:-120px -120px;}
+.icon-warning-sign{background-position:-144px -120px;}
+.icon-plane{background-position:-168px -120px;}
+.icon-calendar{background-position:-192px -120px;}
+.icon-random{background-position:-216px -120px;width:16px;}
+.icon-comment{background-position:-240px -120px;}
+.icon-magnet{background-position:-264px -120px;}
+.icon-chevron-up{background-position:-288px -120px;}
+.icon-chevron-down{background-position:-313px -119px;}
+.icon-retweet{background-position:-336px -120px;}
+.icon-shopping-cart{background-position:-360px -120px;}
+.icon-folder-close{background-position:-384px -120px;}
+.icon-folder-open{background-position:-408px -120px;width:16px;}
+.icon-resize-vertical{background-position:-432px -119px;}
+.icon-resize-horizontal{background-position:-456px -118px;}
+.icon-hdd{background-position:0 -144px;}
+.icon-bullhorn{background-position:-24px -144px;}
+.icon-bell{background-position:-48px -144px;}
+.icon-certificate{background-position:-72px -144px;}
+.icon-thumbs-up{background-position:-96px -144px;}
+.icon-thumbs-down{background-position:-120px -144px;}
+.icon-hand-right{background-position:-144px -144px;}
+.icon-hand-left{background-position:-168px -144px;}
+.icon-hand-up{background-position:-192px -144px;}
+.icon-hand-down{background-position:-216px -144px;}
+.icon-circle-arrow-right{background-position:-240px -144px;}
+.icon-circle-arrow-left{background-position:-264px -144px;}
+.icon-circle-arrow-up{background-position:-288px -144px;}
+.icon-circle-arrow-down{background-position:-312px -144px;}
+.icon-globe{background-position:-336px -144px;}
+.icon-wrench{background-position:-360px -144px;}
+.icon-tasks{background-position:-384px -144px;}
+.icon-filter{background-position:-408px -144px;}
+.icon-briefcase{background-position:-432px -144px;}
+.icon-fullscreen{background-position:-456px -144px;}
+.dropup,.dropdown{position:relative;}
+.dropdown-toggle{*margin-bottom:-3px;}
+.dropdown-toggle:active,.open .dropdown-toggle{outline:0;}
+.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";}
+.dropdown .caret{margin-top:8px;margin-left:2px;}
+.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#ffffff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;}.dropdown-menu.pull-right{right:0;left:auto;}
+.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
+.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#999999;white-space:nowrap;}
+.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{text-decoration:none;color:#ffffff;background-color:#007af5;background-image:-moz-linear-gradient(top, #007fff, #0072e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#007fff), to(#0072e6));background-image:-webkit-linear-gradient(top, #007fff, #0072e6);background-image:-o-linear-gradient(top, #007fff, #0072e6);background-image:linear-gradient(to bottom, #007fff, #0072e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff007fff', endColorstr='#ff0072e6', GradientType=0);}
+.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;outline:0;background-color:#007af5;background-image:-moz-linear-gradient(top, #007fff, #0072e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#007fff), to(#0072e6));background-image:-webkit-linear-gradient(top, #007fff, #0072e6);background-image:-o-linear-gradient(top, #007fff, #0072e6);background-image:linear-gradient(to bottom, #007fff, #0072e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff007fff', endColorstr='#ff0072e6', GradientType=0);}
+.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#dfdfdf;}
+.dropdown-menu .disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:default;}
+.open{*z-index:1000;}.open >.dropdown-menu{display:block;}
+.pull-right>.dropdown-menu{right:0;left:auto;}
+.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000000;content:"";}
+.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px;}
+.dropdown-submenu{position:relative;}
+.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
+.dropdown-submenu:hover>.dropdown-menu{display:block;}
+.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0;}
+.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
+.dropdown-submenu:hover>a:after{border-left-color:#ffffff;}
+.dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
+.dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px;}
+.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#eeeeee;border:1px solid #dcdcdc;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
+.well-large{padding:24px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.well-small{padding:9px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;}.fade.in{opacity:1;}
+.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;}.collapse.in{height:auto;}
+.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;cursor:pointer;opacity:0.4;filter:alpha(opacity=40);}
+button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;}
+.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:14px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#999999;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#dfdfdf;background-image:-moz-linear-gradient(top, #eeeeee, #c8c8c8);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#eeeeee), to(#c8c8c8));background-image:-webkit-linear-gradient(top, #eeeeee, #c8c8c8);background-image:-o-linear-gradient(top, #eeeeee, #c8c8c8);background-image:linear-gradient(to bottom, #eeeeee, #c8c8c8);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffc8c8c8', GradientType=0);border-color:#c8c8c8 #c8c8c8 #a2a2a2;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#c8c8c8;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #bbbbbb;*border:0;border-bottom-color:#a2a2a2;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#999999;background-color:#c8c8c8;*background-color:#bbbbbb;}
+.btn:active,.btn.active{background-color:#aeaeae \9;}
+.btn:first-child{*margin-left:0;}
+.btn:hover{color:#999999;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
+.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
+.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
+.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn-large{padding:22px 30px;font-size:17.5px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px;}
+.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0;}
+.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px;}
+.btn-mini{padding:2px 6px;font-size:10.5px;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
+.btn-block+.btn-block{margin-top:5px;}
+input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}
+.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);}
+.btn{border-color:#c5c5c5;border-color:rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);}
+.btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0f82f5;background-image:-moz-linear-gradient(top, #1a8cff, #0072e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#1a8cff), to(#0072e6));background-image:-webkit-linear-gradient(top, #1a8cff, #0072e6);background-image:-o-linear-gradient(top, #1a8cff, #0072e6);background-image:linear-gradient(to bottom, #1a8cff, #0072e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1a8cff', endColorstr='#ff0072e6', GradientType=0);border-color:#0072e6 #0072e6 #004c99;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0072e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#0072e6;*background-color:#0066cc;}
+.btn-primary:active,.btn-primary.active{background-color:#0059b3 \9;}
+.btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#fe781e;background-image:-moz-linear-gradient(top, #ff8432, #fe6600);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff8432), to(#fe6600));background-image:-webkit-linear-gradient(top, #ff8432, #fe6600);background-image:-o-linear-gradient(top, #ff8432, #fe6600);background-image:linear-gradient(to bottom, #ff8432, #fe6600);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff8432', endColorstr='#fffe6600', GradientType=0);border-color:#fe6600 #fe6600 #b14700;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#fe6600;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#fe6600;*background-color:#e45c00;}
+.btn-warning:active,.btn-warning.active{background-color:#cb5200 \9;}
+.btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#f50f43;background-image:-moz-linear-gradient(top, #ff1a4d, #e60033);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff1a4d), to(#e60033));background-image:-webkit-linear-gradient(top, #ff1a4d, #e60033);background-image:-o-linear-gradient(top, #ff1a4d, #e60033);background-image:linear-gradient(to bottom, #ff1a4d, #e60033);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff1a4d', endColorstr='#ffe60033', GradientType=0);border-color:#e60033 #e60033 #990022;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#e60033;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#e60033;*background-color:#cc002e;}
+.btn-danger:active,.btn-danger.active{background-color:#b30028 \9;}
+.btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#41bb19;background-image:-moz-linear-gradient(top, #47cd1b, #379f15);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#47cd1b), to(#379f15));background-image:-webkit-linear-gradient(top, #47cd1b, #379f15);background-image:-o-linear-gradient(top, #47cd1b, #379f15);background-image:linear-gradient(to bottom, #47cd1b, #379f15);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff47cd1b', endColorstr='#ff379f15', GradientType=0);border-color:#379f15 #379f15 #205c0c;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#379f15;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#379f15;*background-color:#2f8912;}
+.btn-success:active,.btn-success.active{background-color:#28720f \9;}
+.btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#9b59bb;background-image:-moz-linear-gradient(top, #a466c2, #8d46b0);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#a466c2), to(#8d46b0));background-image:-webkit-linear-gradient(top, #a466c2, #8d46b0);background-image:-o-linear-gradient(top, #a466c2, #8d46b0);background-image:linear-gradient(to bottom, #a466c2, #8d46b0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa466c2', endColorstr='#ff8d46b0', GradientType=0);border-color:#8d46b0 #8d46b0 #613079;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#8d46b0;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#8d46b0;*background-color:#7e3f9d;}
+.btn-info:active,.btn-info.active{background-color:#6f378b \9;}
+.btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#080808;background-image:-moz-linear-gradient(top, #0d0d0d, #000000);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0d0d0d), to(#000000));background-image:-webkit-linear-gradient(top, #0d0d0d, #000000);background-image:-o-linear-gradient(top, #0d0d0d, #000000);background-image:linear-gradient(to bottom, #0d0d0d, #000000);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0d0d0d', endColorstr='#ff000000', GradientType=0);border-color:#000000 #000000 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#000000;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#000000;*background-color:#000000;}
+.btn-inverse:active,.btn-inverse.active{background-color:#000000 \9;}
+button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
+button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;}
+button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;}
+button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;}
+.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.btn-link{border-color:transparent;cursor:pointer;color:#007fff;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-link:hover{color:#0066cc;text-decoration:underline;background-color:transparent;}
+.btn-link[disabled]:hover{color:#999999;text-decoration:none;}
+.btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;}
+.btn-group+.btn-group{margin-left:5px;}
+.btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px;}
+.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-group>.btn+.btn{margin-left:-1px;}
+.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px;}
+.btn-group>.btn-mini{font-size:10.5px;}
+.btn-group>.btn-small{font-size:11.9px;}
+.btn-group>.btn-large{font-size:17.5px;}
+.btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;}
+.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
+.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px;}
+.btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;}
+.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;}
+.btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;}
+.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);}
+.btn-group.open .btn.dropdown-toggle{background-color:#c8c8c8;}
+.btn-group.open .btn-primary.dropdown-toggle{background-color:#0072e6;}
+.btn-group.open .btn-warning.dropdown-toggle{background-color:#fe6600;}
+.btn-group.open .btn-danger.dropdown-toggle{background-color:#e60033;}
+.btn-group.open .btn-success.dropdown-toggle{background-color:#379f15;}
+.btn-group.open .btn-info.dropdown-toggle{background-color:#8d46b0;}
+.btn-group.open .btn-inverse.dropdown-toggle{background-color:#000000;}
+.btn .caret{margin-top:8px;margin-left:0;}
+.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px;}
+.btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;}
+.dropup .btn-large .caret{border-bottom-width:5px;}
+.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.btn-group-vertical{display:inline-block;*display:inline;*zoom:1;}
+.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px;}
+.btn-group-vertical>.btn:first-child{-webkit-border-radius:0px 0px 0 0;-moz-border-radius:0px 0px 0 0;border-radius:0px 0px 0 0;}
+.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 0px 0px;-moz-border-radius:0 0 0px 0px;border-radius:0 0 0px 0px;}
+.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:0px 0px 0 0;-moz-border-radius:0px 0px 0 0;border-radius:0px 0px 0 0;}
+.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 0px 0px;-moz-border-radius:0 0 0px 0px;border-radius:0 0 0px 0px;}
+.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#ff7518;border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.alert,.alert h4{color:#ffffff;}
+.alert h4{margin:0;}
+.alert .close{position:relative;top:-2px;right:-21px;line-height:20px;}
+.alert-success{background-color:#3fb618;border-color:transparent;color:#ffffff;}
+.alert-success h4{color:#ffffff;}
+.alert-danger,.alert-error{background-color:#ff0039;border-color:transparent;color:#ffffff;}
+.alert-danger h4,.alert-error h4{color:#ffffff;}
+.alert-info{background-color:#9954bb;border-color:transparent;color:#ffffff;}
+.alert-info h4{color:#ffffff;}
+.alert-block{padding-top:14px;padding-bottom:14px;}
+.alert-block>p,.alert-block>ul{margin-bottom:0;}
+.alert-block p+p{margin-top:5px;}
+.nav{margin-left:0;margin-bottom:20px;list-style:none;}
+.nav>li>a{display:block;}
+.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;}
+.nav>li>a>img{max-width:none;}
+.nav>.pull-right{float:right;}
+.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#dfdfdf;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);text-transform:uppercase;}
+.nav li+.nav-header{margin-top:9px;}
+.nav-list{padding-left:15px;padding-right:15px;margin-bottom:0;}
+.nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
+.nav-list>li>a{padding:3px 15px;}
+.nav-list>.active>a,.nav-list>.active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#007fff;}
+.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px;}
+.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
+.nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";line-height:0;}
+.nav-tabs:after,.nav-pills:after{clear:both;}
+.nav-tabs>li,.nav-pills>li{float:left;}
+.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
+.nav-tabs{border-bottom:1px solid #ddd;}
+.nav-tabs>li{margin-bottom:-1px;}
+.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}
+.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#bbbbbb;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
+.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
+.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#ffffff;background-color:#007fff;}
+.nav-stacked>li{float:none;}
+.nav-stacked>li>a{margin-right:0;}
+.nav-tabs.nav-stacked{border-bottom:0;}
+.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}
+.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
+.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;}
+.nav-pills.nav-stacked>li>a{margin-bottom:3px;}
+.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;}
+.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
+.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
+.nav .dropdown-toggle .caret{border-top-color:#007fff;border-bottom-color:#007fff;margin-top:6px;}
+.nav .dropdown-toggle:hover .caret{border-top-color:#0066cc;border-bottom-color:#0066cc;}
+.nav-tabs .dropdown-toggle .caret{margin-top:8px;}
+.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff;}
+.nav-tabs .active .dropdown-toggle .caret{border-top-color:#bbbbbb;border-bottom-color:#bbbbbb;}
+.nav>.dropdown.active>a:hover{cursor:pointer;}
+.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#ffffff;background-color:#dfdfdf;border-color:#dfdfdf;}
+.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;opacity:1;filter:alpha(opacity=100);}
+.tabs-stacked .open>a:hover{border-color:#dfdfdf;}
+.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";line-height:0;}
+.tabbable:after{clear:both;}
+.tab-content{overflow:auto;}
+.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0;}
+.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
+.tab-content>.active,.pill-content>.active{display:block;}
+.tabs-below>.nav-tabs{border-top:1px solid #ddd;}
+.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0;}
+.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below>.nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;}
+.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd;}
+.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none;}
+.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
+.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
+.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
+.tabs-left>.nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
+.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;}
+.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
+.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
+.tabs-right>.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
+.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;}
+.nav>.disabled>a{color:#dfdfdf;}
+.nav>.disabled>a:hover{text-decoration:none;background-color:transparent;cursor:default;}
+.navbar{overflow:visible;margin-bottom:20px;*position:relative;*z-index:2;}
+.navbar-inner{min-height:50px;padding-left:20px;padding-right:20px;background-color:#080808;background-image:-moz-linear-gradient(top, #080808, #080808);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#080808), to(#080808));background-image:-webkit-linear-gradient(top, #080808, #080808);background-image:-o-linear-gradient(top, #080808, #080808);background-image:linear-gradient(to bottom, #080808, #080808);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff080808', GradientType=0);border:1px solid transparent;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;-webkit-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);-moz-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);*zoom:1;}.navbar-inner:before,.navbar-inner:after{display:table;content:"";line-height:0;}
+.navbar-inner:after{clear:both;}
+.navbar .container{width:auto;}
+.nav-collapse.collapse{height:auto;overflow:visible;}
+.navbar .brand{float:left;display:block;padding:15px 20px 15px;margin-left:-20px;font-size:20px;font-weight:200;color:#ffffff;text-shadow:0 1px 0 #080808;}.navbar .brand:hover{text-decoration:none;}
+.navbar-text{margin-bottom:0;line-height:50px;color:#ffffff;}
+.navbar-link{color:#ffffff;}.navbar-link:hover{color:#bbbbbb;}
+.navbar .divider-vertical{height:50px;margin:0 9px;border-left:1px solid #080808;border-right:1px solid #080808;}
+.navbar .btn,.navbar .btn-group{margin-top:10px;}
+.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0;}
+.navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";line-height:0;}
+.navbar-form:after{clear:both;}
+.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:10px;}
+.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0;}
+.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;}
+.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap;}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0;}
+.navbar-search{position:relative;float:left;margin-top:10px;margin-bottom:0;}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:"Open Sans",Calibri,Candara,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
+.navbar-static-top{position:static;margin-bottom:0;}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0;}
+.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px;}
+.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0;}
+.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
+.navbar-fixed-top{top:0;}
+.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,.1);box-shadow:0 1px 10px rgba(0,0,0,.1);}
+.navbar-fixed-bottom{bottom:0;}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,.1);box-shadow:0 -1px 10px rgba(0,0,0,.1);}
+.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
+.navbar .nav.pull-right{float:right;margin-right:0;}
+.navbar .nav>li{float:left;}
+.navbar .nav>li>a{float:none;padding:15px 15px 15px;color:#ffffff;text-decoration:none;text-shadow:0 1px 0 #080808;}
+.navbar .nav .dropdown-toggle .caret{margin-top:8px;}
+.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:rgba(0, 0, 0, 0.05);color:#bbbbbb;text-decoration:none;}
+.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#ffffff;text-decoration:none;background-color:transparent;-webkit-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);-moz-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);}
+.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#000000;background-image:-moz-linear-gradient(top, #000000, #000000);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#000000), to(#000000));background-image:-webkit-linear-gradient(top, #000000, #000000);background-image:-o-linear-gradient(top, #000000, #000000);background-image:linear-gradient(to bottom, #000000, #000000);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff000000', endColorstr='#ff000000', GradientType=0);border-color:#000000 #000000 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#000000;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#ffffff;background-color:#000000;*background-color:#000000;}
+.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#000000 \9;}
+.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);}
+.btn-navbar .icon-bar+.icon-bar{margin-top:3px;}
+.navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
+.navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
+.navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0, 0, 0, 0.2);border-bottom:0;bottom:-7px;top:auto;}
+.navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #ffffff;border-bottom:0;bottom:-6px;top:auto;}
+.navbar .nav li.dropdown>a:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:transparent;color:#ffffff;}
+.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{left:auto;right:0;}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{left:auto;right:12px;}
+.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{left:auto;right:13px;}
+.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
+.navbar-inverse .navbar-inner{background-color:#007fff;background-image:-moz-linear-gradient(top, #007fff, #007fff);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#007fff), to(#007fff));background-image:-webkit-linear-gradient(top, #007fff, #007fff);background-image:-o-linear-gradient(top, #007fff, #007fff);background-image:linear-gradient(to bottom, #007fff, #007fff);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff007fff', endColorstr='#ff007fff', GradientType=0);border-color:transparent;}
+.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#ffffff;}
+.navbar-inverse .brand{color:#ffffff;}
+.navbar-inverse .navbar-text{color:#ffffff;}
+.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:rgba(0, 0, 0, 0.05);color:#ffffff;}
+.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#ffffff;background-color:#007fff;}
+.navbar-inverse .navbar-link{color:#ffffff;}.navbar-inverse .navbar-link:hover{color:#ffffff;}
+.navbar-inverse .divider-vertical{border-left-color:#007fff;border-right-color:#007fff;}
+.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#007fff;color:#ffffff;}
+.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
+.navbar-inverse .navbar-search .search-query{color:#ffffff;background-color:#80bfff;border-color:#007fff;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none;}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#999999;}
+.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#999999;}
+.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#999999;}
+.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#999999;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
+.navbar-inverse .btn-navbar{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0072e6;background-image:-moz-linear-gradient(top, #0072e6, #0072e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0072e6), to(#0072e6));background-image:-webkit-linear-gradient(top, #0072e6, #0072e6);background-image:-o-linear-gradient(top, #0072e6, #0072e6);background-image:linear-gradient(to bottom, #0072e6, #0072e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0072e6', endColorstr='#ff0072e6', GradientType=0);border-color:#0072e6 #0072e6 #004c99;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#0072e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#ffffff;background-color:#0072e6;*background-color:#0066cc;}
+.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#0059b3 \9;}
+.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}.breadcrumb>li{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 0 #ffffff;}.breadcrumb>li>.divider{padding:0 5px;color:#ccc;}
+.breadcrumb>.active{color:#dfdfdf;}
+.pagination{margin:20px 0;}
+.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
+.pagination ul>li{display:inline;}
+.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#dfdfdf;border:1px solid transparent;border-left-width:0;}
+.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#007fff;}
+.pagination ul>.active>a,.pagination ul>.active>span{color:#dfdfdf;cursor:default;}
+.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#dfdfdf;background-color:transparent;cursor:default;}
+.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.pagination-centered{text-align:center;}
+.pagination-right{text-align:right;}
+.pagination-large ul>li>a,.pagination-large ul>li>span{padding:22px 30px;font-size:17.5px;}
+.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-top-left-radius:0px;-moz-border-radius-topleft:0px;border-top-left-radius:0px;-webkit-border-bottom-left-radius:0px;-moz-border-radius-bottomleft:0px;border-bottom-left-radius:0px;}
+.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:0px;-moz-border-radius-topright:0px;border-top-right-radius:0px;-webkit-border-bottom-right-radius:0px;-moz-border-radius-bottomright:0px;border-bottom-right-radius:0px;}
+.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px;}
+.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:2px 6px;font-size:10.5px;}
+.pager{margin:20px 0;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";line-height:0;}
+.pager:after{clear:both;}
+.pager li{display:inline;}
+.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
+.pager li>a:hover{text-decoration:none;background-color:#f5f5f5;}
+.pager .next>a,.pager .next>span{float:right;}
+.pager .previous>a,.pager .previous>span{float:left;}
+.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#dfdfdf;background-color:#fff;cursor:default;}
+.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
+.modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);}
+.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:none;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
+.modal.fade.in{top:10%;}
+.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;}
+.modal-header h3{margin:0;line-height:30px;}
+.modal-body{position:relative;overflow-y:auto;max-height:400px;padding:15px;}
+.modal-form{margin-bottom:0;}
+.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";line-height:0;}
+.modal-footer:after{clear:both;}
+.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0;}
+.modal-footer .btn-group .btn+.btn{margin-left:-1px;}
+.modal-footer .btn-block+.btn-block{margin-left:0;}
+.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
+.tooltip.top{margin-top:-3px;}
+.tooltip.right{margin-left:3px;}
+.tooltip.bottom{margin-top:3px;}
+.tooltip.left{margin-left:-3px;}
+.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;}
+.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;}
+.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;}
+.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;}
+.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;}
+.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;background-color:#ff7518;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);white-space:normal;}.popover.top{margin-top:-10px;}
+.popover.right{margin-left:10px;}
+.popover.bottom{margin-top:10px;}
+.popover.left{margin-left:-10px;}
+.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#ff7518;border-bottom:1px solid #fe6600;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}
+.popover-content{padding:9px 14px;}
+.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid;}
+.popover .arrow{border-width:16px;}
+.popover .arrow:after{border-width:15px;content:"";}
+.popover.top .arrow{left:50%;margin-left:-16px;border-bottom-width:0;border-top-color:#999;border-top-color:transparent;bottom:-16px;}.popover.top .arrow:after{bottom:1px;margin-left:-15px;border-bottom-width:0;border-top-color:#ff7518;}
+.popover.right .arrow{top:50%;left:-16px;margin-top:-16px;border-left-width:0;border-right-color:#999;border-right-color:transparent;}.popover.right .arrow:after{left:1px;bottom:-15px;border-left-width:0;border-right-color:#ff7518;}
+.popover.bottom .arrow{left:50%;margin-left:-16px;border-top-width:0;border-bottom-color:#999;border-bottom-color:transparent;top:-16px;}.popover.bottom .arrow:after{top:1px;margin-left:-15px;border-top-width:0;border-bottom-color:#ff7518;}
+.popover.left .arrow{top:50%;right:-16px;margin-top:-16px;border-right-width:0;border-left-color:#999;border-left-color:transparent;}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#ff7518;bottom:-15px;}
+.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";line-height:0;}
+.thumbnails:after{clear:both;}
+.row-fluid .thumbnails{margin-left:0;}
+.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px;}
+.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;}
+a.thumbnail:hover{border-color:#007fff;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
+.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;}
+.thumbnail .caption{padding:9px;color:#bbbbbb;}
+.media,.media-body{overflow:hidden;*overflow:visible;zoom:1;}
+.media,.media .media{margin-top:15px;}
+.media:first-child{margin-top:0;}
+.media-object{display:block;}
+.media-heading{margin:0 0 5px;}
+.media .pull-left{margin-right:10px;}
+.media .pull-right{margin-left:10px;}
+.media-list{margin-left:0;list-style:none;}
+.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#ffffff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#dfdfdf;}
+.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
+.badge{padding-left:9px;padding-right:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}
+.label:empty,.badge:empty{display:none;}
+a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}
+.label-important,.badge-important{background-color:#ffffff;}
+.label-important[href],.badge-important[href]{background-color:#e6e6e6;}
+.label-warning,.badge-warning{background-color:#ff7518;}
+.label-warning[href],.badge-warning[href]{background-color:#e45c00;}
+.label-success,.badge-success{background-color:#ffffff;}
+.label-success[href],.badge-success[href]{background-color:#e6e6e6;}
+.label-info,.badge-info{background-color:#ffffff;}
+.label-info[href],.badge-info[href]{background-color:#e6e6e6;}
+.label-inverse,.badge-inverse{background-color:#999999;}
+.label-inverse[href],.badge-inverse[href]{background-color:#808080;}
+.btn .label,.btn .badge{position:relative;top:-1px;}
+.btn-mini .label,.btn-mini .badge{top:0;}
+@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-o-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(to bottom, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.progress .bar{width:0%;height:100%;color:#ffffff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(to bottom, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
+.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);}
+.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
+.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
+.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);}
+.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
+.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);}
+.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
+.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);}
+.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
+.progress-warning .bar,.progress .bar-warning{background-color:#ff9046;background-image:-moz-linear-gradient(top, #ffa365, #ff7518);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffa365), to(#ff7518));background-image:-webkit-linear-gradient(top, #ffa365, #ff7518);background-image:-o-linear-gradient(top, #ffa365, #ff7518);background-image:linear-gradient(to bottom, #ffa365, #ff7518);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffa365', endColorstr='#ffff7518', GradientType=0);}
+.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#ffa365;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
+.accordion{margin-bottom:20px;}
+.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:0px;-moz-border-radius:0px;border-radius:0px;}
+.accordion-heading{border-bottom:0;}
+.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
+.accordion-toggle{cursor:pointer;}
+.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
+.carousel{position:relative;margin-bottom:20px;line-height:1;}
+.carousel-inner{overflow:hidden;width:100%;position:relative;}
+.carousel-inner>.item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}
+.carousel-inner>.item>img{display:block;line-height:1;}
+.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block;}
+.carousel-inner>.active{left:0;}
+.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%;}
+.carousel-inner>.next{left:100%;}
+.carousel-inner>.prev{left:-100%;}
+.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0;}
+.carousel-inner>.active.left{left:-100%;}
+.carousel-inner>.active.right{left:100%;}
+.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#080808;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;}
+.carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);}
+.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#999999;background:rgba(0, 0, 0, 0.75);}
+.carousel-caption h4,.carousel-caption p{color:#ffffff;line-height:20px;}
+.carousel-caption h4{margin:0 0 5px;}
+.carousel-caption p{margin-bottom:0;}
+.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eeeeee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px;}
+.hero-unit li{line-height:30px;}
+.pull-right{float:right;}
+.pull-left{float:left;}
+.hide{display:none;}
+.show{display:block;}
+.invisible{visibility:hidden;}
+.affix{position:fixed;}
+body{font-weight:300;}
+h1{font-size:50px;}
+h2,h3{font-size:26px;}
+h4{font-size:14px;}
+h5,h6{font-size:11px;}
+blockquote{padding:10px 15px;background-color:#eeeeee;border-left-color:#bbbbbb;}blockquote.pull-right{padding:10px 15px;border-right-color:#bbbbbb;}
+blockquote small{color:#bbbbbb;}
+.muted{color:#bbbbbb;}
+.navbar .navbar-inner{background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.navbar .brand:hover{color:#bbbbbb;}
+.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;background-color:rgba(0, 0, 0, 0.05);}
+.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#ffffff;}.navbar .nav li.dropdown.open>.dropdown-toggle:hover,.navbar .nav li.dropdown.active>.dropdown-toggle:hover,.navbar .nav li.dropdown.open.active>.dropdown-toggle:hover{color:#eeeeee;}
+.navbar .navbar-search .search-query{line-height:normal;}
+.navbar-inverse .brand,.navbar-inverse .nav>li>a{text-shadow:none;}
+.navbar-inverse .brand:hover,.navbar-inverse .nav>.active>a,.navbar-inverse .nav>.active>a:hover,.navbar-inverse .nav>.active>a:focus{background-color:rgba(0, 0, 0, 0.05);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;color:#ffffff;}
+.navbar-inverse .navbar-search .search-query{color:#080808;}
+div.subnav{background-color:#dfdfdf;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}div.subnav .nav{background-color:transparent;}
+div.subnav .nav>li>a{border-color:transparent;}
+div.subnav .nav>.active>a,div.subnav .nav>.active>a:hover{border-color:transparent;background-color:#000000;color:#ffffff;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+div.subnav-fixed{top:50px;}
+.nav .open .dropdown-toggle,.nav >li.dropdown.open.active>a:hover{color:#007fff;}
+.nav-tabs >li>a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.nav-tabs.nav-stacked >li>a:hover{background-color:#007fff;color:#ffffff;}
+.nav-tabs.nav-stacked >.active>a,.nav-tabs.nav-stacked >.active>a:hover{background-color:#ffffff;color:#bbbbbb;}
+.nav-tabs.nav-stacked >li:first-child>a,.nav-tabs.nav-stacked >li:last-child>a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.nav-pills >li>a{background-color:#dfdfdf;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;color:#000000;}.nav-pills >li>a:hover{background-color:#000000;color:#ffffff;}
+.nav-pills >.disabled>a,.nav-pills >.disabled>a:hover{background-color:#eeeeee;color:#999999;}
+.nav-list >li>a{color:#080808;}.nav-list >li>a:hover{background-color:#007fff;color:#ffffff;text-shadow:none;}
+.nav-list .nav-header{color:#080808;}
+.nav-list .divider{background-color:#bbbbbb;border-bottom:none;}
+.pagination ul{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.pagination ul >li>a,.pagination ul >li>span{margin-right:6px;color:#080808;}.pagination ul >li>a:hover,.pagination ul >li>span:hover{background-color:#080808;color:#ffffff;}
+.pagination ul >li:last-child>a,.pagination ul >li:last-child>span{margin-right:0;}
+.pagination ul >.active>a,.pagination ul >.active>span{color:#ffffff;}
+.pagination ul >.disabled>span,.pagination ul >.disabled>a,.pagination ul >.disabled>a:hover{background-color:#eeeeee;color:#999999;}
+.pager li>a,.pager li>span{background-color:#dfdfdf;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;color:#080808;}.pager li>a:hover,.pager li>span:hover{background-color:#080808;color:#ffffff;}
+.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{background-color:#eeeeee;color:#999999;}
+.breadcrumb{background-color:#dfdfdf;}.breadcrumb li{text-shadow:none;}
+.breadcrumb .divider,.breadcrumb .active{color:#080808;text-shadow:none;}
+.btn{padding:5px 12px;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;text-shadow:none;}.btn.disabled{box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);}
+.btn-large{padding:22px 30px;}
+.btn-small{padding:2px 10px;}
+.btn-mini{padding:2px 6px;}
+.btn-group >.btn:first-child,.btn-group >.btn:last-child,.btn-group >.dropdown-toggle{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.btn-group >.btn+.dropdown-toggle{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.table tbody tr.success td{color:#ffffff;}
+.table tbody tr.error td{color:#ffffff;}
+.table tbody tr.info td{color:#ffffff;}
+.table-bordered{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child,.table-bordered tfoot:last-child tr:last-child td:first-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"]{color:#080808;}
+.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#ff7518;}
+.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#ff7518;color:#080808;}
+.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#ff0039;}
+.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#ff0039;color:#080808;}
+.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#3fb618;}
+.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#3fb618;color:#080808;}
+legend{border-bottom:none;color:#080808;}
+.form-actions{border-top:none;background-color:#eeeeee;}
+.dropdown-menu{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
+.alert{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;text-shadow:none;}.alert-heading,.alert h1,.alert h2,.alert h3,.alert h4,.alert h5,.alert h6{color:#ffffff;}
+.label{min-width:80px;min-height:80px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;font-weight:300;text-shadow:none;}.label-success{background-color:#3fb618;}
+.label-important{background-color:#ff0039;}
+.label-info{background-color:#9954bb;}
+.label-inverse{background-color:#000000;}
+.badge{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;font-weight:300;text-shadow:none;}.badge-success{background-color:#3fb618;}
+.badge-important{background-color:#ff0039;}
+.badge-info{background-color:#9954bb;}
+.badge-inverse{background-color:#000000;}
+.hero-unit{border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+.well{border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
+[class^="icon-"],[class*=" icon-"]{margin:0 2px;vertical-align:-2px;}
+a.thumbnail{background-color:#dfdfdf;}a.thumbnail:hover{background-color:#bbbbbb;border-color:transparent;}
+.progress{height:6px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;background-color:#eeeeee;background-image:none;}.progress .bar{background-color:#007fff;background-image:none;}
+.progress-info{background-color:#9954bb;}
+.progress-success{background-color:#3fb618;}
+.progress-warning{background-color:#ff7518;}
+.progress-danger{background-color:#ff0039;}
+.modal{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.modal-header{border-bottom:none;}
+.modal-footer{border-top:none;background-color:transparent;}
+.popover{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;color:#ffffff;}.popover-title{border-bottom:none;color:#ffffff;}
+.pull-right{float:right;}
+.pull-left{float:left;}
+.hide{display:none;}
+.show{display:block;}
+.invisible{visibility:hidden;}
+.affix{position:fixed;}
diff --git a/doc-src/01-reset-fonts-grids-base.css b/doc-src/01-reset-fonts-grids-base.css
deleted file mode 100644
index 32f5f8bf..00000000
--- a/doc-src/01-reset-fonts-grids-base.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-Copyright (c) 2009, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.net/yui/license.txt
-version: 2.7.0
-*/
-html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}
-body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
diff --git a/doc-src/02-docstyle.css b/doc-src/02-docstyle.css
index 4eb0c101..ed83708a 100644
--- a/doc-src/02-docstyle.css
+++ b/doc-src/02-docstyle.css
@@ -1,137 +1,16 @@
-
-a {
- color: #3F8ED8;
- text-decoration: none;
-}
-
-
-#hd.doc {
- -x-system-font:none;
- font-family: Helvetica,Arial,Tahoma,Verdana,Sans-Serif;
- color: #444444;
- margin: 0;
- margin-bottom: 1em;
-}
-
-#hd.doc h1 {
- letter-spacing: 3px;
- font-size: 2.5em;
- margin: 0.3em 0;
- font-weight: normal;
-}
-
-#nav {
- float: right;
-}
-
-
-#bd {
- font: 16px/21px "HelveticaNeue","Helvetica Neue",Helvetica,Arial,sans-serif;
- line-height: 1.5;
- color: #444444;
-}
-
-#bd h1, #bd h2, #bd h3 {
- font-family: "Georgia","Times New Roman",Helvetica,Arial,sans-serif;
- font-weight: normal;
- color: #181818;
-}
-
-#bd h1 {
- font-size: 1.9em;
- border-bottom: 2px solid #ff7033;
- margin-top: 5px;
- margin-bottom: 5px;
-}
-
-#bd h2 {
- font-size: 1.4em;
- border-bottom: 1px solid #cccccc;
- margin-top: 5px;
- margin-bottom: 5px;
-}
-
-
-#bd h3 {
- margin-bottom: 0px;
-}
-
-#bd p {
- margin: 1em 0;
- margin-top: 0.5em;
-}
-
-/* Keyboard shortcuts */
-#bd em {
- font-weight: bold;
- color: #00A700;
- font-style: normal;
-}
-
-#ft.doc {
- color: #aaa;
- border-top: 1px solid #aaa;
- clear: both;
- margin-top: 2em;
- font-size: 0.8em;
- letter-spacing: 0.5px;
-}
-
-.faq .question {
- font-size: 1.1em;
- font-weight: bold;
-}
-
-pre {
- font-size: 0.9em;
- line-height: 1.4;
- padding: 10px;
- background-color: #dddddd;
- margin: 1em 0;
-}
-
.terminal {
color: #c0c0c0;
font-size: 1em;
background: #000000;
}
-.docindex {
- font-size: 1.3em;
- line-height: 1.3;
- margin-top: 0.1em;
- margin-bottom: 0;
- margin-left: 0px;
-}
-
-.docindex li {
- list-style-position: inside;
- margin-left: 0;
-}
-.docindex ul {
- margin-left: 2em;
- margin-top: 0.1em;
- margin-bottom: 0.1em;
+pre {
+ margin-top: 10px;
+ color: #333;
}
-li a {
- text-decoration: none;
-}
-.highlight {
- font-size: 14px;
-}
-.example_legend{
- line-height: 1;
- font-size: 12px;
-}
-.example pre {
- margin: 0;
-}
-
-.kvtable th {
- text-align: left;
- white-space: nowrap;
+.tablenum {
+ font-weight: bold;
}
-
diff --git a/doc-src/_explicit.graffle/data.plist b/doc-src/_explicit.graffle/data.plist
new file mode 100644
index 00000000..bc5ef104
--- /dev/null
+++ b/doc-src/_explicit.graffle/data.plist
@@ -0,0 +1,572 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGraffle.MacAppStore</string>
+ <string>139.16</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2013-01-02 19:31:53 +0000</string>
+ <key>Creator</key>
+ <string>Aldo Cortesi</string>
+ <key>DisplayScale</key>
+ <string>1.000 cm = 1.000 cm</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4074</integer>
+ <key>Points</key>
+ <array>
+ <string>{300.4483540852865, 420.70833897590637}</string>
+ <string>{344.88497416178387, 420.70833897590654}</string>
+ <string>{362.21830749511713, 420.04167230923986}</string>
+ <string>{413.55166625976557, 419.70833905537921}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4070</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896692911783873, 420.66667453447985}</string>
+ <string>{129.33331298828122, 420.66667453448002}</string>
+ <string>{146.66664632161454, 420.00000786781334}</string>
+ <string>{198.00000508626297, 419.66667461395269}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{326.00000000000023, 391.39999198913591}, {62, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4063</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 2: Forwarded \
+Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{110, 403.39997863769622}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4061</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 1: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4026</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Server}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4025</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Client}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4004</integer>
+ <key>ImageID</key>
+ <integer>6</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4023</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.463735</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 mitmproxy}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>134</integer>
+ <key>ImageID</key>
+ <integer>3</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>7</integer>
+ <key>ImageLinkBack</key>
+ <array>
+ <dict/>
+ <dict/>
+ </array>
+ <key>ImageList</key>
+ <array>
+ <string>image6.tiff</string>
+ <string>image3.icns</string>
+ </array>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2013-01-03 02:27:49 +0000</string>
+ <key>Modifier</key>
+ <string>Aldo Cortesi</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{595.19998741149902, 841.79998779296875}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{300, 236}, {974, 874}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{0, 202}, {550, 469.33333333333337}}</string>
+ <key>Zoom</key>
+ <real>1.5</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>1.5</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/doc-src/_explicit.graffle/image3.icns b/doc-src/_explicit.graffle/image3.icns
new file mode 100644
index 00000000..964df4b8
--- /dev/null
+++ b/doc-src/_explicit.graffle/image3.icns
Binary files differ
diff --git a/doc-src/_explicit.graffle/image6.tiff b/doc-src/_explicit.graffle/image6.tiff
new file mode 100644
index 00000000..bd6ed534
--- /dev/null
+++ b/doc-src/_explicit.graffle/image6.tiff
Binary files differ
diff --git a/doc-src/_explicit_https.graffle/data.plist b/doc-src/_explicit_https.graffle/data.plist
new file mode 100644
index 00000000..306630a0
--- /dev/null
+++ b/doc-src/_explicit_https.graffle/data.plist
@@ -0,0 +1,1054 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGraffle.MacAppStore</string>
+ <string>139.16</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2013-01-02 19:31:53 +0000</string>
+ <key>Creator</key>
+ <string>Aldo Cortesi</string>
+ <key>DisplayScale</key>
+ <string>1.000 cm = 1.000 cm</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4075</integer>
+ <key>Points</key>
+ <array>
+ <string>{299.94835408528644, 473.66668184598285}</string>
+ <string>{344.38497416178376, 473.66668184598302}</string>
+ <string>{361.71830749511713, 473.00001517931634}</string>
+ <string>{413.05166625976557, 472.66668192545569}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4074</integer>
+ <key>Points</key>
+ <array>
+ <string>{300.4483540852865, 420.70833897590637}</string>
+ <string>{344.88497416178387, 420.70833897590654}</string>
+ <string>{362.21830749511713, 420.04167230923986}</string>
+ <string>{413.55166625976557, 419.70833905537921}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>FilledArrow</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4073</integer>
+ <key>Points</key>
+ <array>
+ <string>{300.44835408528655, 367.66666611035561}</string>
+ <string>{344.88497416178393, 367.66666611035578}</string>
+ <string>{362.21830749511719, 366.99999944368909}</string>
+ <string>{413.55166625976568, 366.66666618982845}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4072</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896697998046875, 526.66670727729809}</string>
+ <string>{129.33331807454422, 526.6667072772982}</string>
+ <string>{146.66665140787754, 526.00004061063157}</string>
+ <string>{198.00001017252598, 525.66670735677087}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4071</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896687825520942, 472.91668446858688}</string>
+ <string>{197.99999491373694, 472.66668319702148}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>FilledArrow</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4070</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896692911783873, 420.66667453447985}</string>
+ <string>{129.33331298828122, 420.66667453448002}</string>
+ <string>{146.66664632161454, 420.00000786781334}</string>
+ <string>{198.00000508626297, 419.66667461395269}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{316.49998792012531, 326.66665395100904}, {65, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4069</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 4: Initiate SSL \
+handshake \
+with SNI}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{317.00000000000006, 456.66707356770831}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4067</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 8: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.187746683756515, 509.33333333333331}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4066</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 7: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.1877466837567, 441.50006103515642}, {76, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4065</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 6: Complete SSL\
+handshake}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{316.99998982747411, 403.66686820983904}, {64, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4063</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 5: CN &amp; SANs}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.187741597493542, 380.00018183390387}, {65, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4061</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 3: Initiate SSL \
+handshake \
+with SNI}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.187745571136503, 338.66666666666669}, {84, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4060</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 2: 200 Connection \
+Established}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.187741915384976, 283.66659164428717}, {64, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4058</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 1: CONNECT \
+request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4041</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896692911783944, 366.91666793823208}</string>
+ <string>{198, 366.66666666666669}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>FilledArrow</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>31</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896687825520857, 314.66666126251221}</string>
+ <string>{129.33330790201822, 314.66666126251238}</string>
+ <string>{146.66664123535153, 313.99999459584569}</string>
+ <string>{198, 313.66666134198505}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4026</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Server}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4025</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Client}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4004</integer>
+ <key>ImageID</key>
+ <integer>6</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4023</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.463735</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 mitmproxy}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>134</integer>
+ <key>ImageID</key>
+ <integer>3</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>7</integer>
+ <key>ImageLinkBack</key>
+ <array>
+ <dict/>
+ <dict/>
+ </array>
+ <key>ImageList</key>
+ <array>
+ <string>image6.tiff</string>
+ <string>image3.icns</string>
+ </array>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2013-01-03 02:14:45 +0000</string>
+ <key>Modifier</key>
+ <string>Aldo Cortesi</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{595.19998741149902, 841.79998779296875}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{271, 336}, {974, 874}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{0, 202}, {550, 469.33333333333337}}</string>
+ <key>Zoom</key>
+ <real>1.5</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>1.5</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/doc-src/_explicit_https.graffle/image3.icns b/doc-src/_explicit_https.graffle/image3.icns
new file mode 100644
index 00000000..964df4b8
--- /dev/null
+++ b/doc-src/_explicit_https.graffle/image3.icns
Binary files differ
diff --git a/doc-src/_explicit_https.graffle/image6.tiff b/doc-src/_explicit_https.graffle/image6.tiff
new file mode 100644
index 00000000..bd6ed534
--- /dev/null
+++ b/doc-src/_explicit_https.graffle/image6.tiff
Binary files differ
diff --git a/doc-src/_layout.html b/doc-src/_layout.html
index d7637194..d9ff6be1 100644
--- a/doc-src/_layout.html
+++ b/doc-src/_layout.html
@@ -1,30 +1,80 @@
-<div id="doc">
- <div style="" id="hd" class="doc">
- <!--(block nav)-->
- <div id="nav">
- <!--(block pb)-->
- <a href="@!urlTo(previous)!@">prev</a>
- <!--(end)-->
- <!--(block nb)-->
- <a href="@!urlTo(next)!@">next</a>
- <!--(end)-->
- $!pb if previous else "prev"!$ |
- <a href="@!urlTo('/index.html')!@">index</a> |
- $!nb if next else "next"!$
- </div>
- <!--(end)-->
- $!nav if this.title!="docs" else ""!$
- <h1><a href="@!urlTo("/index.html")!@">mitmproxy 0.9 docs</a></h1>
+<div class="navbar">
+ <div class="navbar-inner">
+ <div class="container-fluid">
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </a>
+ <a class="brand" href="@!urlTo("/index.html")!@">mitmproxy 0.9 docs</a>
+ </div><!--/.nav-collapse -->
</div>
- <div id="bd">
- <div id="yui-main">
- <div style="" class="yui-b">
- $!title if this.title!="docs" else ""!$
- $!body!$
- </div>
- </div>
+ </div>
+</div>
+
+<div class="container-fluid">
+ <div class="row-fluid">
+ <div class="span3">
+ <div class="well sidebar-nav">
+ <ul class="nav nav-list">
+ $!nav("index.html", this, state)!$
+ $!nav("install.html", this, state)!$
+ $!nav("howmitmproxy.html", this, state)!$
+ $!nav("faq.html", this, state)!$
+
+ <li class="nav-header">Tools</li>
+ $!nav("mitmproxy.html", this, state)!$
+ $!nav("mitmdump.html", this, state)!$
+
+ <li class="nav-header">Features</li>
+ $!nav("anticache.html", this, state)!$
+ $!nav("clientreplay.html", this, state)!$
+ $!nav("filters.html", this, state)!$
+ $!nav("proxyauth.html", this, state)!$
+ $!nav("replacements.html", this, state)!$
+ $!nav("serverreplay.html", this, state)!$
+ $!nav("setheaders.html", this, state)!$
+ $!nav("sticky.html", this, state)!$
+ $!nav("reverseproxy.html", this, state)!$
+ $!nav("upstreamcerts.html", this, state)!$
+
+ <li class="nav-header">SSL interception</li>
+ $!nav("ssl.html", this, state)!$
+ $!nav("certinstall/firefox.html", this, state)!$
+ $!nav("certinstall/osx.html", this, state)!$
+ $!nav("certinstall/windows7.html", this, state)!$
+ $!nav("certinstall/ios.html", this, state)!$
+ $!nav("certinstall/android.html", this, state)!$
+
+ <li class="nav-header">Transparent Proxying</li>
+ $!nav("transparent.html", this, state)!$
+ $!nav("transparent/linux.html", this, state)!$
+ $!nav("transparent/osx.html", this, state)!$
+
+ <li class="nav-header">Tutorials</li>
+ $!nav("tutorials/30second.html", this, state)!$
+ $!nav("tutorials/gamecenter.html", this, state)!$
+
+ <li class="nav-header">Scripting mitmproxy</li>
+ $!nav("scripting/inlinescripts.html", this, state)!$
+ $!nav("scripting/libmproxy.html", this, state)!$
+ </ul>
+ </div>
</div>
- <div style="" id="ft" class="doc">
- <p>@!copyright!@</p>
+
+ <div class="span9">
+ <div class="page-header">
+ <h1>@!this.title!@</h1>
+ </div>
+ $!body!$
</div>
-</div>
+
+ </div><!--/row-->
+
+ <hr>
+
+ <footer>
+ <p>@!copyright!@</p>
+ </footer>
+
+</div><!--/.fluid-container-->
diff --git a/doc-src/_transparent.graffle/data.plist b/doc-src/_transparent.graffle/data.plist
new file mode 100644
index 00000000..722b4a44
--- /dev/null
+++ b/doc-src/_transparent.graffle/data.plist
@@ -0,0 +1,771 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGraffle.MacAppStore</string>
+ <string>139.16</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2013-01-02 19:31:53 +0000</string>
+ <key>Creator</key>
+ <string>Aldo Cortesi</string>
+ <key>DisplayScale</key>
+ <string>1.000 cm = 1.000 cm</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{101.18773396809897, 358.41662979125977}, {62, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4079</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 2: Redirection}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{102.18775939941409, 405.16666666666663}, {78, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4078</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 3: HTTP Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ControlPoints</key>
+ <array>
+ <string>{-29.333333333333343, 15.666671991348267}</string>
+ <string>{-14, -7.3333333333333712}</string>
+ </array>
+ <key>ID</key>
+ <integer>37</integer>
+ <key>Points</key>
+ <array>
+ <string>{196.99999491373691, 331.83332316080725}</string>
+ <string>{198.00000508626303, 402.49998982747394}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Bezier</key>
+ <true/>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34387397766082, 289.3333333333328}, {84, 52.666667938232422}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4076</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.547829</string>
+ <key>g</key>
+ <string>1</string>
+ <key>r</key>
+ <string>0.790866</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 router}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4075</integer>
+ <key>Points</key>
+ <array>
+ <string>{304.061024983724, 422.16667167345679}</string>
+ <string>{348.49764506022132, 422.16667167345696}</string>
+ <string>{365.83097839355469, 421.50000500679027}</string>
+ <string>{417.16433715820312, 421.16667175292963}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{321.11267089843761, 405.16706339518225}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4067</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 4: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{101.18773682912195, 295.66660690307623}, {62, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4058</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 1: Connection}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4041</integer>
+ <key>Points</key>
+ <array>
+ <string>{85.896713256836037, 421.41666793823208}</string>
+ <string>{199.00002034505209, 421.16666666666669}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>31</integer>
+ <key>Points</key>
+ <array>
+ <string>{84.896687825520857, 314.66666126251221}</string>
+ <string>{129.33330790201822, 314.66666126251238}</string>
+ <string>{146.66664123535153, 313.99999459584569}</string>
+ <string>{198, 313.66666134198505}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4026</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Server}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4025</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Client}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4004</integer>
+ <key>ImageID</key>
+ <integer>6</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4023</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.463735</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 mitmproxy}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>134</integer>
+ <key>ImageID</key>
+ <integer>3</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>7</integer>
+ <key>ImageLinkBack</key>
+ <array>
+ <dict/>
+ <dict/>
+ </array>
+ <key>ImageList</key>
+ <array>
+ <string>image6.tiff</string>
+ <string>image3.icns</string>
+ </array>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2013-01-03 04:13:10 +0000</string>
+ <key>Modifier</key>
+ <string>Aldo Cortesi</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{595.19998741149902, 841.79998779296875}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{295, 141}, {974, 874}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{0, 208}, {550, 469.33333333333337}}</string>
+ <key>Zoom</key>
+ <real>1.5</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>1.5</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/doc-src/_transparent.graffle/image3.icns b/doc-src/_transparent.graffle/image3.icns
new file mode 100644
index 00000000..964df4b8
--- /dev/null
+++ b/doc-src/_transparent.graffle/image3.icns
Binary files differ
diff --git a/doc-src/_transparent.graffle/image6.tiff b/doc-src/_transparent.graffle/image6.tiff
new file mode 100644
index 00000000..bd6ed534
--- /dev/null
+++ b/doc-src/_transparent.graffle/image6.tiff
Binary files differ
diff --git a/doc-src/_transparent_https.graffle/data.plist b/doc-src/_transparent_https.graffle/data.plist
new file mode 100644
index 00000000..9c1395d7
--- /dev/null
+++ b/doc-src/_transparent_https.graffle/data.plist
@@ -0,0 +1,1096 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGraffle.MacAppStore</string>
+ <string>139.16</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2013-01-02 19:31:53 +0000</string>
+ <key>Creator</key>
+ <string>Aldo Cortesi</string>
+ <key>DisplayScale</key>
+ <string>1.000 cm = 1.000 cm</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4075</integer>
+ <key>Points</key>
+ <array>
+ <string>{299.99999999999994, 470.90565482775372}</string>
+ <string>{344.43662007649726, 470.90565482775389}</string>
+ <string>{361.76995340983063, 470.23898816108721}</string>
+ <string>{413.10331217447907, 469.90565490722656}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4074</integer>
+ <key>Points</key>
+ <array>
+ <string>{300.5, 417.94731195767724}</string>
+ <string>{344.93662007649738, 417.94731195767741}</string>
+ <string>{362.26995340983063, 417.28064529101073}</string>
+ <string>{413.60331217447907, 416.94731203715008}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>FilledArrow</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4073</integer>
+ <key>Points</key>
+ <array>
+ <string>{300.50000000000006, 364.90563909212648}</string>
+ <string>{344.93662007649743, 364.90563909212665}</string>
+ <string>{362.26995340983069, 364.23897242545996}</string>
+ <string>{413.60331217447919, 363.90563917159932}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{316.55163383483881, 323.90562693277991}, {65, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4069</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 4: Initiate SSL \
+handshake \
+with SNI}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{317.05164591471356, 453.90604654947919}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4067</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 8: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{317.05163574218761, 400.90584119160991}, {64, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4063</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 5: CN &amp; SANs}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4072</integer>
+ <key>Points</key>
+ <array>
+ <string>{85.333343505859332, 525.3331921100596}</string>
+ <string>{129.7699635823565, 525.3331921100596}</string>
+ <string>{147.10329691568987, 524.66652544339308}</string>
+ <string>{198.4366556803383, 524.33319218953238}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4071</integer>
+ <key>Points</key>
+ <array>
+ <string>{85.3333333333334, 471.58316930134964}</string>
+ <string>{198.43664042154924, 471.33316802978419}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>0</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>FilledArrow</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>4070</integer>
+ <key>Points</key>
+ <array>
+ <string>{85.33333841959633, 419.33315936724267}</string>
+ <string>{129.76995849609349, 419.33315936724279}</string>
+ <string>{147.10329182942687, 418.66649270057616}</string>
+ <string>{198.4366505940753, 418.33315944671557}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{97.957725524902315, 508.66666666666663}, {49, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4066</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 7: Request}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.624392191569157, 440.16654586791918}, {76, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4065</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 6: Complete SSL\
+handshake}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.624387105305999, 377.33333333333331}, {65, 36}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4061</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 3: Initiate SSL \
+handshake \
+with SNI}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{94.624387105305971, 344.58320871988946}, {62, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4079</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 2: Redirection}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ControlPoints</key>
+ <array>
+ <string>{-29.333333333333343, 15.666671991348267}</string>
+ <string>{-14, -7.3333333333333712}</string>
+ </array>
+ <key>ID</key>
+ <integer>37</integer>
+ <key>Points</key>
+ <array>
+ <string>{197.43664042154938, 317.99990208943694}</string>
+ <string>{198.4366505940755, 388.66656875610363}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>Bezier</key>
+ <true/>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>LineType</key>
+ <integer>1</integer>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34387397766082, 289.3333333333328}, {84, 52.666667938232422}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4076</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.547829</string>
+ <key>g</key>
+ <string>1</string>
+ <key>r</key>
+ <string>0.790866</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 router}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{97.957725842793792, 284.99970499674527}, {62, 12}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>4058</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs20 \cf0 1: Connection}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>ID</key>
+ <integer>31</integer>
+ <key>Points</key>
+ <array>
+ <string>{85.333333333333329, 300.8332401911419}</string>
+ <string>{129.76995340983069, 300.83324019114207}</string>
+ <string>{147.10328674316401, 300.16657352447538}</string>
+ <string>{198.43664550781247, 299.83324027061474}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4026</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Server}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>ID</key>
+ <integer>4025</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Client}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4004</integer>
+ <key>ImageID</key>
+ <integer>6</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>4023</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.463735</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red37\green17\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 mitmproxy}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>ID</key>
+ <integer>134</integer>
+ <key>ImageID</key>
+ <integer>3</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>7</integer>
+ <key>ImageLinkBack</key>
+ <array>
+ <dict/>
+ <dict/>
+ </array>
+ <key>ImageList</key>
+ <array>
+ <string>image6.tiff</string>
+ <string>image3.icns</string>
+ </array>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2013-01-03 04:16:32 +0000</string>
+ <key>Modifier</key>
+ <string>Aldo Cortesi</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{595.19998741149902, 841.79998779296875}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{869, 248}, {974, 874}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{0, 208}, {550, 469.33333333333337}}</string>
+ <key>Zoom</key>
+ <real>1.5</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>1.5</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/doc-src/_transparent_https.graffle/image3.icns b/doc-src/_transparent_https.graffle/image3.icns
new file mode 100644
index 00000000..964df4b8
--- /dev/null
+++ b/doc-src/_transparent_https.graffle/image3.icns
Binary files differ
diff --git a/doc-src/_transparent_https.graffle/image6.tiff b/doc-src/_transparent_https.graffle/image6.tiff
new file mode 100644
index 00000000..bd6ed534
--- /dev/null
+++ b/doc-src/_transparent_https.graffle/image6.tiff
Binary files differ
diff --git a/doc-src/admin.html b/doc-src/admin.html
deleted file mode 100644
index b89cd8bc..00000000
--- a/doc-src/admin.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-Please send any comments, suggestions and bug reports to <a href="mailto:$!docMaintainerEmail!$">$!docMaintainerEmail!$</a>.
-
-__mitmproxy__ is licensed under Version 3 of the Gnu General Public License,
-the full text of which can be found in the LICENSE file in the source
-distribution.
-
diff --git a/doc-src/anticache.html b/doc-src/anticache.html
deleted file mode 100644
index 79f0683d..00000000
--- a/doc-src/anticache.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-- command-line: _--anticache_
-- mitmproxy shortcut: _o_, then _a_
-
-When the __anticache__ option is passed to mitmproxy, it removes headers
-(__if-none-match__ and __if-modified-since__) that might elicit a
-304-not-modified response from the server. This is useful when you want to make
-sure you capture an HTTP exchange in its totality, and during [client
-replay](@!urlTo("clientreplay.html")!@).
-
diff --git a/doc-src/certinstall/android-proxydroidinstall.png b/doc-src/certinstall/android-proxydroidinstall.png
deleted file mode 100644
index f84c9eef..00000000
--- a/doc-src/certinstall/android-proxydroidinstall.png
+++ /dev/null
Binary files differ
diff --git a/doc-src/certinstall/android-proxydroidsettings.png b/doc-src/certinstall/android-proxydroidsettings.png
deleted file mode 100644
index 70a73d2d..00000000
--- a/doc-src/certinstall/android-proxydroidsettings.png
+++ /dev/null
Binary files differ
diff --git a/doc-src/certinstall/android.html b/doc-src/certinstall/android.html
index 3f57c39e..852938ce 100644
--- a/doc-src/certinstall/android.html
+++ b/doc-src/certinstall/android.html
@@ -4,9 +4,9 @@ embarrasment](http://code.google.com/p/android/issues/detail?id=1273). It's
scarcely credible, but Android didn't have a global proxy setting at all until
quite recently, and it's still not supported on many common Android versions.
In the meantime the app ecosystem has grown used to life without this basic
-necessity, and many apps merrily ignore it even if it's there. The upshot is
-that in many cases the only way to make interception work on Android is to do
-it without relying on the proxy settings.
+necessity, and many apps merrily ignore it even if it's there. This situation
+is improving, but in many circumstances using [transparent
+mode](@!urlTo("transparent.html")!@) is mandatory for testing Android apps.
We used an Asus Transformer Prime TF201 with Android 4.0.3 in the examples
below - your device may differ, but the broad process should be similar.
@@ -16,7 +16,7 @@ Installing the mitmproxy certificate
====================================
The first step is to install mitmproxy's interception certificate on the
-Android device. In your ~/.mitmproxy directory, there should be a file called
+Android device. In your ~/.mitmproxy directory, there is a file called
__mitmproxy-ca-cert.cer__ - we need to transfer this file to
__/sdcard/Downloads__ on the Android device. If this file doesn't exist for
you, your certs were generated with an older version of mitmproxy - just copy
@@ -51,53 +51,3 @@ settings, you're just about done - simply configure the settings to point at
mitmproxy. If not, proceed to the next step...
-Working around Android's proxy shortcomings
-===========================================
-
-In response to Android's proxy situation, a number of apps have been created to
-duct-tape proxy support onto the OS. These tools work by running a rudimentary
-local proxy on the device, and forwarding all traffic destined for HTTP/S ports
-to it using iptables. Since the proxy is running locally, it can detect what
-the final IP address of the redirected traffic would have been. The local proxy
-then connects to a user-configured upstream proxy, and initiates a proxy
-CONNECT request to the destination IP.
-
-Now, if the configured upstream proxy is mitmproxy, we have a slight problem.
-Proxy requests from the Android device in this scheme will specify only the
-destination IP address, __not__ the destination domain. Mitmproxy needs the
-target domain to generate a valid interception certificate. The solution is
-mitmproxy's [upstream certificate](@!urlTo("upstreamcerts.html")!@) option.
-When this is active, mitmproxy makes a connection to the upstream server to
-obtain the certificate Common Name and Subject Alternative Names.
-
-Adding all this together, we can achieve reliable Android interception with
-only a few more minutes of setup. The instructions below show how to set up an
-Android device with
-[ProxyDroid](https://play.google.com/store/apps/details?id=org.proxydroid) (the
-local "duct-tape" proxy implementation) to achieve interception.
-
-Install ProxyDroid
-------------------
-
-First, root your device - this is required to install ProxyDroid. Then install
-ProxyDroid from the Google Play store:
-
-<img src="android-proxydroidinstall.png"/>
-
-You will be prompted for super-user access, which you must allow. Next, enter
-the ProxyDroid settings, and change the proxy settings to point to your
-mitmproxy instance. When you're done, it should look something like this:
-
-<img src="android-proxydroidsettings.png"/>
-
-In this case, our mitmproxy instance is at the host __maru.otago.ac.nz__,
-running on port __8080__.
-
-When you start mitmproxy, make sure that the upstream certificate option is set
-(use the _--upstream-cert_ command-line option, or enable it interactively
-using the _o_ shortcut):
-
-<pre class="terminal">
-mitmproxy --upstream-cert
-</pre>
-
diff --git a/doc-src/explicit.png b/doc-src/explicit.png
new file mode 100644
index 00000000..c9ba26a7
--- /dev/null
+++ b/doc-src/explicit.png
Binary files differ
diff --git a/doc-src/explicit_https.png b/doc-src/explicit_https.png
new file mode 100644
index 00000000..1f1ca023
--- /dev/null
+++ b/doc-src/explicit_https.png
Binary files differ
diff --git a/doc-src/features/anticache.html b/doc-src/features/anticache.html
new file mode 100644
index 00000000..f42903e8
--- /dev/null
+++ b/doc-src/features/anticache.html
@@ -0,0 +1,18 @@
+
+When the __anticache__ option is passed to mitmproxy, it removes headers
+(__if-none-match__ and __if-modified-since__) that might elicit a
+304-not-modified response from the server. This is useful when you want to make
+sure you capture an HTTP exchange in its totality. It's also often used during
+[client replay](@!urlTo("clientreplay.html")!@), when you want to make sure the
+server responds with complete data.
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th> <td>--anticache</td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>o</b> then <b>a</b></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/clientreplay.html b/doc-src/features/clientreplay.html
index d4b1c3ff..6638d078 100644
--- a/doc-src/clientreplay.html
+++ b/doc-src/features/clientreplay.html
@@ -1,7 +1,4 @@
-- command-line: _-c path_
-- mitmproxy shortcut: _c_
-
Client-side replay does what it says on the tin: you provide a previously saved
HTTP conversation, and mitmproxy replays the client requests one by one. Note
that mitmproxy serializes the requests, waiting for a response from the server
@@ -9,6 +6,17 @@ before starting the next request. This might differ from the recorded
conversation, where requests may have been made concurrently.
You may want to use client-side replay in conjunction with the
-[anticache](@!urlTo("anticache.html")!@) option.
+[anticache](@!urlTo("anticache.html")!@) option, to make sure the server
+responds with complete data.
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th> <td>-c path</td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>c</b></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/filters.html b/doc-src/features/filters.html
index 2424c6f8..c7f0f78b 100644
--- a/doc-src/filters.html
+++ b/doc-src/features/filters.html
@@ -2,13 +2,15 @@
Many commands in __mitmproxy__ and __mitmdump__ take a filter expression.
Filter expressions consist of the following operators:
-<table>
+<table class="table">
+ <tbody>
<!--(for i in filt_help)-->
<tr>
<td class="filt_cmd">@!i[0]!@</td>
<td class="filt_help">@!i[1]!@</td>
</tr>
<!--(end)-->
+ </tbody>
</table>
- Regexes are Python-style
diff --git a/doc-src/features/index.py b/doc-src/features/index.py
new file mode 100644
index 00000000..f7efc23a
--- /dev/null
+++ b/doc-src/features/index.py
@@ -0,0 +1,14 @@
+from countershape import Page
+
+pages = [
+ Page("anticache.html", "Anticache"),
+ Page("clientreplay.html", "Client-side replay"),
+ Page("filters.html", "Filter expressions"),
+ Page("setheaders.html", "Set Headers"),
+ Page("serverreplay.html", "Server-side replay"),
+ Page("sticky.html", "Sticky cookies and auth"),
+ Page("proxyauth.html", "Proxy Authentication"),
+ Page("replacements.html", "Replacements"),
+ Page("reverseproxy.html", "Reverse proxy mode"),
+ Page("upstreamcerts.html", "Upstream Certs"),
+]
diff --git a/doc-src/features/proxyauth.html b/doc-src/features/proxyauth.html
new file mode 100644
index 00000000..0618ee68
--- /dev/null
+++ b/doc-src/features/proxyauth.html
@@ -0,0 +1,25 @@
+
+
+Asks the user for authentication before they are permitted to use the proxy.
+Authentication headers are stripped from the flows, so they are not passed to
+upstream servers. For now, only HTTP Basic authentication is supported.
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th>
+ <td>
+ <ul>
+ <li>--nonanonymous</li>
+
+ <li>--singleuser USER</li>
+
+ <li>--htpasswd PATH</li>
+ </ul>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+
+
diff --git a/doc-src/replacements.html b/doc-src/features/replacements.html
index 986e773a..c10fe2c3 100644
--- a/doc-src/replacements.html
+++ b/doc-src/features/replacements.html
@@ -1,6 +1,3 @@
-- command-line: _--replace_, _--replace-from-file_
-- mitmproxy shortcut: _R_
-
Mitmproxy lets you specify an arbitrary number of patterns that define text
replacements within flows. Each pattern has 3 components: a filter that defines
which flows a replacement applies to, a regular expression that defines what
@@ -59,3 +56,19 @@ The _R_ shortcut key in mitmproxy lets you add and edit replacement hooks using
a built-in editor. The context-sensitive help (_h_) has complete usage
information.
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th>
+ <td>
+ <ul>
+ <li>--replace</li>
+ <li>--replace-from-file</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>R</b></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/reverseproxy.html b/doc-src/features/reverseproxy.html
index 4160b5c6..524df083 100644
--- a/doc-src/reverseproxy.html
+++ b/doc-src/features/reverseproxy.html
@@ -1,8 +1,17 @@
-- command-line: _-P_ http[s]://hostname[:port]
-- mitmproxy shortcut: _P_
-
In reverse proxy mode, mitmproxy acts as a standard HTTP server and forwards
all requests to the specified upstream server. Note that the displayed URL for
flows in this mode will use the value of the __Host__ header field from the
request, not the reverse proxy server.
+
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th> <td>-P http[s]://hostname[:port]</td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>P</b></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/serverreplay.html b/doc-src/features/serverreplay.html
index 1282be06..1282be06 100644
--- a/doc-src/serverreplay.html
+++ b/doc-src/features/serverreplay.html
diff --git a/doc-src/features/setheaders.html b/doc-src/features/setheaders.html
new file mode 100644
index 00000000..b74525df
--- /dev/null
+++ b/doc-src/features/setheaders.html
@@ -0,0 +1,18 @@
+
+This feature lets you specify a set of headers to be added to requests or
+responses, based on a filter pattern. You can specify these either on the
+command-line, or through an interactive editor in mitmproxy.
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th>
+ <td>
+ --setheader PATTERN
+ </td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>H</b></td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/sticky.html b/doc-src/features/sticky.html
index 6208f658..1b79f922 100644
--- a/doc-src/sticky.html
+++ b/doc-src/features/sticky.html
@@ -1,10 +1,6 @@
## Sticky cookies
-- command-line: _-t_ (sticky cookies on all requests)
-- command-line: _-T filt_ (sticky cookies on requests matching filt)
-- mitmproxy shortcut: _t_
-
When the sticky cookie option is set, __mitmproxy__ will add the cookie most
recently set by the server to any cookie-less request. Consider a service that
sets a cookie to track the session after authentication. Using sticky cookies,
@@ -20,15 +16,47 @@ replay](@!urlTo("clientreplay.html")!@) - you can record the authentication
process once, and simply replay it on startup every time you need to interact
with the secured resources.
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th>
+ <td>
+ <ul>
+ <li>-t (sticky cookies on all requests)</li>
+ <li>-T FILTER (sticky cookies on requests matching filter</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>t</b></td>
+ </tr>
+ </tbody>
+</table>
-## Sticky auth
-- command-line: _-u_ (sticky auth on all requests)
-- command-line: _-U filt_ (sticky auth on requests matching filt)
-- mitmproxy shortcut: _u_
+## Sticky auth
The sticky auth option is analogous to the sticky cookie option, in that HTTP
__Authorization__ headers are simply replayed to the server once they have been
seen. This is enough to allow you to access a server resource using HTTP Basic
authentication through the proxy. Note that __mitmproxy__ doesn't (yet) support
replay of HTTP Digest authentication.
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th>
+ <td>
+ <ul>
+ <li>-u (sticky auth on all requests)</li>
+ <li>-U FILTER (sticky auth on requests matching filter</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <th>mitmproxy shortcut</th> <td><b>u</b></td>
+ </tr>
+ </tbody>
+</table>
+
+
diff --git a/doc-src/features/upstreamcerts.html b/doc-src/features/upstreamcerts.html
new file mode 100644
index 00000000..8de75ee3
--- /dev/null
+++ b/doc-src/features/upstreamcerts.html
@@ -0,0 +1,21 @@
+When mitmproxy receives a connection destined for an SSL-protected service, it
+freezes the connection before reading its request data, and makes a connection
+to the upstream server to "sniff" the contents of its SSL certificate. The
+information gained - the __Common Name__ and __Subject Alternative Names__ - is
+then used to generate the interception certificate, which is sent to the client
+so the connection can continue.
+
+This rather intricate little dance lets us seamlessly generate correct
+certificates even if the client has specifed only an IP address rather than the
+hostname. It also means that we don't need to sniff additional data to generate
+certs in transparent mode.
+
+Upstream cert sniffing is on by default, and can optionally be turned off.
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th width="20%">command-line</th> <td>--no-upstream-cert</td>
+ </tr>
+ </tbody>
+</table>
diff --git a/doc-src/howmitmproxy.html b/doc-src/howmitmproxy.html
new file mode 100644
index 00000000..6ea723cd
--- /dev/null
+++ b/doc-src/howmitmproxy.html
@@ -0,0 +1,341 @@
+
+TODO:
+
+- Clarify terminology: SSL vs TLS
+
+
+Mitmproxy is an enormously flexible tool. Knowing exactly how the proxying
+process works will help you deploy it more creatively, and let you understand
+its fundamental assumptions and how to work around them. This document explains
+mitmproxy's proxy mechanism by example, starting with the simplest explicit
+proxy configuration, and working up to the most complicated interaction -
+transparent proxying of SSL-protected traffic in the presence of SNI.
+
+
+<div class="page-header">
+ <h1>Explicit HTTP</h1>
+</div>
+
+Configuring the client to use mitmproxy as an explicit proxy is the simplest
+and most reliable way to intercept traffic. The proxy protocol is codified in
+the [HTTP RFC](http://www.ietf.org/rfc/rfc2068.txt), so the behaviour of both
+the client and the server is well defined, and usually reliable. In the
+simplest possible interaction with mitmproxy, a client connects directly to the
+proxy, and makes a request that looks like this:
+
+<pre>GET http://example.com/index.html HTTP/1.1</pre>
+
+This is a proxy GET request - an extended form of the vanilla HTTP GET request
+that includes a schema and host specification, and it includes all the
+information mitmproxy needs to proceed.
+
+<img src="explicit.png"/>
+
+<table class="table">
+ <tbody>
+ <tr>
+
+ <td><b>1</b></td>
+
+ <td>The client connects to the proxy and makes a request.</td>
+
+ </tr>
+
+ <tr>
+
+ <td><b>2</b></td>
+
+ <td>Mitmproxy connects to the upstream server and simply forwards
+ the request on.</td>
+
+ </tr>
+ </tbody>
+</table>
+
+
+<div class="page-header">
+ <h1>Explicit HTTPS</h1>
+</div>
+
+The process for an explicitly proxied HTTPS connection is quite different. The
+client connects to the proxy and makes a request that looks like this:
+
+<pre>CONNECT example.com:443 HTTP/1.1</pre>
+
+A conventional proxy can neither view nor manipulate an SSL-encrypted data
+stream, so a CONNECT request simply asks the proxy to open a pipe between the
+client and server. The proxy here is just a facilitator - it blindly forwards
+data in both directions without knowing anything about the contents. The
+negotiation of the SSL connection happens over this pipe, and the subsequent
+flow of requests and responses are completely opaque to the proxy.
+
+## The MITM in mitmproxy
+
+This is where mitmproxy's fundamental trick comes in to play. The MITM in its
+name stands for Man-In-The-Middle - a reference to the process we use to
+intercept and interfere with these theoretially opaque data streams. The basic
+idea is to pretend to be the server to the client, and pretend to be the client
+to the server. The tricky part is that the Certificate Authority system is
+designed to prevent exactly this attack, by allowing a trusted third-party to
+cryptographically sign a server's SSL certificates to verify that the certs are
+legit. If this signature is from a non-trusted party, a secure client will
+simply drop the connection and refuse to proceed. Despite the many shortcomings
+of the CA system as it exists today, this is usually fatal to attempts to MITM
+an SSL connection for analysis.
+
+Our answer to this conundrum is to become a trusted Certificate Authority
+ourselves. Mitmproxy includes a full CA implementation that generates
+interception certificates on the fly. To get the client to trust these
+certificates, we register mitmproxy as a CA with the device manually.
+
+## Complication 1: What's the remote hostname?
+
+To proceed with this plan, we need to know the domain name to use in the
+interception certificate - the client will verify that the certificate is for
+the domain it's connecting to, and abort if this is not the case. At first
+blush, it seems that the CONNECT request above gives us all we need - in this
+example, both of these values are "example.com". But what if the client had
+initiated the connection as follows:
+
+<pre>CONNECT 10.1.1.1:443 HTTP/1.1</pre>
+
+Using the IP address is perfectly legitimate because it gives us enough
+information to initiate the pipe, even though it doesn't reveal the remote
+hostname.
+
+Mitmproxy has a cunning mechanism that smooths this over - upstream certificate
+sniffing. As soon as we see the CONNECT request, we pause the client part of
+the conversation, and initiate a simultaneous connection to the server. We
+complete the SSL handshake with the server, and inspect the certificates it
+used. Now, we use the Common Name in the upstream SSL certificates to generate
+the dummy certificate for the client. Voila, we have the correct hostname to
+present to the client, even if it was never specified.
+
+
+## Complication 2: Subject Alternate Name
+
+Enter the next complication. Sometimes, the certificate Common Name is not, in
+fact, the hostname that the client is connecting to. This is because of the
+optional Subject Alternate Name field in the SSL certificate that allows an
+arbitrary number of alternate domains to be specified. If the expected domain
+matches any of these, the client wil proceed, even though the domain doesn't
+match the certificate Common Name. The answer here is simple: when extract the
+CN from the upstream cert, we also extract the SANs, and add them to the
+generated dummy certificate.
+
+
+## Complication 3: Server Name Indication
+
+One of the big limitations of conventional SSL is that each certificate
+requires its own IP address. This means that you couldn't do virtual hosting
+where multiple domains with independent certificates share the same IP address.
+In a world with a rapidly shrinking IPv4 address pool this is a problem, and we
+have a solution in the form of the Server Name Indication extension to the SSL
+and TLS protocols. This lets the client specify the remote server name at the
+start of the SSL handshake, which then lets the server select the right
+certificate to complete the process.
+
+SNI breaks our upstream certificate sniffing process, because when we connect
+without using SNI, we get served a default certificate that may have nothing to
+do with the certificate expected by the client. The solution is another tricky
+complication to the client connection process. After the client connects, we
+allow the SSL handshake to continue until just _after_ the SNI value has been
+passed to us. Now we can pause the conversation, and initiate an upstream
+connection using the correct SNI value, which then serves us the correct
+upstream certificate, from which we can extract the expected CN and SANs.
+
+
+## Putting it all together
+
+Lets put all of this together into the complete explicitly proxied HTTPS flow.
+
+<img src="explicit_https.png"/>
+
+<table class="table">
+ <tbody>
+ <tr>
+ <td><b>1</b></td>
+ <td>The client makes a connection to mitmproxy, and issues an HTTP
+ CONNECT request.</td>
+ </tr>
+ <tr>
+ <td><b>2</b></td>
+
+ <td>Mitmproxy responds with a 200 Connection Established, as if it
+ has set up the CONNECT pipe.</td>
+ </tr>
+ <tr>
+ <td><b>3</b></td>
+
+ <td>The client believes it's talking to the remote server, and
+ initiates the SSL connection. It uses SNI to indicate the hostname
+ it is connecting to.</td>
+ </tr>
+
+ <tr>
+ <td><b>4</b></td>
+
+ <td>Mitmproxy connects to the server, and establishes an SSL
+ connection using the SNI hostname indicated by the client.</td>
+
+ </tr>
+ <tr>
+ <td><b>5</b></td>
+
+ <td>The server responds with the matching SSL certificate, which
+ contains the CN and SAN values needed to generate the interception
+ certificate.</td>
+ </tr>
+ <tr>
+ <td><b>6</b></td>
+
+ <td>Mitmproxy generates the interception cert, and continues the
+ client SSL handshake paused in step 3.</td>
+ </tr>
+ <tr>
+ <td><b>7</b></td>
+
+ <td>The client sends the request over the established SSL
+ connection.</td>
+ </tr>
+ <tr>
+ <td><b>7</b></td>
+
+ <td>Mitmproxy passes the request on to the server over the SSL
+ connection initiated in step 4.</td>
+ </tr>
+ </tbody>
+</table>
+
+
+<div class="page-header">
+ <h1>Transparent HTTP</h1>
+</div>
+
+When a transparent proxy is used, the HTTP/S connection is redirected into a
+proxy at the network layer, without any client configuration being required.
+This makes transparent proxying ideal for those situations where you can't
+change client behaviour - proxy-oblivious Android applications being a common
+example.
+
+To achieve this, we need to introduce two extra components. The first new
+component is a router that transparently redirects the TCP connection to the
+proxy. Once the client has initiated the connection, it makes a vanilla HTTP
+request, which might look something like this:
+
+<pre>GET /index.html HTTP/1.1</pre>
+
+Note that this request differs from the explicit proxy variation, in that it
+omits the scheme and hostname. How, then, do we know which upstream host to
+forward the request to? The routing mechanism that has performed the
+redirection keeps track of the original destination. Each different routing
+mechanism has its own ideosyncratic way of exposing this data, so this
+introduces the second component required for working transparent proxying: a
+host module that knows how to retrieve the original destination address from
+the router. Once we have this information, the process is fairly
+straight-forward.
+
+<img src="transparent.png"/>
+
+
+<table class="table">
+ <tbody>
+ <tr>
+ <td><b>1</b></td>
+ <td>The client makes a connection to the server.</td>
+ </tr>
+ <tr>
+ <td><b>2</b></td>
+
+ <td>The router redirects the connection to mitmproxy, which is
+ typically listening on a local port of the same host. Mitmproxy
+ then consults the routing mechanism to establish what the original
+ destination was.</td>
+ </tr>
+ <tr>
+ <td><b>3</b></td>
+
+ <td>Now, we simply read the client's request...</td>
+ </tr>
+
+ <tr>
+ <td><b>4</b></td>
+
+ <td>... and forward it upstream.</td>
+
+ </tr>
+ </tbody>
+</table>
+
+<div class="page-header">
+ <h1>Transparent HTTPS</h1>
+</div>
+
+The process for transparently proxying an HTTPS request is a merger of the
+methods we've outlined for transparently proxying HTTP, and explicitly proxying
+HTTPS. We use the routing mechanism to establish the upstream server address,
+and then proceed as for explit HTTPS connections to establish the CN and SANs,
+and cope with SNI.
+
+<img src="transparent_https.png"/>
+
+
+<table class="table">
+ <tbody>
+ <tr>
+ <td><b>1</b></td>
+ <td>The client makes a connection to the server.</td>
+ </tr>
+ <tr>
+ <td><b>2</b></td>
+
+ <td>The router redirects the connection to mitmproxy, which is
+ typically listening on a local port of the same host. Mitmproxy
+ then consults the routing mechanism to establish what the original
+ destination was.</td>
+ </tr>
+ <tr>
+ <td><b>3</b></td>
+
+ <td>The client believes it's talking to the remote server, and
+ initiates the SSL connection. It uses SNI to indicate the hostname
+ it is connecting to.</td>
+ </tr>
+
+ <tr>
+ <td><b>4</b></td>
+
+ <td>Mitmproxy connects to the server, and establishes an SSL
+ connection using the SNI hostname indicated by the client.</td>
+
+ </tr>
+ <tr>
+ <td><b>5</b></td>
+
+ <td>The server responds with the matching SSL certificate, which
+ contains the CN and SAN values needed to generate the interception
+ certificate.</td>
+ </tr>
+ <tr>
+ <td><b>6</b></td>
+
+ <td>Mitmproxy generates the interception cert, and continues the
+ client SSL handshake paused in step 3.</td>
+ </tr>
+ <tr>
+ <td><b>7</b></td>
+
+ <td>The client sends the request over the established SSL
+ connection.</td>
+ </tr>
+ <tr>
+ <td><b>7</b></td>
+
+ <td>Mitmproxy passes the request on to the server over the SSL
+ connection initiated in step 4.</td>
+ </tr>
+ </tbody>
+</table>
+
+
+
diff --git a/doc-src/index.html b/doc-src/index.html
index 3b6d122d..79687ec6 100644
--- a/doc-src/index.html
+++ b/doc-src/index.html
@@ -1,49 +1,4 @@
-<ul class="docindex">
- <li><a href="@!urlTo("intro.html")!@">Introduction</a></li>
- <li><a href="@!urlTo("install.html")!@">Installation</a></li>
- <li><a href="@!urlTo("mitmproxy.html")!@">mitmproxy</a></li>
- <li><a href="@!urlTo("mitmdump.html")!@">mitmdump</a></li>
- <li>Features
- <ul>
- <li><a href="@!urlTo("clientreplay.html")!@">Client-side replay</a></li>
- <li><a href="@!urlTo("serverreplay.html")!@">Server-side replay</a></li>
- <li><a href="@!urlTo("sticky.html")!@">Sticky cookies and auth</a></li>
- <li><a href="@!urlTo("reverseproxy.html")!@">Reverse proxy mode</a></li>
- <li><a href="@!urlTo("upstreamcerts.html")!@">Upstream Certs</a></li>
- <li><a href="@!urlTo("replacements.html")!@">Replacements</a></li>
- <li><a href="@!urlTo("anticache.html")!@">Anticache</a></li>
- <li><a href="@!urlTo("filters.html")!@">Filter expressions</a></li>
- </ul>
- </li>
- <li>Scripting mitmproxy
- <ul>
- <li><a href="@!urlTo("scripting/inlinescripts.html")!@">Inline Scripts</a></li>
- <li><a href="@!urlTo("scripting/libmproxy.html")!@">libmproxy</a></li>
- </ul>
- </li>
- <li><a href="@!urlTo("ssl.html")!@">Setting up SSL interception</a>
- <ul>
- <li><a href="@!urlTo("certinstall/firefox.html")!@">Firefox</a></li>
- <li><a href="@!urlTo("certinstall/osx.html")!@">OSX</a></li>
- <li><a href="@!urlTo("certinstall/windows7.html")!@">Windows 7</a></li>
- <li><a href="@!urlTo("certinstall/ios.html")!@">iPhone/iPad</a></li>
- <li><a href="@!urlTo("certinstall/android.html")!@">Android</a></li>
- </ul>
- </li>
- <li><a href="@!urlTo("transparent.html")!@">Setting up Transparent Proxying</a>
- <ul>
- <li><a href="@!urlTo("transparent/linux.html")!@">Linux</a></li>
- <li><a href="@!urlTo("transparent/osx.html")!@">OSX</a></li>
- <li><a href="@!urlTo("transparent/osx.html")!@">OpenBSD</a></li>
- </ul>
- </li>
- <li>Tutorials
- <ul>
- <li> <a href="@!urlTo("tutorials/30second.html")!@">Client replay: a 30 second example</a> </li>
- <li> <a href="@!urlTo("tutorials/gamecenter.html")!@">Setting highscores on Apple's GameCenter</a> </li>
- </ul>
- </li>
- <li><a href="@!urlTo("faq.html")!@">FAQ</a></li>
- <li><a href="@!urlTo("admin.html")!@">Administrivia</a></li>
-</ul>
+@!index_contents!@
+
+
diff --git a/doc-src/index.py b/doc-src/index.py
index 27faf602..930037ec 100644
--- a/doc-src/index.py
+++ b/doc-src/index.py
@@ -1,42 +1,29 @@
import os, sys
import countershape
-from countershape import Page, Directory, PythonModule, markup
+from countershape import Page, Directory, PythonModule, markup, model
import countershape.template
sys.path.insert(0, "..")
from libmproxy import filt
MITMPROXY_SRC = "~/git/public/mitmproxy"
-
-if ns.options.website:
- ns.title = countershape.template.Template(None, "<h1>@!this.title!@</h1>")
- this.layout = countershape.Layout("_websitelayout.html")
-else:
- ns.title = countershape.template.Template(None, "<h1>@!this.title!@</h1>")
- this.layout = countershape.Layout("_layout.html")
-
+this.layout = countershape.Layout("_layout.html")
+this.titlePrefix = "mitmproxy 0.9 - "
this.markup = markup.Markdown()
+
ns.docMaintainer = "Aldo Cortesi"
ns.docMaintainerEmail = "aldo@corte.si"
-ns.copyright = u"\u00a9 mitmproxy project, 2012"
-
-ns.index = countershape.widgets.SiblingPageIndex('/index.html', divclass="pageindex")
+ns.copyright = u"\u00a9 mitmproxy project, 2013"
def mpath(p):
p = os.path.join(MITMPROXY_SRC, p)
return os.path.expanduser(p)
-ns.license = file(mpath("LICENSE")).read()
ns.index_contents = file(mpath("README.mkd")).read()
-
-
-top = os.path.abspath(os.getcwd())
def example(s):
d = file(mpath(s)).read()
extemp = """<div class="example">%s<div class="example_legend">(%s)</div></div>"""
return extemp%(countershape.template.Syntax("py")(d), s)
-
-
ns.example = example
filt_help = []
@@ -64,25 +51,27 @@ filt_help.extend(
ns.filt_help = filt_help
+def nav(page, current, state):
+ if current.match(page, False):
+ pre = '<li class="active">'
+ else:
+ pre = "<li>"
+ p = state.application.getPage(page)
+ return pre + '<a href="%s">%s</a></li>'%(model.UrlTo(page), p.title)
+ns.nav = nav
pages = [
- Page("index.html", "docs"),
- Page("intro.html", "Introduction"),
+ Page("index.html", "Introduction"),
Page("install.html", "Installation"),
Page("mitmproxy.html", "mitmproxy"),
Page("mitmdump.html", "mitmdump"),
- Page("clientreplay.html", "Client-side replay"),
- Page("serverreplay.html", "Server-side replay"),
- Page("sticky.html", "Sticky cookies and auth"),
- Page("upstreamcerts.html", "Upstream Certs"),
- Page("replacements.html", "Replacements"),
- Page("reverseproxy.html", "Reverse proxy mode"),
- Page("anticache.html", "Anticache"),
- Page("filters.html", "Filter expressions"),
- Page("ssl.html", "Setting up SSL interception"),
+ Page("howmitmproxy.html", "How mitmproxy works"),
+
+ Page("ssl.html", "Overview"),
Directory("certinstall"),
Directory("scripting"),
Directory("tutorials"),
+ Page("transparent.html", "Overview"),
+ Directory("transparent"),
Page("faq.html", "FAQ"),
- Page("admin.html", "Administrivia")
]
diff --git a/doc-src/install.html b/doc-src/install.html
index 0968cd66..30e2774d 100644
--- a/doc-src/install.html
+++ b/doc-src/install.html
@@ -1,54 +1,49 @@
-## Using Pip
+The preferred way to install mitmproxy - whether you're installing the latest
+release or from source - is to use [pip](http://www.pip-installer.org/). If you
+don't already have pip on your system, you can find installation instructions
+[here](http://www.pip-installer.org/en/latest/installing.html).
-The preferred way to install mitmproxy is to use
-[pip](http://pypi.python.org/pypi/pip). A single command will install the
-latest release of mitmproxy, along with all its dependencies:
-<pre>
-sudo pip install mitmproxy
+## Installing the latest release
+
+A single command will download and install the latest release of mitmproxy,
+along with all its dependencies:
+
+<pre class="terminal">
+pip install mitmproxy
</pre>
-## From Source
+## Installing from source
-- When installing from source, you will need to install the
-[dependencies](@!urlTo("intro.html")!@) by hand.
-- Then run the following command from the base of the source distribution:
+When installing from source, the easiest method is still to use pip. In this
+case run:
-<pre>
-sudo python setup.py install
+<pre class="terminal">
+pip install /path/to/source
</pre>
+Note that if you're installing current git master, you will also have to
+install the current git master of [netlib](http://github.com/cortesi/netlib) by
+hand.
## OSX
+- If you're running a Python interpreter installed with homebrew (or similar),
+you may have to install some dependencies by hand.
- Make sure that XCode is installed from the App Store, and that the
command-line tools have been downloaded (XCode/Preferences/Downloads).
-- Install __pip__ using the following command:
-
-<pre>
-sudo easy_install pip
-</pre>
-
-- Now use __pip__ to set up the dependencies and do the install:
-
-<pre>
-sudo pip install mitmproxy
-</pre>
-
-This procedure may vary if, for instance, you've installed Python from an
-external source like [homebrew](http://mxcl.github.com/homebrew/). In that
-case, the easiest way to proceed is to first install __easy_install__, then
-continue as above.
+- Now use __pip__ to do the installation, as above.
There are a few bits of customization you might want to do to make mitmproxy
-comfortable to use. At the moment, mitmproxy's color scheme is optimized for a
-dark background terminal, so you probably want to change the default. You can
-use the OSX <b>open</b> program to create a simple and effective
-<b>~/.mailcap</b> file to view HTTP bodies:
+comfortable to use on OSX. The default color scheme is optimized for a dark
+background terminal, but you can select a palette for a light terminal
+background with the --palette option. You can use the OSX <b>open</b> program
+to create a simple and effective <b>~/.mailcap</b> file to view request and
+response bodies:
-<pre>
+<pre class="terminal">
application/*; /usr/bin/open -Wn %s
audio/*; /usr/bin/open -Wn %s
image/*; /usr/bin/open -Wn %s
diff --git a/doc-src/intro.html b/doc-src/intro.html
deleted file mode 100644
index 79687ec6..00000000
--- a/doc-src/intro.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-@!index_contents!@
-
-
diff --git a/doc-src/scripting/inlinescripts.html b/doc-src/scripting/inlinescripts.html
index 860ad9b6..7abf743c 100644
--- a/doc-src/scripting/inlinescripts.html
+++ b/doc-src/scripting/inlinescripts.html
@@ -1,4 +1,3 @@
-
__mitmproxy__ has a powerful scripting API that allows you to modify flows
on-the-fly or rewrite previously saved flows locally.
@@ -22,13 +21,13 @@ response itself.
Called once on startup, before any other events.
-###clientconnect(ScriptContext, ClientConnect)
+### clientconnect(ScriptContext, ClientConnect)
Called when a client initiates a connection to the proxy. Note that
a connection can correspond to multiple HTTP requests.
-###request(ScriptContext, Flow)
+### request(ScriptContext, Flow)
Called when a client request has been received. The __Flow__ object is
guaranteed to have a non-None __request__ attribute.
diff --git a/doc-src/transparent.png b/doc-src/transparent.png
new file mode 100644
index 00000000..3994d681
--- /dev/null
+++ b/doc-src/transparent.png
Binary files differ
diff --git a/doc-src/transparent/index.py b/doc-src/transparent/index.py
index fa2a67da..d277d708 100644
--- a/doc-src/transparent/index.py
+++ b/doc-src/transparent/index.py
@@ -3,5 +3,4 @@ from countershape import Page
pages = [
Page("linux.html", "Linux"),
Page("osx.html", "OSX"),
- Page("openbsd.html", "OpenBSD"),
]
diff --git a/doc-src/transparent/openbsd.html b/doc-src/transparent/openbsd.html
deleted file mode 100644
index e69de29b..00000000
--- a/doc-src/transparent/openbsd.html
+++ /dev/null
diff --git a/doc-src/transparent_https.png b/doc-src/transparent_https.png
new file mode 100644
index 00000000..559cddd2
--- /dev/null
+++ b/doc-src/transparent_https.png
Binary files differ
diff --git a/doc-src/upstreamcerts.html b/doc-src/upstreamcerts.html
deleted file mode 100644
index 32a13a9a..00000000
--- a/doc-src/upstreamcerts.html
+++ /dev/null
@@ -1,15 +0,0 @@
-- command-line: _--upstream-cert_
-- mitmproxy shortcut: _o_, then _u_
-
-Normally, mitmproxy uses the target domain specified in a client's proxy
-request to generate an interception certificate. When __upstream-cert__ mode is
-activated a different procedure is followed: a connection is made to the
-specified remote server to retrieve its __Common Name__ and __Subject
-Alternative Names__. This feature is especially useful when the client
-specifies an IP address rather than a host name in the proxy request. If this
-is the case, we can only generate a certificate if we can establish the __CN__
-and __SANs__ from the upstream server.
-
-Note that __upstream-cert__ mode does not work when the remote server relies on
-[Server Name Indication](http://en.wikipedia.org/wiki/Server_Name_Indication).
-Luckily, SNI is still not very widely used.
diff --git a/examples/iframe_injector b/examples/iframe_injector
new file mode 100755
index 00000000..6dd28674
--- /dev/null
+++ b/examples/iframe_injector
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+"""
+ Zap encoding in requests and inject iframe after body tag in html responses.
+ Usage:
+ iframe_injector http://someurl/somefile.html
+"""
+from libmproxy import controller, proxy
+import os
+import sys
+
+
+class InjectingMaster(controller.Master):
+ def __init__(self, server, iframe_url):
+ controller.Master.__init__(self, server)
+ self._iframe_url = iframe_url
+
+ def run(self):
+ try:
+ return controller.Master.run(self)
+ except KeyboardInterrupt:
+ self.shutdown()
+
+ def handle_request(self, msg):
+ if 'Accept-Encoding' in msg.headers:
+ msg.headers["Accept-Encoding"] = 'none'
+ msg._ack()
+
+ def handle_response(self, msg):
+ if msg.content:
+ c = msg.replace('<body>', '<body><iframe src="%s" frameborder="0" height="0" width="0"></iframe>' % self._iframe_url)
+ if c > 0:
+ print 'Iframe injected!'
+ msg._ack()
+
+
+def main(argv):
+ if len(argv) != 2:
+ print "Usage: %s IFRAME_URL" % argv[0]
+ sys.exit(1)
+ iframe_url = argv[1]
+ config = proxy.ProxyConfig(
+ cacert = os.path.expanduser("~/.mitmproxy/mitmproxy-ca.pem")
+ )
+ server = proxy.ProxyServer(config, 8080)
+ print 'Starting proxy...'
+ m = InjectingMaster(server, iframe_url)
+ m.run()
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/libmproxy/authentication.py b/libmproxy/authentication.py
index e5383f5a..500ead6b 100644
--- a/libmproxy/authentication.py
+++ b/libmproxy/authentication.py
@@ -2,35 +2,49 @@ import binascii
import contrib.md5crypt as md5crypt
class NullProxyAuth():
- """ No proxy auth at all (returns empty challange headers) """
- def __init__(self, password_manager=None):
+ """
+ No proxy auth at all (returns empty challange headers)
+ """
+ def __init__(self, password_manager):
self.password_manager = password_manager
self.username = ""
- def authenticate(self, auth_value):
- """ Tests that the specified user is allowed to use the proxy (stub) """
+ def clean(self, headers):
+ """
+ Clean up authentication headers, so they're not passed upstream.
+ """
+ pass
+
+ def authenticate(self, headers):
+ """
+ Tests that the user is allowed to use the proxy
+ """
return True
def auth_challenge_headers(self):
- """ Returns a dictionary containing the headers require to challenge the user """
+ """
+ Returns a dictionary containing the headers require to challenge the user
+ """
return {}
- def get_username(self):
- return self.username
-
class BasicProxyAuth(NullProxyAuth):
-
- def __init__(self, password_manager, realm="mitmproxy"):
+ CHALLENGE_HEADER = 'Proxy-Authenticate'
+ AUTH_HEADER = 'Proxy-Authorization'
+ def __init__(self, password_manager, realm):
NullProxyAuth.__init__(self, password_manager)
- self.realm = "mitmproxy"
+ self.realm = realm
- def authenticate(self, auth_value):
- if (not auth_value) or (not auth_value[0]):
- return False;
+ def clean(self, headers):
+ del headers[self.AUTH_HEADER]
+
+ def authenticate(self, headers):
+ auth_value = headers.get(self.AUTH_HEADER, [])
+ if not auth_value:
+ return False
try:
- scheme, username, password = self.parse_authorization_header(auth_value[0])
- except:
+ scheme, username, password = self.parse_auth_value(auth_value[0])
+ except ValueError:
return False
if scheme.lower()!='basic':
return False
@@ -40,14 +54,26 @@ class BasicProxyAuth(NullProxyAuth):
return True
def auth_challenge_headers(self):
- return {'Proxy-Authenticate':'Basic realm="%s"'%self.realm}
+ return {self.CHALLENGE_HEADER:'Basic realm="%s"'%self.realm}
- def parse_authorization_header(self, auth_value):
+ def unparse_auth_value(self, scheme, username, password):
+ v = binascii.b2a_base64(username + ":" + password)
+ return scheme + " " + v
+
+ def parse_auth_value(self, auth_value):
words = auth_value.split()
+ if len(words) != 2:
+ raise ValueError("Invalid basic auth credential.")
scheme = words[0]
- user = binascii.a2b_base64(words[1])
- username, password = user.split(':')
- return scheme, username, password
+ try:
+ user = binascii.a2b_base64(words[1])
+ except binascii.Error:
+ raise ValueError("Invalid basic auth credential: user:password pair not valid base64: %s"%words[1])
+ parts = user.split(':')
+ if len(parts) != 2:
+ raise ValueError("Invalid basic auth credential: decoded user:password pair not valid: %s"%user)
+ return scheme, parts[0], parts[1]
+
class PasswordManager():
def __init__(self):
@@ -56,8 +82,8 @@ class PasswordManager():
def test(self, username, password_token):
return False
-class PermissivePasswordManager(PasswordManager):
+class PermissivePasswordManager(PasswordManager):
def __init__(self):
PasswordManager.__init__(self)
@@ -66,16 +92,17 @@ class PermissivePasswordManager(PasswordManager):
return True
return False
-class HtpasswdPasswordManager(PasswordManager):
- """ Read usernames and passwords from a file created by Apache htpasswd"""
+class HtpasswdPasswordManager(PasswordManager):
+ """
+ Read usernames and passwords from a file created by Apache htpasswd
+ """
def __init__(self, filehandle):
PasswordManager.__init__(self)
entries = (line.strip().split(':') for line in filehandle)
valid_entries = (entry for entry in entries if len(entry)==2)
self.usernames = {username:token for username,token in valid_entries}
-
def test(self, username, password_token):
if username not in self.usernames:
return False
@@ -84,8 +111,8 @@ class HtpasswdPasswordManager(PasswordManager):
expected = md5crypt.md5crypt(password_token, salt, '$'+magic+'$')
return expected==full_token
-class SingleUserPasswordManager(PasswordManager):
+class SingleUserPasswordManager(PasswordManager):
def __init__(self, username, password):
PasswordManager.__init__(self)
self.username = username
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index db1ebf0d..de70bea8 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -248,11 +248,6 @@ def common_options(parser):
help="Byte size limit of HTTP request and response bodies."\
" Understands k/m/g suffixes, i.e. 3m for 3 megabytes."
)
- parser.add_argument(
- "--cert-wait-time", type=float,
- action="store", dest="cert_wait_time", default=0,
- help="Wait for specified number of seconds after a new cert is generated. This can smooth over small discrepancies between the client and server times."
- )
parser.add_argument(
"--no-upstream-cert", default=False,
@@ -338,46 +333,29 @@ def common_options(parser):
group = parser.add_argument_group(
"Proxy Authentication",
"""
- Specification of which users are allowed to access the proxy and the method used for authenticating them.
- If authscheme is specified, one must specify a list of authorized users and their passwords.
- In case that authscheme is not specified, or set to None, any list of authorized users will be ignored.
- """.strip()
- )
-
- group.add_argument(
- "--authscheme", type=str,
- action="store", dest="authscheme", default=None, choices=["none", "basic"],
- help="""
- Specify the scheme used by the proxy to identify users.
- If not none, requires the specification of a list of authorized users.
- This option is ignored if the proxy is in transparent or reverse mode.
- """.strip()
-
+ Specify which users are allowed to access the proxy and the method
+ used for authenticating them. These options are ignored if the
+ proxy is in transparent or reverse proxy mode.
+ """
)
-
user_specification_group = group.add_mutually_exclusive_group()
-
-
user_specification_group.add_argument(
"--nonanonymous",
action="store_true", dest="auth_nonanonymous",
- help="Allow access to any user as long as a username is specified. Ignores the provided password."
+ help="Allow access to any user long as a credentials are specified."
)
user_specification_group.add_argument(
"--singleuser",
action="store", dest="auth_singleuser", type=str,
- help="Allows access to a single user as specified by the option value. Specify a username and password in the form username:password."
+ metavar="USER",
+ help="Allows access to a a single user, specified in the form username:password."
)
-
user_specification_group.add_argument(
"--htpasswd",
action="store", dest="auth_htpasswd", type=argparse.FileType('r'),
+ metavar="PATH",
help="Allow access to users specified in an Apache htpasswd file."
)
-
-
-
-
proxy.certificate_option_group(parser)
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 9a6b5527..2c4c5513 100755
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -1387,6 +1387,8 @@ class FlowMaster(controller.Master):
self.kill_nonreplay = kill
def stop_server_playback(self):
+ if self.server_playback.exit:
+ self.shutdown()
self.server_playback = None
def do_server_playback(self, flow):
@@ -1420,10 +1422,6 @@ class FlowMaster(controller.Master):
self.shutdown()
self.client_playback.tick(self)
- if self.server_playback:
- if self.server_playback.exit and self.server_playback.count() == 0:
- self.shutdown()
-
return controller.Master.tick(self, q)
def duplicate_flow(self, f):
diff --git a/libmproxy/platform/osx.py b/libmproxy/platform/osx.py
index a66c03ed..dda5d9af 100644
--- a/libmproxy/platform/osx.py
+++ b/libmproxy/platform/osx.py
@@ -1,103 +1,23 @@
-import socket, ctypes
-
-# Python socket module does not have this constant
-DIOCNATLOOK = 23
-PFDEV = "/dev/pf"
-
-
-class PF_STATE_XPORT(ctypes.Union):
- """
- union pf_state_xport {
- u_int16_t port;
- u_int16_t call_id;
- u_int32_t spi;
- };
- """
- _fields_ = [
- ("port", ctypes.c_uint),
- ("call_id", ctypes.c_uint),
- ("spi", ctypes.c_ulong),
- ]
-
-
-class PF_ADDR(ctypes.Union):
- """
- struct pf_addr {
- union {
- struct in_addr v4;
- struct in6_addr v6;
- u_int8_t addr8[16];
- u_int16_t addr16[8];
- u_int32_t addr32[4];
- } pfa;
- }
- """
- _fields_ = [
- ("addr8", ctypes.c_byte * 2),
- ("addr16", ctypes.c_byte * 4),
- ("addr32", ctypes.c_byte * 8),
- ]
-
-
-class PFIOC_NATLOOK(ctypes.Structure):
- """
- struct pfioc_natlook {
- struct pf_addr saddr;
- struct pf_addr daddr;
- struct pf_addr rsaddr;
- struct pf_addr rdaddr;
- #ifndef NO_APPLE_EXTENSIONS
- union pf_state_xport sxport;
- union pf_state_xport dxport;
- union pf_state_xport rsxport;
- union pf_state_xport rdxport;
- sa_family_t af;
- u_int8_t proto;
- u_int8_t proto_variant;
- u_int8_t direction;
- #else
- u_int16_t sport;
- u_int16_t dport;
- u_int16_t rsport;
- u_int16_t rdport;
- sa_family_t af;
- u_int8_t proto;
- u_int8_t direction;
- #endif
- };
- """
- _fields_ = [
- ("saddr", PF_ADDR),
- ("daddr", PF_ADDR),
- ("rsaddr", PF_ADDR),
- ("rdaddr", PF_ADDR),
-
- ("sxport", PF_STATE_XPORT),
- ("dxport", PF_STATE_XPORT),
- ("rsxport", PF_STATE_XPORT),
- ("rdxport", PF_STATE_XPORT),
- ("af", ctypes.c_uint),
- ("proto", ctypes.c_ushort),
- ("proto_variant", ctypes.c_ushort),
- ("direction", ctypes.c_ushort),
- ]
+import subprocess
+import pf
+"""
+ Doing this the "right" way by using DIOCNATLOOK on the pf device turns out
+ to be a pain. Apple has made a number of modifications to the data
+ structures returned, and compiling userspace tools to test and work with
+ this turns out to be a pain in the ass. Parsing pfctl output is short,
+ simple, and works.
+"""
class Resolver:
+ STATECMD = ("sudo", "-n", "/sbin/pfctl", "-s", "state")
def __init__(self):
- self.pfdev = open(PFDEV, "r")
+ pass
def original_addr(self, csock):
- """
- The following sttruct defintions are plucked from the current XNU source, found here:
-
- http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/bsd/net/pfvar.h
-
-
- union pf_state_xport {
- u_int16_t port;
- u_int16_t call_id;
- u_int32_t spi;
- };
- """
- pass
+ peer = csock.getpeername()
+ try:
+ stxt = subprocess.check_output(self.STATECMD, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError:
+ return None
+ return pf.lookup(peer[0], peer[1], stxt)
diff --git a/libmproxy/platform/pf.py b/libmproxy/platform/pf.py
new file mode 100644
index 00000000..062d3311
--- /dev/null
+++ b/libmproxy/platform/pf.py
@@ -0,0 +1,16 @@
+
+def lookup(address, port, s):
+ """
+ Parse the pfctl state output s, to look up the destination host
+ matching the client (address, port).
+
+ Returns an (address, port) tuple, or None.
+ """
+ spec = "%s:%s"%(address, port)
+ for i in s.split("\n"):
+ if "ESTABLISHED:ESTABLISHED" in i and spec in i:
+ s = i.split()
+ if len(s) > 4:
+ s = s[4].split(":")
+ if len(s) == 2:
+ return s[0], int(s[1])
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index 4c57aeb0..cf006f60 100755
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -38,19 +38,19 @@ class Log(controller.Msg):
class ProxyConfig:
- def __init__(self, certfile = None, cacert = None, clientcerts = None, cert_wait_time=0, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
+ def __init__(self, certfile = None, cacert = None, clientcerts = None, no_upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None, certdir = None, authenticator=None):
assert not (reverse_proxy and transparent_proxy)
self.certfile = certfile
self.cacert = cacert
self.clientcerts = clientcerts
- self.certdir = certdir
- self.cert_wait_time = cert_wait_time
self.no_upstream_cert = no_upstream_cert
self.body_size_limit = body_size_limit
self.reverse_proxy = reverse_proxy
self.transparent_proxy = transparent_proxy
self.authenticator = authenticator
+ self.certstore = certutils.CertStore(certdir)
+
class RequestReplayThread(threading.Thread):
def __init__(self, config, flow, masterq):
self.config, self.flow, self.masterq = config, flow, masterq
@@ -247,8 +247,7 @@ class ProxyHandler(tcp.BaseHandler):
raise ProxyError(502, "Unable to get remote cert: %s"%str(v))
sans = cert.altnames
host = cert.cn.decode("utf8").encode("idna")
- ret = certutils.dummy_cert(self.config.certdir, self.config.cacert, host, sans)
- time.sleep(self.config.cert_wait_time)
+ ret = self.config.certstore.get_cert(host, sans, self.config.cacert)
if not ret:
raise ProxyError(502, "mitmproxy: Unable to generate dummy cert.")
return ret
@@ -270,7 +269,10 @@ class ProxyHandler(tcp.BaseHandler):
def read_request(self, client_conn):
self.rfile.reset_timestamps()
if self.config.transparent_proxy:
- host, port = self.config.transparent_proxy["resolver"].original_addr(self.connection)
+ orig = self.config.transparent_proxy["resolver"].original_addr(self.connection)
+ if not orig:
+ raise ProxyError(502, "Transparent mode failure: could not resolve original destination.")
+ host, port = orig
if not self.ssl_established and (port in self.config.transparent_proxy["sslports"]):
scheme = "https"
certfile = self.find_cert(host, port, None)
@@ -311,7 +313,7 @@ class ProxyHandler(tcp.BaseHandler):
line = self.get_line(self.rfile)
if line == "":
return None
- if line.startswith("CONNECT"):
+ if http.parse_init_connect(line):
r = http.parse_init_connect(line)
if not r:
raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
@@ -332,14 +334,15 @@ class ProxyHandler(tcp.BaseHandler):
raise ProxyError(400, str(v))
self.proxy_connect_state = (host, port, httpversion)
line = self.rfile.readline(line)
+
if self.proxy_connect_state:
- host, port, httpversion = self.proxy_connect_state
r = http.parse_init_http(line)
if not r:
raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
method, path, httpversion = r
headers = self.read_headers(authenticate=False)
+ host, port, _ = self.proxy_connect_state
content = http.read_http_body_request(
self.rfile, self.wfile, headers, httpversion, self.config.body_size_limit
)
@@ -348,7 +351,7 @@ class ProxyHandler(tcp.BaseHandler):
r = http.parse_init_proxy(line)
if not r:
raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
- method, scheme, host, port, path, httpversion = http.parse_init_proxy(line)
+ method, scheme, host, port, path, httpversion = r
headers = self.read_headers(authenticate=True)
content = http.read_http_body_request(
self.rfile, self.wfile, headers, httpversion, self.config.body_size_limit
@@ -359,8 +362,15 @@ class ProxyHandler(tcp.BaseHandler):
headers = http.read_headers(self.rfile)
if headers is None:
raise ProxyError(400, "Invalid headers")
- if authenticate and self.config.authenticator and not self.config.authenticator.authenticate(headers.get('Proxy-Authorization', [])):
- raise ProxyError(407, "Proxy Authentication Required", self.config.authenticator.auth_challenge_headers())
+ if authenticate and self.config.authenticator:
+ if self.config.authenticator.authenticate(headers):
+ self.config.authenticator.clean(headers)
+ else:
+ raise ProxyError(
+ 407,
+ "Proxy Authentication Required",
+ self.config.authenticator.auth_challenge_headers()
+ )
return headers
def send_response(self, response):
@@ -405,13 +415,6 @@ class ProxyServer(tcp.TCPServer):
except socket.error, v:
raise ProxyServerError('Error starting proxy server: ' + v.strerror)
self.masterq = None
- if config.certdir:
- self.certdir = config.certdir
- self.remove_certdir = False
- else:
- self.certdir = tempfile.mkdtemp(prefix="mitmproxy")
- config.certdir = self.certdir
- self.remove_certdir = True
self.apps = AppRegistry()
def start_slave(self, klass, masterq):
@@ -430,11 +433,7 @@ class ProxyServer(tcp.TCPServer):
pass
def handle_shutdown(self):
- try:
- if self.remove_certdir:
- shutil.rmtree(self.certdir)
- except OSError:
- pass
+ self.config.certstore.cleanup()
class AppRegistry:
@@ -537,30 +536,24 @@ def process_proxy_options(parser, options):
if not os.path.exists(options.certdir) or not os.path.isdir(options.certdir):
parser.error("Dummy cert directory does not exist or is not a directory: %s"%options.certdir)
- if options.authscheme and (options.authscheme!='none'):
- if not (options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd):
- parser.error("Proxy authentication scheme is specified, but no allowed user list is given.")
- if options.auth_singleuser and len(options.auth_singleuser.split(':'))!=2:
- parser.error("Authorized user is not given in correct format username:password")
- if options.auth_nonanonymous:
- password_manager = authentication.PermissivePasswordManager()
- elif options.auth_singleuser:
+ if (options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd):
+ if options.auth_singleuser:
+ if len(options.auth_singleuser.split(':')) != 2:
+ parser.error("Please specify user in the format username:password")
username, password = options.auth_singleuser.split(':')
password_manager = authentication.SingleUserPasswordManager(username, password)
+ elif options.auth_nonanonymous:
+ password_manager = authentication.PermissivePasswordManager()
elif options.auth_htpasswd:
password_manager = authentication.HtpasswdPasswordManager(options.auth_htpasswd)
- # in the meanwhile, basic auth is the only true authentication scheme we support
- # so just use it
- authenticator = authentication.BasicProxyAuth(password_manager)
+ authenticator = authentication.BasicProxyAuth(password_manager, "mitmproxy")
else:
authenticator = authentication.NullProxyAuth(None)
-
return ProxyConfig(
certfile = options.cert,
cacert = cacert,
clientcerts = options.clientcerts,
- cert_wait_time = options.cert_wait_time,
body_size_limit = body_size_limit,
no_upstream_cert = options.no_upstream_cert,
reverse_proxy = rp,
diff --git a/setup.py b/setup.py
index 6fb25c01..9a5398be 100644
--- a/setup.py
+++ b/setup.py
@@ -93,7 +93,4 @@ setup(
"Topic :: Software Development :: Testing"
],
install_requires=["netlib", "urwid>=1.1", "pyasn1>0.1.2", "pyopenssl>=0.12", "PIL", "lxml"],
- dependency_links=[
- 'https://github.com/cortesi/netlib/tarball/master#egg=netlib-0.1'
- ],
)
diff --git a/test/data/pf01 b/test/data/pf01
new file mode 100644
index 00000000..3139a289
--- /dev/null
+++ b/test/data/pf01
@@ -0,0 +1,4 @@
+No ALTQ support in kernel
+ALTQ related functions disabled
+ALL tcp 127.0.0.1:8080 <- 5.5.5.6:80 <- 192.168.1.111:40001 FIN_WAIT_2:FIN_WAIT_2
+ALL tcp 127.0.0.1:8080 <- 5.5.5.5:80 <- 192.168.1.111:40000 ESTABLISHED:ESTABLISHED
diff --git a/test/test_authentication.py b/test/test_authentication.py
new file mode 100644
index 00000000..f7a5ecd3
--- /dev/null
+++ b/test/test_authentication.py
@@ -0,0 +1,58 @@
+import binascii
+from libmproxy import authentication
+from netlib import odict
+import tutils
+
+
+class TestNullProxyAuth:
+ def test_simple(self):
+ na = authentication.NullProxyAuth(authentication.PermissivePasswordManager())
+ assert not na.auth_challenge_headers()
+ assert na.authenticate("foo")
+ na.clean({})
+
+
+class TestBasicProxyAuth:
+ def test_simple(self):
+ ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test")
+ h = odict.ODictCaseless()
+ assert ba.auth_challenge_headers()
+ assert not ba.authenticate(h)
+
+ def test_parse_auth_value(self):
+ ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test")
+ vals = ("basic", "foo", "bar")
+ assert ba.parse_auth_value(ba.unparse_auth_value(*vals)) == vals
+ tutils.raises(ValueError, ba.parse_auth_value, "")
+ tutils.raises(ValueError, ba.parse_auth_value, "foo bar")
+
+ v = "basic " + binascii.b2a_base64("foo")
+ tutils.raises(ValueError, ba.parse_auth_value, v)
+
+ def test_authenticate_clean(self):
+ ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test")
+
+ hdrs = odict.ODictCaseless()
+ vals = ("basic", "foo", "bar")
+ hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)]
+ assert ba.authenticate(hdrs)
+
+ ba.clean(hdrs)
+ assert not ba.AUTH_HEADER in hdrs
+
+
+ hdrs[ba.AUTH_HEADER] = [""]
+ assert not ba.authenticate(hdrs)
+
+ hdrs[ba.AUTH_HEADER] = ["foo"]
+ assert not ba.authenticate(hdrs)
+
+ vals = ("foo", "foo", "bar")
+ hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)]
+ assert not ba.authenticate(hdrs)
+
+ ba = authentication.BasicProxyAuth(authentication.PasswordManager(), "test")
+ vals = ("basic", "foo", "bar")
+ hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)]
+ assert not ba.authenticate(hdrs)
+
diff --git a/test/test_dump.py b/test/test_dump.py
index 0337bb33..e1241e29 100644
--- a/test/test_dump.py
+++ b/test/test_dump.py
@@ -48,6 +48,15 @@ class TestDumpMaster:
fw.add(t)
f.close()
+ def test_error(self):
+ cs = StringIO()
+ o = dump.Options(verbosity=1)
+ m = dump.DumpMaster(None, o, None, outfile=cs)
+ f = tutils.tflow_err()
+ m.handle_request(f.request)
+ assert m.handle_error(f.error)
+ assert "error" in cs.getvalue()
+
def test_replay(self):
cs = StringIO()
diff --git a/test/test_flow.py b/test/test_flow.py
index 277d2407..2af702ce 100644
--- a/test/test_flow.py
+++ b/test/test_flow.py
@@ -624,6 +624,7 @@ class TestFlowMaster:
fm.handle_error(flow.Error(f.request, "error"))
def test_server_playback(self):
+ controller.should_exit = False
s = flow.State()
f = tutils.tflow()
@@ -641,8 +642,9 @@ class TestFlowMaster:
r = tutils.tflow()
r.request.content = "gibble"
assert not fm.do_server_playback(r)
-
assert fm.do_server_playback(tutils.tflow())
+
+ fm.start_server_playback(pb, False, [], True, False)
q = Queue.Queue()
fm.tick(q)
assert controller.should_exit
@@ -650,6 +652,20 @@ class TestFlowMaster:
fm.stop_server_playback()
assert not fm.server_playback
+ def test_server_playback_kill(self):
+ s = flow.State()
+ f = tutils.tflow()
+ f.response = tutils.tresp(f.request)
+ pb = [f]
+ fm = flow.FlowMaster(None, s)
+ fm.refresh_server_playback = True
+ fm.start_server_playback(pb, True, [], False, False)
+
+ f = tutils.tflow()
+ f.request.host = "nonexistent"
+ fm.process_new_request(f)
+ assert "killed" in f.error.msg
+
def test_stickycookie(self):
s = flow.State()
fm = flow.FlowMaster(None, s)
diff --git a/test/test_platform_pf.py b/test/test_platform_pf.py
new file mode 100644
index 00000000..a2e7c3c1
--- /dev/null
+++ b/test/test_platform_pf.py
@@ -0,0 +1,13 @@
+import tutils
+from libmproxy.platform import pf
+
+
+class TestLookup:
+ def test_simple(self):
+ p = tutils.test_data.path("data/pf01")
+ d = open(p).read()
+ assert pf.lookup("192.168.1.111", 40000, d) == ("5.5.5.5", 80)
+ assert not pf.lookup("192.168.1.112", 40000, d)
+ assert not pf.lookup("192.168.1.111", 40001, d)
+
+
diff --git a/test/tools/getcert b/test/tools/getcert
index 6447ecc7..8fabefb7 100755
--- a/test/tools/getcert
+++ b/test/tools/getcert
@@ -5,5 +5,3 @@ import socket, tempfile, ssl, subprocess
addr = socket.gethostbyname(sys.argv[1])
print ssl.get_server_certificate((addr, 443))
-
-
diff --git a/test/tools/getcn b/test/tools/getcn
deleted file mode 100755
index 212977c3..00000000
--- a/test/tools/getcn
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-import sys
-sys.path.insert(0, "../../")
-from libmproxy import certutils
-
-if len(sys.argv) > 2:
- port = int(sys.argv[2])
-else:
- pport = 443
-
-cn, san = certutils.get_remote_cn(sys.argv[1], port)
-print cn
-if san:
- for i in san:
- print "\t", i
-
-
diff --git a/test/tutils.py b/test/tutils.py
index 0e661a4b..5ce56cb4 100644
--- a/test/tutils.py
+++ b/test/tutils.py
@@ -4,7 +4,7 @@ from contextlib import contextmanager
from libmproxy import proxy, flow, controller, utils
from netlib import certutils
import human_curl as hurl
-import libpathod.test
+import libpathod.test, libpathod.pathoc
def treq(conn=None):
if not conn:
@@ -194,7 +194,6 @@ class ReverseProxTest(ProxTestBase):
return r
-
@contextmanager
def tmpdir(*args, **kwargs):
orig_workdir = os.getcwd()
@@ -245,4 +244,5 @@ def raises(exc, obj, *args, **kwargs):
)
raise AssertionError("No exception raised.")
+
test_data = utils.Data(__name__)