aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.env6
-rwxr-xr-xcheck_coding_style.sh20
-rw-r--r--doc-src/01-bootstrap.min.css9
-rw-r--r--doc-src/01-vendor.css6706
-rw-r--r--doc-src/02-app.css43
-rw-r--r--doc-src/02-docstyle.css20
-rw-r--r--doc-src/_layout.html70
-rw-r--r--doc-src/_nav.html2
-rw-r--r--doc-src/_websitelayout.html42
-rw-r--r--doc-src/dev/architecture.html8
-rw-r--r--doc-src/dev/index.py8
-rw-r--r--doc-src/features/index.py2
-rw-r--r--doc-src/howmitmproxy.html8
-rw-r--r--doc-src/index.py11
-rw-r--r--doc-src/mitmproxy-long.pngbin0 -> 123829 bytes
-rw-r--r--doc-src/mitmproxy.html28
-rw-r--r--doc-src/modes.html20
-rw-r--r--doc-src/tutorials/gamecenter.html6
-rw-r--r--doc-src/tutorials/index.py2
-rw-r--r--doc-src/tutorials/transparent-dhcp.html8
-rw-r--r--examples/add_header.py2
-rw-r--r--examples/change_upstream_proxy.py14
-rw-r--r--examples/dns_spoofing.py8
-rw-r--r--examples/dup_and_replay.py2
-rw-r--r--examples/filt.py14
-rwxr-xr-xexamples/flowbasic3
-rw-r--r--examples/flowwriter.py2
-rw-r--r--examples/har_extractor.py88
-rw-r--r--examples/iframe_injector.py9
-rw-r--r--examples/ignore_websocket.py3
-rwxr-xr-xexamples/mitmproxywrapper.py60
-rw-r--r--examples/modify_form.py5
-rw-r--r--examples/modify_querystring.py2
-rw-r--r--examples/modify_response_body.py7
-rw-r--r--examples/nonblocking.py2
-rw-r--r--examples/proxapp.py2
-rw-r--r--examples/read_dumpfile5
-rw-r--r--examples/redirect_requests.py3
-rw-r--r--examples/stream.py2
-rw-r--r--examples/stream_modify.py4
-rw-r--r--examples/stub.py9
-rw-r--r--examples/upsidedownternet.py3
-rw-r--r--libmproxy/cmdline.py20
-rw-r--r--libmproxy/console/__init__.py29
-rw-r--r--libmproxy/console/common.py6
-rw-r--r--libmproxy/console/contentview.py23
-rw-r--r--libmproxy/console/flowdetailview.py2
-rw-r--r--libmproxy/console/flowlist.py8
-rw-r--r--libmproxy/console/flowview.py101
-rw-r--r--libmproxy/console/grideditor.py23
-rw-r--r--libmproxy/console/help.py25
-rw-r--r--libmproxy/console/options.py1
-rw-r--r--libmproxy/console/palettes.py2
-rw-r--r--libmproxy/console/pathedit.py2
-rw-r--r--libmproxy/console/searchable.py6
-rw-r--r--libmproxy/console/select.py18
-rw-r--r--libmproxy/console/statusbar.py30
-rw-r--r--libmproxy/console/tabs.py5
-rw-r--r--libmproxy/controller.py11
-rw-r--r--libmproxy/dump.py25
-rw-r--r--libmproxy/encoding.py10
-rw-r--r--libmproxy/filt.py80
-rw-r--r--libmproxy/flow.py101
-rw-r--r--libmproxy/main.py2
-rw-r--r--libmproxy/onboarding/app.py13
-rw-r--r--libmproxy/platform/linux.py3
-rw-r--r--libmproxy/platform/osx.py5
-rw-r--r--libmproxy/platform/windows.py78
-rw-r--r--libmproxy/protocol/__init__.py2
-rw-r--r--libmproxy/protocol/handle.py5
-rw-r--r--libmproxy/protocol/http.py101
-rw-r--r--libmproxy/protocol/primitives.py13
-rw-r--r--libmproxy/protocol/tcp.py3
-rw-r--r--libmproxy/proxy/config.py72
-rw-r--r--libmproxy/proxy/connection.py32
-rw-r--r--libmproxy/proxy/primitives.py15
-rw-r--r--libmproxy/proxy/server.py95
-rw-r--r--libmproxy/script.py35
-rw-r--r--libmproxy/tnetstring.py92
-rw-r--r--libmproxy/utils.py29
-rw-r--r--libmproxy/version.py2
-rw-r--r--libmproxy/web/__init__.py9
-rw-r--r--libmproxy/web/app.py9
-rwxr-xr-xmitmdump2
-rwxr-xr-xmitmproxy2
-rw-r--r--release/mitmdump.spec4
-rw-r--r--release/mitmproxy.spec4
-rw-r--r--release/mitmweb.spec4
-rw-r--r--release/release-checklist3
-rw-r--r--setup.cfg9
-rw-r--r--setup.py22
-rw-r--r--test/mock_urwid.py6
-rw-r--r--test/scripts/a.py4
-rw-r--r--test/scripts/all.py8
-rw-r--r--test/scripts/concurrent_decorator.py2
-rw-r--r--test/scripts/concurrent_decorator_err.py3
-rw-r--r--test/scripts/duplicate_flow.py1
-rw-r--r--test/scripts/stream_modify.py2
-rw-r--r--test/test_app.py9
-rw-r--r--test/test_cmdline.py29
-rw-r--r--test/test_console.py6
-rw-r--r--test/test_console_contentview.py163
-rw-r--r--test/test_console_help.py2
-rw-r--r--test/test_controller.py2
-rw-r--r--test/test_dump.py17
-rw-r--r--test/test_encoding.py22
-rw-r--r--test/test_examples.py2
-rw-r--r--test/test_filt.py11
-rw-r--r--test/test_flow.py223
-rw-r--r--test/test_fuzzing.py9
-rw-r--r--test/test_platform_pf.py21
-rw-r--r--test/test_protocol_http.py17
-rw-r--r--test/test_proxy.py35
-rw-r--r--test/test_script.py13
-rw-r--r--test/test_server.py242
-rw-r--r--test/test_utils.py8
-rw-r--r--test/tools/bench.py18
-rw-r--r--test/tools/benchtool.py55
-rwxr-xr-xtest/tools/getcert5
-rw-r--r--test/tools/passive_close.py6
-rw-r--r--test/tservers.py49
-rw-r--r--test/tutils.py49
122 files changed, 8494 insertions, 1006 deletions
diff --git a/.env b/.env
index 7f847e29..97f38452 100644
--- a/.env
+++ b/.env
@@ -1,5 +1,5 @@
-DIR=`dirname $0`
-if [ -z "$VIRTUAL_ENV" ] && [ -f $DIR/../venv.mitmproxy/bin/activate ]; then
+DIR="${0%/*}"
+if [ -z "$VIRTUAL_ENV" ] && [ -f "$DIR/../venv.mitmproxy/bin/activate" ]; then
echo "Activating mitmproxy virtualenv..."
- source $DIR/../venv.mitmproxy/bin/activate
+ source "$DIR/../venv.mitmproxy/bin/activate"
fi
diff --git a/check_coding_style.sh b/check_coding_style.sh
new file mode 100755
index 00000000..5b38e003
--- /dev/null
+++ b/check_coding_style.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+autopep8 -i -r -a -a .
+if [[ -n "$(git status -s)" ]]; then
+ echo "autopep8 yielded the following changes:"
+ git status -s
+ git --no-pager diff
+ exit 1
+fi
+
+autoflake -i -r --remove-all-unused-imports --remove-unused-variables .
+if [[ -n "$(git status -s)" ]]; then
+ echo "autoflake yielded the following changes:"
+ git status -s
+ git --no-pager diff
+ exit 1
+fi
+
+echo "Coding style seems to be ok."
+exit 0
diff --git a/doc-src/01-bootstrap.min.css b/doc-src/01-bootstrap.min.css
deleted file mode 100644
index 2e79d91a..00000000
--- a/doc-src/01-bootstrap.min.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/*!
- * Bootstrap v2.3.1
- *
- * Copyright 2012 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.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:32px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}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{width:auto\9;height:auto;max-width:100%;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"]{cursor:pointer;-webkit-appearance:button}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{*{color:#000!important;text-shadow:none!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:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:16px;line-height:22px;color:#555;background-color:#fff}a{color:#007fff;text-decoration:none}a:hover,a:focus{color:#06c;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;line-height:0;content:""}.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;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:32px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.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;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 11px}.lead{margin-bottom:22px;font-size:24px;font-weight:200;line-height:33px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#dfdfdf}a.muted:hover,a.muted:focus{color:#c6c6c6}.text-warning{color:#fff}a.text-warning:hover,a.text-warning:focus{color:#e6e6e6}.text-error{color:#fff}a.text-error:hover,a.text-error:focus{color:#e6e6e6}.text-info{color:#fff}a.text-info:hover,a.text-info:focus{color:#e6e6e6}.text-success{color:#fff}a.text-success:hover,a.text-success:focus{color:#e6e6e6}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:11px 0;font-family:inherit;font-weight:300;line-height:22px;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:44px}h1{font-size:44px}h2{font-size:36px}h3{font-size:28px}h4{font-size:20px}h5{font-size:16px}h6{font-size:13.6px}h1 small{font-size:28px}h2 small{font-size:20px}h3 small{font-size:16px}h4 small{font-size:16px}.page-header{padding-bottom:10px;margin:44px 0 22px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 11px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:22px}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;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:22px}dt,dd{line-height:22px}dt{font-weight:bold}dd{margin-left:11px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:22px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}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 22px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:20px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:22px;color:#dfdfdf}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;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:22px;font-style:normal;line-height:22px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:14px;color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:10.5px;margin:0 0 11px;font-size:15px;line-height:22px;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:0;-moz-border-radius:0;border-radius:0}pre.prettyprint{margin-bottom:22px}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 22px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:22px;font-size:24px;line-height:44px;color:#999;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:16.5px;color:#dfdfdf}label,input,button,select,textarea{font-size:16px;font-weight:normal;line-height:22px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,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:22px;padding:4px 6px;margin-bottom:11px;font-size:16px;line-height:22px;color:#bbb;vertical-align:middle;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}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:#fff;border:1px solid #bbb;-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,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;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:32px;*margin-top:4px;line-height:32px}select{width:220px;background-color:#fff;border:1px solid #bbb}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;cursor:not-allowed;background-color:#fcfcfc;border-color:#bbb;-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)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#bbb}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#bbb}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#bbb}.radio,.checkbox{min-height:22px;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;line-height:0;content:""}.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:#eee}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:#fff}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#fff}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#fff;-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 #fff;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#fff;background-color:#ff7518;border-color:#fff}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#fff}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#fff}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#fff;-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 #fff;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#fff;background-color:#ff0039;border-color:#fff}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#fff}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#fff}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#fff;-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 #fff;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#fff;background-color:#3fb618;border-color:#fff}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#fff}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#fff}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#fff;-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 #fff;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#fff;background-color:#9954bb;border-color:#fff}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:21px 20px 22px;margin-top:22px;margin-bottom:22px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#7b7b7b}.help-block{display:block;margin-bottom:11px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:11px;font-size:0;white-space:nowrap;vertical-align:middle}.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,.input-append .popover,.input-prepend .popover{font-size:16px}.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;-moz-border-radius:0;border-radius: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:22px;min-width:16px;padding:4px 5px;font-size:16px;font-weight:normal;line-height:22px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;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:0;-moz-border-radius:0;border-radius:0}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.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;-moz-border-radius:0;border-radius: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;-moz-border-radius:0;border-radius: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;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius: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;margin-bottom:0;vertical-align:middle;*zoom:1}.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:11px}legend+.control-group{margin-top:22px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:22px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.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:11px}.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:22px}.table th,.table td{padding:8px;line-height:22px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.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 #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.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,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-topleft:0}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:0;border-top-right-radius:0;-moz-border-radius-topright: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 tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright: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:0;border-top-left-radius:0;-moz-border-radius-topleft:0}.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:0;border-top-right-radius:0;-moz-border-radius-topright:0}.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-top:1px;*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}.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:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>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{width:16px;background-position:-216px -120px}.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{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.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 #000;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:#fff;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:10px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:22px;color:#999;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;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,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;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;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff007fff',endColorstr='#ff0072e6',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#dfdfdf}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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 #000;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;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.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-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#eee;border:1px solid #dcdcdc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-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:0;-moz-border-radius:0;border-radius:0}.well-small{padding:9px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:22px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:16px;line-height:22px;color:#999;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#dfdfdf;*background-color:#c8c8c8;background-image:-moz-linear-gradient(top,#eee,#c8c8c8);background-image:-webkit-gradient(linear,0 0,0 100%,from(#eee),to(#c8c8c8));background-image:-webkit-linear-gradient(top,#eee,#c8c8c8);background-image:-o-linear-gradient(top,#eee,#c8c8c8);background-image:linear-gradient(to bottom,#eee,#c8c8c8);background-repeat:repeat-x;border:1px solid #bbb;*border: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);border-bottom-color:#a2a2a2;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee',endColorstr='#ffc8c8c8',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#999;background-color:#c8c8c8;*background-color:#bbb}.btn:active,.btn.active{background-color:#aeaeae \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#999;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .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,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:22px 30px;font-size:20px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:13.6px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.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:12px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-block{display:block;width:100%;padding-right:0;padding-left: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-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0f82f5;*background-color:#0072e6;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;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);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1a8cff',endColorstr='#ff0072e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#0072e6;*background-color:#06c}.btn-primary:active,.btn-primary.active{background-color:#0059b3 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#fe781e;*background-color:#fe6600;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;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);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff8432',endColorstr='#fffe6600',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#fe6600;*background-color:#e45c00}.btn-warning:active,.btn-warning.active{background-color:#cb5200 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#f50f43;*background-color:#e60033;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;border-color:#e60033 #e60033 #902;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff1a4d',endColorstr='#ffe60033',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#e60033;*background-color:#cc002e}.btn-danger:active,.btn-danger.active{background-color:#b30028 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#41bb19;*background-color:#379f15;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;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);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff47cd1b',endColorstr='#ff379f15',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#379f15;*background-color:#2f8912}.btn-success:active,.btn-success.active{background-color:#28720f \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#9b59bb;*background-color:#8d46b0;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;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);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa466c2',endColorstr='#ff8d46b0',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#8d46b0;*background-color:#7e3f9d}.btn-info:active,.btn-info.active{background-color:#6f378b \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#080808;*background-color:#000;background-image:-moz-linear-gradient(top,#0d0d0d,#000);background-image:-webkit-gradient(linear,0 0,0 100%,from(#0d0d0d),to(#000));background-image:-webkit-linear-gradient(top,#0d0d0d,#000);background-image:-o-linear-gradient(top,#0d0d0d,#000);background-image:linear-gradient(to bottom,#0d0d0d,#000);background-repeat:repeat-x;border-color:#000 #000 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0d0d0d',endColorstr='#ff000000',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#000;*background-color:#000}.btn-inverse:active,.btn-inverse.active{background-color:#000 \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{color:#007fff;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#06c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#999;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:11px;margin-bottom:11px;font-size:0}.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:16px}.btn-group>.btn-mini{font-size:12px}.btn-group>.btn-small{font-size:13.6px}.btn-group>.btn-large{font-size:20px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}.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-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,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:#000}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.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:#fff;border-bottom-color:#fff}.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-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.alert{padding:8px 35px 8px 14px;margin-bottom:22px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#ff7518;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.alert,.alert h4{color:#fff}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:22px}.alert-success{color:#fff;background-color:#3fb618;border-color:transparent}.alert-success h4{color:#fff}.alert-danger,.alert-error{color:#fff;background-color:#ff0039;border-color:transparent}.alert-danger h4,.alert-error h4{color:#fff}.alert-info{color:#fff;background-color:#9954bb;border-color:transparent}.alert-info h4{color:#fff}.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-bottom:22px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.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:22px;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-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-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,.nav-list>.active>a:focus{color:#fff;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:10px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.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:22px;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,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#bbb;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.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,.nav-pills>.active>a:focus{color:#fff;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;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.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{margin-top:6px;border-top-color:#007fff;border-bottom-color:#007fff}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#06c;border-bottom-color:#06c}.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:#bbb;border-bottom-color:#bbb}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#dfdfdf;border-color:#dfdfdf}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#dfdfdf}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.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,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{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,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.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,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#dfdfdf}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:22px;overflow:visible}.navbar-inner{min-height:50px;padding-right:20px;padding-left: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;border:1px solid transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808',endColorstr='#ff080808',GradientType=0);*zoom:1;-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)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:14px 20px 14px;margin-left:-20px;font-size:20px;font-weight:200;color:#fff;text-shadow:0 1px 0 #080808}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:50px;color:#fff}.navbar-link{color:#fff}.navbar-link:hover,.navbar-link:focus{color:#fff}.navbar .divider-vertical{height:50px;margin:0 9px;border-right:1px solid #080808;border-left:1px solid #080808}.navbar .btn,.navbar .btn-group{margin-top:10px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.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{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,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-right:0;padding-left: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,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,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:14px 15px 14px;color:#fff;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{color:#fff;text-decoration:none;background-color:#3b3b3b}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#fff;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-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#000;*background-color:#000;background-image:-moz-linear-gradient(top,#000,#000);background-image:-webkit-gradient(linear,0 0,0 100%,from(#000),to(#000));background-image:-webkit-linear-gradient(top,#000,#000);background-image:-o-linear-gradient(top,#000,#000);background-image:linear-gradient(to bottom,#000,#000);background-repeat:repeat-x;border-color:#000 #000 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff000000',endColorstr='#ff000000',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#000;*background-color:#000}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#000 \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{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:transparent}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.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:#fff;border-bottom-color:#fff}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-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;border-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff007fff',endColorstr='#ff007fff',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#fff}.navbar-inverse .navbar-text{color:#fff}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:rgba(0,0,0,0.05)}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#007fff}.navbar-inverse .navbar-link{color:#fff}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#007fff;border-left-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{color:#fff;background-color:#007fff}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.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:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#80bfff;border-color:#007fff;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#999}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#999}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#999}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#999;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline: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)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0072e6;*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;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);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0072e6',endColorstr='#ff0072e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#0072e6;*background-color:#06c}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#0059b3 \9}.breadcrumb{padding:8px 15px;margin:0 0 22px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#dfdfdf}.pagination{margin:22px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;*zoom:1;-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:22px;text-decoration:none;background-color:#dfdfdf;border:1px solid transparent;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.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,.pagination ul>.disabled>a:focus{color:#dfdfdf;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}.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:20px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}.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-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-left-radius:0;border-top-left-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-topleft:0}.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:0;border-top-right-radius:0;-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:13.6px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:2px 6px;font-size:12px}.pager{margin:22px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.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,.pager li>a:focus{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>a:focus,.pager .disabled>span{color:#dfdfdf;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;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;outline:0;-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}.modal.fade{top:-25%;-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}.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;max-height:400px;padding:15px;overflow-y:auto}.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;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.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;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.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-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#ff7518;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);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;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-title:empty{display:none}.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{bottom:-16px;left:50%;margin-left:-16px;border-top-color:#999;border-top-color:transparent;border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-15px;border-top-color:#ff7518;border-bottom-width:0}.popover.right .arrow{top:50%;left:-16px;margin-top:-16px;border-right-color:#999;border-right-color:transparent;border-left-width:0}.popover.right .arrow:after{bottom:-15px;left:1px;border-right-color:#ff7518;border-left-width:0}.popover.bottom .arrow{top:-16px;left:50%;margin-left:-16px;border-bottom-color:#999;border-bottom-color:transparent;border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-15px;border-bottom-color:#ff7518;border-top-width:0}.popover.left .arrow{top:50%;right:-16px;margin-top:-16px;border-left-color:#999;border-left-color:transparent;border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-15px;border-left-color:#ff7518;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:22px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:22px;border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-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 .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{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-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#bbb}.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:13.536px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#dfdfdf}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#fff}.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:#fff}.label-success[href],.badge-success[href]{background-color:#e6e6e6}.label-info,.badge-info{background-color:#fff}.label-info[href],.badge-info[href]{background-color:#e6e6e6}.label-inverse,.badge-inverse{background-color:#999}.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{height:22px;margin-bottom:22px;overflow:hidden;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;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;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)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;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 .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,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:22px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.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:22px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>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:#fff;text-align:center;background:#080808;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#999;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:22px;color:#fff}.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:33px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:33px}body{overflow-y:scroll;font-weight:300}h1{font-size:50px}h2,h3{font-size:26px}h4{font-size:14px}h5,h6{font-size:11px}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#999}blockquote{padding:10px 15px;background-color:#eee;border-left-color:#bbb}blockquote.pull-right{padding:10px 15px;border-right-color:#bbb}blockquote small{color:#999}.muted{color:#bbb}.text-warning{color:#ff7518}a.text-warning:hover{color:#e45c00}.text-error{color:#ff0039}a.text-error:hover{color:#cc002e}.text-info{color:#9954bb}a.text-info:hover{color:#7e3f9d}.text-success{color:#3fb618}a.text-success:hover{color:#2f8912}.navbar .navbar-inner{background-image:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.navbar .brand:hover{color:#fff}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{background-color:#3b3b3b;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#fff}.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:#eee}.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{color:#fff;background-color:rgba(0,0,0,0.05);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.navbar-inverse .navbar-search .search-query{color:#080808}div.subnav{margin:0 1px;background:#dfdfdf none;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}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{color:#fff;background-color:#000;border-color:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}div.subnav-fixed{top:51px;margin:0}.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{color:#fff;background-color:#007fff}.nav-tabs.nav-stacked>.active>a,.nav-tabs.nav-stacked>.active>a:hover{color:#bbb;background-color:#fff}.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}.tabs-below>.nav-tabs>li>a,.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-pills>li>a{color:#000;background-color:#dfdfdf;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-pills>li>a:hover{color:#fff;background-color:#000}.nav-pills>.disabled>a,.nav-pills>.disabled>a:hover{color:#999;background-color:#eee}.nav-list>li>a{color:#080808}.nav-list>li>a:hover{color:#fff;text-shadow:none;background-color:#007fff}.nav-list .nav-header{font-size:16px;color:#000}.nav-list .divider{background-color:#bbb;border-bottom:0}.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{color:#fff;background-color:#080808}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{margin-right:0}.pagination ul>.active>a,.pagination ul>.active>span{color:#fff}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;background-color:#eee}.pager li>a,.pager li>span{color:#080808;background-color:#dfdfdf;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.pager li>a:hover,.pager li>span:hover{color:#fff;background-color:#080808}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;background-color:#eee}.breadcrumb{background-color:#dfdfdf}.breadcrumb li{text-shadow:none}.breadcrumb .divider,.breadcrumb .active{color:#080808;text-shadow:none}.btn{padding:5px 12px;color:#080808;text-shadow:none;background-image:none;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-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:hover,.btn:focus{color:#000}.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:#fff}.table tbody tr.error td{color:#fff}.table tbody tr.info td{color:#fff}.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{color:#080808;border-color:#ff7518}.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{color:#080808;border-color:#ff0039}.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{color:#080808;border-color:#3fb618}legend{color:#080808;border-bottom:0}.form-actions{background-color:#eee;border-top:0}.dropdown-menu{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.alert{text-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.alert-heading,.alert h1,.alert h2,.alert h3,.alert h4,.alert h5,.alert h6{color:#fff}.label{min-width:80px;min-height:80px;font-weight:300;text-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.label-success{background-color:#3fb618}.label-important{background-color:#ff0039}.label-info{background-color:#9954bb}.label-inverse{background-color:#000}.badge{font-weight:300;text-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.badge-success{background-color:#3fb618}.badge-important{background-color:#ff0039}.badge-info{background-color:#9954bb}.badge-inverse{background-color:#000}.hero-unit{border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.well{border:0;-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:#bbb;border-color:transparent}.progress{height:6px;background-color:#eee;background-image:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow: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:0}.modal-footer{background-color:transparent;border-top:0}.popover{color:#fff;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.popover-title{color:#fff;border-bottom:0}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}pre{margin-top:10px;color:#333}pre.terminal{font-size:1em;color:#c0c0c0;background:#000}.tlist li{padding-top:.3em;paddint-bottom:.3em}
diff --git a/doc-src/01-vendor.css b/doc-src/01-vendor.css
new file mode 100644
index 00000000..9c97647a
--- /dev/null
+++ b/doc-src/01-vendor.css
@@ -0,0 +1,6706 @@
+.navbar-inverse .badge {
+ background-color: #fff;
+ color: #2780e3;
+}
+body {
+ -webkit-font-smoothing: antialiased;
+}
+.text-primary,
+.text-primary:hover {
+ color: #2780e3;
+}
+.text-success,
+.text-success:hover {
+ color: #3fb618;
+}
+.text-danger,
+.text-danger:hover {
+ color: #ff0039;
+}
+.text-warning,
+.text-warning:hover {
+ color: #ff7518;
+}
+.text-info,
+.text-info:hover {
+ color: #9954bb;
+}
+table a:not(.btn),
+.table a:not(.btn) {
+ text-decoration: underline;
+}
+table .dropdown-menu a,
+.table .dropdown-menu a {
+ text-decoration: none;
+}
+table .success,
+.table .success,
+table .warning,
+.table .warning,
+table .danger,
+.table .danger,
+table .info,
+.table .info {
+ color: #fff;
+}
+table .success a,
+.table .success a,
+table .warning a,
+.table .warning a,
+table .danger a,
+.table .danger a,
+table .info a,
+.table .info a {
+ color: #fff;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .form-control-feedback {
+ color: #ff7518;
+}
+.has-warning .form-control,
+.has-warning .form-control:focus,
+.has-warning .input-group-addon {
+ border: 1px solid #ff7518;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .form-control-feedback {
+ color: #ff0039;
+}
+.has-error .form-control,
+.has-error .form-control:focus,
+.has-error .input-group-addon {
+ border: 1px solid #ff0039;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .form-control-feedback {
+ color: #3fb618;
+}
+.has-success .form-control,
+.has-success .form-control:focus,
+.has-success .input-group-addon {
+ border: 1px solid #3fb618;
+}
+.nav-pills > li > a {
+ border-radius: 0;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ background-image: none;
+}
+.close {
+ text-decoration: none;
+ text-shadow: none;
+ opacity: 0.4;
+}
+.close:hover,
+.close:focus {
+ opacity: 1;
+}
+.alert {
+ border: none;
+}
+.alert .alert-link {
+ text-decoration: underline;
+ color: #fff;
+}
+.label {
+ border-radius: 0;
+}
+.progress {
+ height: 8px;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.progress .progress-bar {
+ font-size: 8px;
+ line-height: 8px;
+}
+.panel-heading,
+.panel-footer {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.panel-default .close {
+ color: #333333;
+}
+a.list-group-item-success.active {
+ background-color: #3fb618;
+}
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+ background-color: #379f15;
+}
+a.list-group-item-warning.active {
+ background-color: #ff7518;
+}
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+ background-color: #fe6600;
+}
+a.list-group-item-danger.active {
+ background-color: #ff0039;
+}
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+ background-color: #e60033;
+}
+.modal .close {
+ color: #333333;
+}
+.popover {
+ color: #333333;
+}
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+html {
+ font-family: sans-serif;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+mark {
+ background: #ff0;
+ color: #000;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+sup {
+ top: -0.5em;
+}
+sub {
+ bottom: -0.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: textfield;
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+legend {
+ border: 0;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+td,
+th {
+ padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+ *,
+ *:before,
+ *:after {
+ background: transparent !important;
+ color: #000 !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ a[href^="#"]:after,
+ a[href^="javascript:"]: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;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+ select {
+ background: #fff !important;
+ }
+ .navbar {
+ display: none;
+ }
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+ .label {
+ border: 1px solid #000;
+ }
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+@font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url('../fonts/glyphicons-halflings-regular.eot');
+ src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+ content: "\2a";
+}
+.glyphicon-plus:before {
+ content: "\2b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+ content: "\20ac";
+}
+.glyphicon-minus:before {
+ content: "\2212";
+}
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+.glyphicon-glass:before {
+ content: "\e001";
+}
+.glyphicon-music:before {
+ content: "\e002";
+}
+.glyphicon-search:before {
+ content: "\e003";
+}
+.glyphicon-heart:before {
+ content: "\e005";
+}
+.glyphicon-star:before {
+ content: "\e006";
+}
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+.glyphicon-user:before {
+ content: "\e008";
+}
+.glyphicon-film:before {
+ content: "\e009";
+}
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+.glyphicon-th:before {
+ content: "\e011";
+}
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+.glyphicon-ok:before {
+ content: "\e013";
+}
+.glyphicon-remove:before {
+ content: "\e014";
+}
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+.glyphicon-off:before {
+ content: "\e017";
+}
+.glyphicon-signal:before {
+ content: "\e018";
+}
+.glyphicon-cog:before {
+ content: "\e019";
+}
+.glyphicon-trash:before {
+ content: "\e020";
+}
+.glyphicon-home:before {
+ content: "\e021";
+}
+.glyphicon-file:before {
+ content: "\e022";
+}
+.glyphicon-time:before {
+ content: "\e023";
+}
+.glyphicon-road:before {
+ content: "\e024";
+}
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+.glyphicon-download:before {
+ content: "\e026";
+}
+.glyphicon-upload:before {
+ content: "\e027";
+}
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+.glyphicon-lock:before {
+ content: "\e033";
+}
+.glyphicon-flag:before {
+ content: "\e034";
+}
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+.glyphicon-tag:before {
+ content: "\e041";
+}
+.glyphicon-tags:before {
+ content: "\e042";
+}
+.glyphicon-book:before {
+ content: "\e043";
+}
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+.glyphicon-print:before {
+ content: "\e045";
+}
+.glyphicon-camera:before {
+ content: "\e046";
+}
+.glyphicon-font:before {
+ content: "\e047";
+}
+.glyphicon-bold:before {
+ content: "\e048";
+}
+.glyphicon-italic:before {
+ content: "\e049";
+}
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+.glyphicon-list:before {
+ content: "\e056";
+}
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+.glyphicon-picture:before {
+ content: "\e060";
+}
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+.glyphicon-tint:before {
+ content: "\e064";
+}
+.glyphicon-edit:before {
+ content: "\e065";
+}
+.glyphicon-share:before {
+ content: "\e066";
+}
+.glyphicon-check:before {
+ content: "\e067";
+}
+.glyphicon-move:before {
+ content: "\e068";
+}
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+.glyphicon-backward:before {
+ content: "\e071";
+}
+.glyphicon-play:before {
+ content: "\e072";
+}
+.glyphicon-pause:before {
+ content: "\e073";
+}
+.glyphicon-stop:before {
+ content: "\e074";
+}
+.glyphicon-forward:before {
+ content: "\e075";
+}
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+.glyphicon-eject:before {
+ content: "\e078";
+}
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+.glyphicon-gift:before {
+ content: "\e102";
+}
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+.glyphicon-fire:before {
+ content: "\e104";
+}
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+.glyphicon-plane:before {
+ content: "\e108";
+}
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+.glyphicon-random:before {
+ content: "\e110";
+}
+.glyphicon-comment:before {
+ content: "\e111";
+}
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+.glyphicon-bell:before {
+ content: "\e123";
+}
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+.glyphicon-globe:before {
+ content: "\e135";
+}
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+.glyphicon-filter:before {
+ content: "\e138";
+}
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+.glyphicon-link:before {
+ content: "\e144";
+}
+.glyphicon-phone:before {
+ content: "\e145";
+}
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+.glyphicon-usd:before {
+ content: "\e148";
+}
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+.glyphicon-sort:before {
+ content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+.glyphicon-expand:before {
+ content: "\e158";
+}
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+.glyphicon-flash:before {
+ content: "\e162";
+}
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+.glyphicon-record:before {
+ content: "\e165";
+}
+.glyphicon-save:before {
+ content: "\e166";
+}
+.glyphicon-open:before {
+ content: "\e167";
+}
+.glyphicon-saved:before {
+ content: "\e168";
+}
+.glyphicon-import:before {
+ content: "\e169";
+}
+.glyphicon-export:before {
+ content: "\e170";
+}
+.glyphicon-send:before {
+ content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+.glyphicon-header:before {
+ content: "\e180";
+}
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+.glyphicon-tower:before {
+ content: "\e184";
+}
+.glyphicon-stats:before {
+ content: "\e185";
+}
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+.glyphicon-cd:before {
+ content: "\e201";
+}
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+.glyphicon-copy:before {
+ content: "\e205";
+}
+.glyphicon-paste:before {
+ content: "\e206";
+}
+.glyphicon-alert:before {
+ content: "\e209";
+}
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+.glyphicon-king:before {
+ content: "\e211";
+}
+.glyphicon-queen:before {
+ content: "\e212";
+}
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+.glyphicon-knight:before {
+ content: "\e215";
+}
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+.glyphicon-bed:before {
+ content: "\e219";
+}
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+.glyphicon-erase:before {
+ content: "\e221";
+}
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+.glyphicon-btc:before {
+ content: "\e227";
+}
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+.glyphicon-scale:before {
+ content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+.glyphicon-education:before {
+ content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+.glyphicon-oil:before {
+ content: "\e238";
+}
+.glyphicon-grain:before {
+ content: "\e239";
+}
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+.glyphicon-console:before {
+ content: "\e254";
+}
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+html {
+ font-size: 10px;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+ font-family: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+ font-size: 15px;
+ line-height: 1.42857143;
+ color: #333333;
+ background-color: #ffffff;
+}
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+a {
+ color: #2780e3;
+ text-decoration: none;
+}
+a:hover,
+a:focus {
+ color: #165ba8;
+ text-decoration: underline;
+}
+a:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+figure {
+ margin: 0;
+}
+img {
+ vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+.img-rounded {
+ border-radius: 0;
+}
+.img-thumbnail {
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 0;
+ -webkit-transition: all 0.2s ease-in-out;
+ -o-transition: all 0.2s ease-in-out;
+ transition: all 0.2s ease-in-out;
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+}
+.img-circle {
+ border-radius: 50%;
+}
+hr {
+ margin-top: 21px;
+ margin-bottom: 21px;
+ border: 0;
+ border-top: 1px solid #e6e6e6;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+[role="button"] {
+ cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ font-family: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+ font-weight: 300;
+ line-height: 1.1;
+ color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #999999;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 21px;
+ margin-bottom: 10.5px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+ font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+ margin-top: 10.5px;
+ margin-bottom: 10.5px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+ font-size: 75%;
+}
+h1,
+.h1 {
+ font-size: 39px;
+}
+h2,
+.h2 {
+ font-size: 32px;
+}
+h3,
+.h3 {
+ font-size: 26px;
+}
+h4,
+.h4 {
+ font-size: 19px;
+}
+h5,
+.h5 {
+ font-size: 15px;
+}
+h6,
+.h6 {
+ font-size: 13px;
+}
+p {
+ margin: 0 0 10.5px;
+}
+.lead {
+ margin-bottom: 21px;
+ font-size: 17px;
+ font-weight: 300;
+ line-height: 1.4;
+}
+@media (min-width: 768px) {
+ .lead {
+ font-size: 22.5px;
+ }
+}
+small,
+.small {
+ font-size: 86%;
+}
+mark,
+.mark {
+ background-color: #ff7518;
+ padding: .2em;
+}
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
+.text-lowercase {
+ text-transform: lowercase;
+}
+.text-uppercase {
+ text-transform: uppercase;
+}
+.text-capitalize {
+ text-transform: capitalize;
+}
+.text-muted {
+ color: #999999;
+}
+.text-primary {
+ color: #2780e3;
+}
+a.text-primary:hover {
+ color: #1967be;
+}
+.text-success {
+ color: #ffffff;
+}
+a.text-success:hover {
+ color: #e6e6e6;
+}
+.text-info {
+ color: #ffffff;
+}
+a.text-info:hover {
+ color: #e6e6e6;
+}
+.text-warning {
+ color: #ffffff;
+}
+a.text-warning:hover {
+ color: #e6e6e6;
+}
+.text-danger {
+ color: #ffffff;
+}
+a.text-danger:hover {
+ color: #e6e6e6;
+}
+.bg-primary {
+ color: #fff;
+ background-color: #2780e3;
+}
+a.bg-primary:hover {
+ background-color: #1967be;
+}
+.bg-success {
+ background-color: #3fb618;
+}
+a.bg-success:hover {
+ background-color: #2f8912;
+}
+.bg-info {
+ background-color: #9954bb;
+}
+a.bg-info:hover {
+ background-color: #7e3f9d;
+}
+.bg-warning {
+ background-color: #ff7518;
+}
+a.bg-warning:hover {
+ background-color: #e45c00;
+}
+.bg-danger {
+ background-color: #ff0039;
+}
+a.bg-danger:hover {
+ background-color: #cc002e;
+}
+.page-header {
+ padding-bottom: 9.5px;
+ margin: 42px 0 21px;
+ border-bottom: 1px solid #e6e6e6;
+}
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: 10.5px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+ margin-bottom: 0;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+.list-inline {
+ padding-left: 0;
+ list-style: none;
+ margin-left: -5px;
+}
+.list-inline > li {
+ display: inline-block;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+dl {
+ margin-top: 0;
+ margin-bottom: 21px;
+}
+dt,
+dd {
+ line-height: 1.42857143;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .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;
+ }
+}
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #999999;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+blockquote {
+ padding: 10.5px 21px;
+ margin: 0 0 21px;
+ font-size: 18.75px;
+ border-left: 5px solid #e6e6e6;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+ margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+ display: block;
+ font-size: 80%;
+ line-height: 1.42857143;
+ color: #999999;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+ content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid #e6e6e6;
+ border-left: 0;
+ text-align: right;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+ content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+ content: '\00A0 \2014';
+}
+address {
+ margin-bottom: 21px;
+ font-style: normal;
+ line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #c7254e;
+ background-color: #f9f2f4;
+ border-radius: 0;
+}
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #ffffff;
+ background-color: #333333;
+ border-radius: 0;
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+ box-shadow: none;
+}
+pre {
+ display: block;
+ padding: 10px;
+ margin: 0 0 10.5px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #333333;
+ background-color: #f5f5f5;
+ border: 1px solid #cccccc;
+ border-radius: 0;
+}
+pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+}
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+.container {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+@media (min-width: 768px) {
+ .container {
+ width: 750px;
+ }
+}
+@media (min-width: 992px) {
+ .container {
+ width: 970px;
+ }
+}
+@media (min-width: 1200px) {
+ .container {
+ width: 1170px;
+ }
+}
+.container-fluid {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.row {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+ position: relative;
+ min-height: 1px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+ float: left;
+}
+.col-xs-12 {
+ width: 100%;
+}
+.col-xs-11 {
+ width: 91.66666667%;
+}
+.col-xs-10 {
+ width: 83.33333333%;
+}
+.col-xs-9 {
+ width: 75%;
+}
+.col-xs-8 {
+ width: 66.66666667%;
+}
+.col-xs-7 {
+ width: 58.33333333%;
+}
+.col-xs-6 {
+ width: 50%;
+}
+.col-xs-5 {
+ width: 41.66666667%;
+}
+.col-xs-4 {
+ width: 33.33333333%;
+}
+.col-xs-3 {
+ width: 25%;
+}
+.col-xs-2 {
+ width: 16.66666667%;
+}
+.col-xs-1 {
+ width: 8.33333333%;
+}
+.col-xs-pull-12 {
+ right: 100%;
+}
+.col-xs-pull-11 {
+ right: 91.66666667%;
+}
+.col-xs-pull-10 {
+ right: 83.33333333%;
+}
+.col-xs-pull-9 {
+ right: 75%;
+}
+.col-xs-pull-8 {
+ right: 66.66666667%;
+}
+.col-xs-pull-7 {
+ right: 58.33333333%;
+}
+.col-xs-pull-6 {
+ right: 50%;
+}
+.col-xs-pull-5 {
+ right: 41.66666667%;
+}
+.col-xs-pull-4 {
+ right: 33.33333333%;
+}
+.col-xs-pull-3 {
+ right: 25%;
+}
+.col-xs-pull-2 {
+ right: 16.66666667%;
+}
+.col-xs-pull-1 {
+ right: 8.33333333%;
+}
+.col-xs-pull-0 {
+ right: auto;
+}
+.col-xs-push-12 {
+ left: 100%;
+}
+.col-xs-push-11 {
+ left: 91.66666667%;
+}
+.col-xs-push-10 {
+ left: 83.33333333%;
+}
+.col-xs-push-9 {
+ left: 75%;
+}
+.col-xs-push-8 {
+ left: 66.66666667%;
+}
+.col-xs-push-7 {
+ left: 58.33333333%;
+}
+.col-xs-push-6 {
+ left: 50%;
+}
+.col-xs-push-5 {
+ left: 41.66666667%;
+}
+.col-xs-push-4 {
+ left: 33.33333333%;
+}
+.col-xs-push-3 {
+ left: 25%;
+}
+.col-xs-push-2 {
+ left: 16.66666667%;
+}
+.col-xs-push-1 {
+ left: 8.33333333%;
+}
+.col-xs-push-0 {
+ left: auto;
+}
+.col-xs-offset-12 {
+ margin-left: 100%;
+}
+.col-xs-offset-11 {
+ margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+ margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+ margin-left: 75%;
+}
+.col-xs-offset-8 {
+ margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+ margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+ margin-left: 50%;
+}
+.col-xs-offset-5 {
+ margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+ margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+ margin-left: 25%;
+}
+.col-xs-offset-2 {
+ margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+ margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+ margin-left: 0%;
+}
+@media (min-width: 768px) {
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+ float: left;
+ }
+ .col-sm-12 {
+ width: 100%;
+ }
+ .col-sm-11 {
+ width: 91.66666667%;
+ }
+ .col-sm-10 {
+ width: 83.33333333%;
+ }
+ .col-sm-9 {
+ width: 75%;
+ }
+ .col-sm-8 {
+ width: 66.66666667%;
+ }
+ .col-sm-7 {
+ width: 58.33333333%;
+ }
+ .col-sm-6 {
+ width: 50%;
+ }
+ .col-sm-5 {
+ width: 41.66666667%;
+ }
+ .col-sm-4 {
+ width: 33.33333333%;
+ }
+ .col-sm-3 {
+ width: 25%;
+ }
+ .col-sm-2 {
+ width: 16.66666667%;
+ }
+ .col-sm-1 {
+ width: 8.33333333%;
+ }
+ .col-sm-pull-12 {
+ right: 100%;
+ }
+ .col-sm-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-sm-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-sm-pull-9 {
+ right: 75%;
+ }
+ .col-sm-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-sm-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-sm-pull-6 {
+ right: 50%;
+ }
+ .col-sm-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-sm-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-sm-pull-3 {
+ right: 25%;
+ }
+ .col-sm-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-sm-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-sm-pull-0 {
+ right: auto;
+ }
+ .col-sm-push-12 {
+ left: 100%;
+ }
+ .col-sm-push-11 {
+ left: 91.66666667%;
+ }
+ .col-sm-push-10 {
+ left: 83.33333333%;
+ }
+ .col-sm-push-9 {
+ left: 75%;
+ }
+ .col-sm-push-8 {
+ left: 66.66666667%;
+ }
+ .col-sm-push-7 {
+ left: 58.33333333%;
+ }
+ .col-sm-push-6 {
+ left: 50%;
+ }
+ .col-sm-push-5 {
+ left: 41.66666667%;
+ }
+ .col-sm-push-4 {
+ left: 33.33333333%;
+ }
+ .col-sm-push-3 {
+ left: 25%;
+ }
+ .col-sm-push-2 {
+ left: 16.66666667%;
+ }
+ .col-sm-push-1 {
+ left: 8.33333333%;
+ }
+ .col-sm-push-0 {
+ left: auto;
+ }
+ .col-sm-offset-12 {
+ margin-left: 100%;
+ }
+ .col-sm-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-sm-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-sm-offset-9 {
+ margin-left: 75%;
+ }
+ .col-sm-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-sm-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-sm-offset-6 {
+ margin-left: 50%;
+ }
+ .col-sm-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-sm-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-sm-offset-3 {
+ margin-left: 25%;
+ }
+ .col-sm-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-sm-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-sm-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ float: left;
+ }
+ .col-md-12 {
+ width: 100%;
+ }
+ .col-md-11 {
+ width: 91.66666667%;
+ }
+ .col-md-10 {
+ width: 83.33333333%;
+ }
+ .col-md-9 {
+ width: 75%;
+ }
+ .col-md-8 {
+ width: 66.66666667%;
+ }
+ .col-md-7 {
+ width: 58.33333333%;
+ }
+ .col-md-6 {
+ width: 50%;
+ }
+ .col-md-5 {
+ width: 41.66666667%;
+ }
+ .col-md-4 {
+ width: 33.33333333%;
+ }
+ .col-md-3 {
+ width: 25%;
+ }
+ .col-md-2 {
+ width: 16.66666667%;
+ }
+ .col-md-1 {
+ width: 8.33333333%;
+ }
+ .col-md-pull-12 {
+ right: 100%;
+ }
+ .col-md-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-md-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-md-pull-9 {
+ right: 75%;
+ }
+ .col-md-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-md-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-md-pull-6 {
+ right: 50%;
+ }
+ .col-md-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-md-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-md-pull-3 {
+ right: 25%;
+ }
+ .col-md-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-md-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-md-pull-0 {
+ right: auto;
+ }
+ .col-md-push-12 {
+ left: 100%;
+ }
+ .col-md-push-11 {
+ left: 91.66666667%;
+ }
+ .col-md-push-10 {
+ left: 83.33333333%;
+ }
+ .col-md-push-9 {
+ left: 75%;
+ }
+ .col-md-push-8 {
+ left: 66.66666667%;
+ }
+ .col-md-push-7 {
+ left: 58.33333333%;
+ }
+ .col-md-push-6 {
+ left: 50%;
+ }
+ .col-md-push-5 {
+ left: 41.66666667%;
+ }
+ .col-md-push-4 {
+ left: 33.33333333%;
+ }
+ .col-md-push-3 {
+ left: 25%;
+ }
+ .col-md-push-2 {
+ left: 16.66666667%;
+ }
+ .col-md-push-1 {
+ left: 8.33333333%;
+ }
+ .col-md-push-0 {
+ left: auto;
+ }
+ .col-md-offset-12 {
+ margin-left: 100%;
+ }
+ .col-md-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-md-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-md-offset-9 {
+ margin-left: 75%;
+ }
+ .col-md-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-md-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-md-offset-6 {
+ margin-left: 50%;
+ }
+ .col-md-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-md-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-md-offset-3 {
+ margin-left: 25%;
+ }
+ .col-md-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-md-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-md-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+ float: left;
+ }
+ .col-lg-12 {
+ width: 100%;
+ }
+ .col-lg-11 {
+ width: 91.66666667%;
+ }
+ .col-lg-10 {
+ width: 83.33333333%;
+ }
+ .col-lg-9 {
+ width: 75%;
+ }
+ .col-lg-8 {
+ width: 66.66666667%;
+ }
+ .col-lg-7 {
+ width: 58.33333333%;
+ }
+ .col-lg-6 {
+ width: 50%;
+ }
+ .col-lg-5 {
+ width: 41.66666667%;
+ }
+ .col-lg-4 {
+ width: 33.33333333%;
+ }
+ .col-lg-3 {
+ width: 25%;
+ }
+ .col-lg-2 {
+ width: 16.66666667%;
+ }
+ .col-lg-1 {
+ width: 8.33333333%;
+ }
+ .col-lg-pull-12 {
+ right: 100%;
+ }
+ .col-lg-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-lg-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-lg-pull-9 {
+ right: 75%;
+ }
+ .col-lg-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-lg-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-lg-pull-6 {
+ right: 50%;
+ }
+ .col-lg-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-lg-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-lg-pull-3 {
+ right: 25%;
+ }
+ .col-lg-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-lg-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-lg-pull-0 {
+ right: auto;
+ }
+ .col-lg-push-12 {
+ left: 100%;
+ }
+ .col-lg-push-11 {
+ left: 91.66666667%;
+ }
+ .col-lg-push-10 {
+ left: 83.33333333%;
+ }
+ .col-lg-push-9 {
+ left: 75%;
+ }
+ .col-lg-push-8 {
+ left: 66.66666667%;
+ }
+ .col-lg-push-7 {
+ left: 58.33333333%;
+ }
+ .col-lg-push-6 {
+ left: 50%;
+ }
+ .col-lg-push-5 {
+ left: 41.66666667%;
+ }
+ .col-lg-push-4 {
+ left: 33.33333333%;
+ }
+ .col-lg-push-3 {
+ left: 25%;
+ }
+ .col-lg-push-2 {
+ left: 16.66666667%;
+ }
+ .col-lg-push-1 {
+ left: 8.33333333%;
+ }
+ .col-lg-push-0 {
+ left: auto;
+ }
+ .col-lg-offset-12 {
+ margin-left: 100%;
+ }
+ .col-lg-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-lg-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-lg-offset-9 {
+ margin-left: 75%;
+ }
+ .col-lg-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-lg-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-lg-offset-6 {
+ margin-left: 50%;
+ }
+ .col-lg-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-lg-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-lg-offset-3 {
+ margin-left: 25%;
+ }
+ .col-lg-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-lg-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-lg-offset-0 {
+ margin-left: 0%;
+ }
+}
+table {
+ background-color: transparent;
+}
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #999999;
+ text-align: left;
+}
+th {
+ text-align: left;
+}
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 21px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #dddddd;
+}
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #dddddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.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 > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+ padding: 5px;
+}
+.table-bordered {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+ border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+ background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+ background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-column;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-cell;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+ background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+ background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+ background-color: #3fb618;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+ background-color: #379f15;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+ background-color: #9954bb;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+ background-color: #8d46b0;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+ background-color: #ff7518;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+ background-color: #fe6600;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+ background-color: #ff0039;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+ background-color: #e60033;
+}
+.table-responsive {
+ overflow-x: auto;
+ min-height: 0.01%;
+}
+@media screen and (max-width: 767px) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: 15.75px;
+ overflow-y: hidden;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid #dddddd;
+ }
+ .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ .table-responsive > .table > thead > tr > th,
+ .table-responsive > .table > tbody > tr > th,
+ .table-responsive > .table > tfoot > tr > th,
+ .table-responsive > .table > thead > tr > td,
+ .table-responsive > .table > tbody > tr > td,
+ .table-responsive > .table > tfoot > tr > td {
+ white-space: nowrap;
+ }
+ .table-responsive > .table-bordered {
+ border: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+ }
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+ border-bottom: 0;
+ }
+}
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ min-width: 0;
+}
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 21px;
+ font-size: 22.5px;
+ line-height: inherit;
+ color: #333333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+label {
+ display: inline-block;
+ max-width: 100%;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+input[type="search"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ line-height: normal;
+}
+input[type="file"] {
+ display: block;
+}
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+select[multiple],
+select[size] {
+ height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+output {
+ display: block;
+ padding-top: 11px;
+ font-size: 15px;
+ line-height: 1.42857143;
+ color: #333333;
+}
+.form-control {
+ display: block;
+ width: 100%;
+ height: 43px;
+ padding: 10px 18px;
+ font-size: 15px;
+ line-height: 1.42857143;
+ color: #333333;
+ background-color: #ffffff;
+ background-image: none;
+ border: 1px solid #cccccc;
+ border-radius: 0;
+ -webkit-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-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.form-control::-moz-placeholder {
+ color: #999999;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #999999;
+}
+.form-control::-webkit-input-placeholder {
+ color: #999999;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+ background-color: #e6e6e6;
+ opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+ cursor: not-allowed;
+}
+textarea.form-control {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type="date"],
+ input[type="time"],
+ input[type="datetime-local"],
+ input[type="month"] {
+ line-height: 43px;
+ }
+ input[type="date"].input-sm,
+ input[type="time"].input-sm,
+ input[type="datetime-local"].input-sm,
+ input[type="month"].input-sm,
+ .input-group-sm input[type="date"],
+ .input-group-sm input[type="time"],
+ .input-group-sm input[type="datetime-local"],
+ .input-group-sm input[type="month"] {
+ line-height: 31px;
+ }
+ input[type="date"].input-lg,
+ input[type="time"].input-lg,
+ input[type="datetime-local"].input-lg,
+ input[type="month"].input-lg,
+ .input-group-lg input[type="date"],
+ .input-group-lg input[type="time"],
+ .input-group-lg input[type="datetime-local"],
+ .input-group-lg input[type="month"] {
+ line-height: 64px;
+ }
+}
+.form-group {
+ margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+ position: relative;
+ display: block;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+ min-height: 21px;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ position: absolute;
+ margin-left: -20px;
+ margin-top: 4px \9;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+ position: relative;
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ vertical-align: middle;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+ cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+ cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+ cursor: not-allowed;
+}
+.form-control-static {
+ padding-top: 11px;
+ padding-bottom: 11px;
+ margin-bottom: 0;
+ min-height: 36px;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-sm {
+ height: 31px;
+ padding: 5px 10px;
+ font-size: 13px;
+ line-height: 1.5;
+ border-radius: 0;
+}
+select.input-sm {
+ height: 31px;
+ line-height: 31px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+ height: auto;
+}
+.form-group-sm .form-control {
+ height: 31px;
+ padding: 5px 10px;
+ font-size: 13px;
+ line-height: 1.5;
+ border-radius: 0;
+}
+select.form-group-sm .form-control {
+ height: 31px;
+ line-height: 31px;
+}
+textarea.form-group-sm .form-control,
+select[multiple].form-group-sm .form-control {
+ height: auto;
+}
+.form-group-sm .form-control-static {
+ height: 31px;
+ padding: 5px 10px;
+ font-size: 13px;
+ line-height: 1.5;
+ min-height: 34px;
+}
+.input-lg {
+ height: 64px;
+ padding: 18px 30px;
+ font-size: 19px;
+ line-height: 1.3333333;
+ border-radius: 0;
+}
+select.input-lg {
+ height: 64px;
+ line-height: 64px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+ height: auto;
+}
+.form-group-lg .form-control {
+ height: 64px;
+ padding: 18px 30px;
+ font-size: 19px;
+ line-height: 1.3333333;
+ border-radius: 0;
+}
+select.form-group-lg .form-control {
+ height: 64px;
+ line-height: 64px;
+}
+textarea.form-group-lg .form-control,
+select[multiple].form-group-lg .form-control {
+ height: auto;
+}
+.form-group-lg .form-control-static {
+ height: 64px;
+ padding: 18px 30px;
+ font-size: 19px;
+ line-height: 1.3333333;
+ min-height: 40px;
+}
+.has-feedback {
+ position: relative;
+}
+.has-feedback .form-control {
+ padding-right: 53.75px;
+}
+.form-control-feedback {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ display: block;
+ width: 43px;
+ height: 43px;
+ line-height: 43px;
+ text-align: center;
+ pointer-events: none;
+}
+.input-lg + .form-control-feedback {
+ width: 64px;
+ height: 64px;
+ line-height: 64px;
+}
+.input-sm + .form-control-feedback {
+ width: 31px;
+ height: 31px;
+ line-height: 31px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+ color: #ffffff;
+}
+.has-success .form-control {
+ border-color: #ffffff;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-success .form-control:focus {
+ border-color: #e6e6e6;
+ -webkit-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;
+}
+.has-success .input-group-addon {
+ color: #ffffff;
+ border-color: #ffffff;
+ background-color: #3fb618;
+}
+.has-success .form-control-feedback {
+ color: #ffffff;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+ color: #ffffff;
+}
+.has-warning .form-control {
+ border-color: #ffffff;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-warning .form-control:focus {
+ border-color: #e6e6e6;
+ -webkit-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;
+}
+.has-warning .input-group-addon {
+ color: #ffffff;
+ border-color: #ffffff;
+ background-color: #ff7518;
+}
+.has-warning .form-control-feedback {
+ color: #ffffff;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+ color: #ffffff;
+}
+.has-error .form-control {
+ border-color: #ffffff;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-error .form-control:focus {
+ border-color: #e6e6e6;
+ -webkit-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;
+}
+.has-error .input-group-addon {
+ color: #ffffff;
+ border-color: #ffffff;
+ background-color: #ff0039;
+}
+.has-error .form-control-feedback {
+ color: #ffffff;
+}
+.has-feedback label ~ .form-control-feedback {
+ top: 26px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+ top: 0;
+}
+.help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #737373;
+}
+@media (min-width: 768px) {
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-static {
+ display: inline-block;
+ }
+ .form-inline .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .form-inline .input-group .input-group-addon,
+ .form-inline .input-group .input-group-btn,
+ .form-inline .input-group .form-control {
+ width: auto;
+ }
+ .form-inline .input-group > .form-control {
+ width: 100%;
+ }
+ .form-inline .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio,
+ .form-inline .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio label,
+ .form-inline .checkbox label {
+ padding-left: 0;
+ }
+ .form-inline .radio input[type="radio"],
+ .form-inline .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 11px;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+ min-height: 32px;
+}
+.form-horizontal .form-group {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .control-label {
+ text-align: right;
+ margin-bottom: 0;
+ padding-top: 11px;
+ }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+ right: 15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-lg .control-label {
+ padding-top: 24.9999994px;
+ }
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-sm .control-label {
+ padding-top: 6px;
+ }
+}
+.btn {
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 10px 18px;
+ font-size: 15px;
+ line-height: 1.42857143;
+ border-radius: 0;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #ffffff;
+ text-decoration: none;
+}
+.btn:active,
+.btn.active {
+ outline: 0;
+ background-image: none;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ pointer-events: none;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-default {
+ color: #ffffff;
+ background-color: #222222;
+ border-color: #222222;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default.focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ color: #ffffff;
+ background-color: #090909;
+ border-color: #040404;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+ background-color: #222222;
+ border-color: #222222;
+}
+.btn-default .badge {
+ color: #222222;
+ background-color: #ffffff;
+}
+.btn-primary {
+ color: #ffffff;
+ background-color: #2780e3;
+ border-color: #2780e3;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary.focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ color: #ffffff;
+ background-color: #1967be;
+ border-color: #1862b5;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: #2780e3;
+ border-color: #2780e3;
+}
+.btn-primary .badge {
+ color: #2780e3;
+ background-color: #ffffff;
+}
+.btn-success {
+ color: #ffffff;
+ background-color: #3fb618;
+ border-color: #3fb618;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success.focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ color: #ffffff;
+ background-color: #2f8912;
+ border-color: #2c8011;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+ background-color: #3fb618;
+ border-color: #3fb618;
+}
+.btn-success .badge {
+ color: #3fb618;
+ background-color: #ffffff;
+}
+.btn-info {
+ color: #ffffff;
+ background-color: #9954bb;
+ border-color: #9954bb;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info.focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ color: #ffffff;
+ background-color: #7e3f9d;
+ border-color: #783c96;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+ background-color: #9954bb;
+ border-color: #9954bb;
+}
+.btn-info .badge {
+ color: #9954bb;
+ background-color: #ffffff;
+}
+.btn-warning {
+ color: #ffffff;
+ background-color: #ff7518;
+ border-color: #ff7518;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning.focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ color: #ffffff;
+ background-color: #e45c00;
+ border-color: #da5800;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+ background-color: #ff7518;
+ border-color: #ff7518;
+}
+.btn-warning .badge {
+ color: #ff7518;
+ background-color: #ffffff;
+}
+.btn-danger {
+ color: #ffffff;
+ background-color: #ff0039;
+ border-color: #ff0039;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger.focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ color: #ffffff;
+ background-color: #cc002e;
+ border-color: #c2002b;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+ background-color: #ff0039;
+ border-color: #ff0039;
+}
+.btn-danger .badge {
+ color: #ff0039;
+ background-color: #ffffff;
+}
+.btn-link {
+ color: #2780e3;
+ font-weight: normal;
+ border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+ background-color: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+ border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+ color: #165ba8;
+ text-decoration: underline;
+ background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+ color: #999999;
+ text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+ padding: 18px 30px;
+ font-size: 19px;
+ line-height: 1.3333333;
+ border-radius: 0;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+ padding: 5px 10px;
+ font-size: 13px;
+ line-height: 1.5;
+ border-radius: 0;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+ padding: 1px 5px;
+ font-size: 13px;
+ line-height: 1.5;
+ border-radius: 0;
+}
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity 0.15s linear;
+ -o-transition: opacity 0.15s linear;
+ transition: opacity 0.15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.collapse {
+ display: none;
+}
+.collapse.in {
+ display: block;
+}
+tr.collapse.in {
+ display: table-row;
+}
+tbody.collapse.in {
+ display: table-row-group;
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition-property: height, visibility;
+ transition-property: height, visibility;
+ -webkit-transition-duration: 0.35s;
+ transition-duration: 0.35s;
+ -webkit-transition-timing-function: ease;
+ transition-timing-function: ease;
+}
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: 4px dashed;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle:focus {
+ outline: 0;
+}
+.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;
+ font-size: 15px;
+ text-align: left;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ background-clip: padding-box;
+}
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 9.5px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.42857143;
+ color: #333333;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ text-decoration: none;
+ color: #ffffff;
+ background-color: #2780e3;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ text-decoration: none;
+ outline: 0;
+ background-color: #2780e3;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #999999;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ cursor: not-allowed;
+}
+.open > .dropdown-menu {
+ display: block;
+}
+.open > a {
+ outline: 0;
+}
+.dropdown-menu-right {
+ left: auto;
+ right: 0;
+}
+.dropdown-menu-left {
+ left: 0;
+ right: auto;
+}
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #999999;
+ white-space: nowrap;
+}
+.dropdown-backdrop {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ z-index: 990;
+}
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ border-top: 0;
+ border-bottom: 4px solid;
+ content: "";
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-right .dropdown-menu {
+ left: auto;
+ right: 0;
+ }
+ .navbar-right .dropdown-menu-left {
+ left: 0;
+ right: auto;
+ }
+}
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+ z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+ margin-left: -1px;
+}
+.btn-toolbar {
+ margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+ float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+ margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+.btn-group > .btn:first-child {
+ margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+.btn-group.open .dropdown-toggle {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn .caret {
+ margin-left: 0;
+}
+.btn-lg .caret {
+ border-width: 5px 5px 0;
+ border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+ border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+ float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-bottom-left-radius: 0;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+ float: none;
+ display: table-cell;
+ width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+ width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+ left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+.input-group {
+ position: relative;
+ display: table;
+ border-collapse: separate;
+}
+.input-group[class*="col-"] {
+ float: none;
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ height: 64px;
+ padding: 18px 30px;
+ font-size: 19px;
+ line-height: 1.3333333;
+ border-radius: 0;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+ height: 64px;
+ line-height: 64px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ height: 31px;
+ padding: 5px 10px;
+ font-size: 13px;
+ line-height: 1.5;
+ border-radius: 0;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+ height: 31px;
+ line-height: 31px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+.input-group-addon {
+ padding: 10px 18px;
+ font-size: 15px;
+ font-weight: normal;
+ line-height: 1;
+ color: #333333;
+ text-align: center;
+ background-color: #e6e6e6;
+ border: 1px solid #cccccc;
+ border-radius: 0;
+}
+.input-group-addon.input-sm {
+ padding: 5px 10px;
+ font-size: 13px;
+ border-radius: 0;
+}
+.input-group-addon.input-lg {
+ padding: 18px 30px;
+ font-size: 19px;
+ border-radius: 0;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+ margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap;
+}
+.input-group-btn > .btn {
+ position: relative;
+}
+.input-group-btn > .btn + .btn {
+ margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+ z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+ margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+ margin-left: -1px;
+}
+.nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+}
+.nav > li {
+ position: relative;
+ display: block;
+}
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #e6e6e6;
+}
+.nav > li.disabled > a {
+ color: #999999;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+ color: #999999;
+ text-decoration: none;
+ background-color: transparent;
+ cursor: not-allowed;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #e6e6e6;
+ border-color: #2780e3;
+}
+.nav .nav-divider {
+ height: 1px;
+ margin: 9.5px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.nav > li > a > img {
+ max-width: none;
+}
+.nav-tabs {
+ border-bottom: 1px solid #dddddd;
+}
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 0 0 0 0;
+}
+.nav-tabs > li > a:hover {
+ border-color: #e6e6e6 #e6e6e6 #dddddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #555555;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-bottom-color: transparent;
+ cursor: default;
+}
+.nav-tabs.nav-justified {
+ width: 100%;
+ border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+ float: none;
+}
+.nav-tabs.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-tabs.nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs.nav-justified > li > a {
+ margin-right: 0;
+ border-radius: 0;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 0 0 0 0;
+ }
+ .nav-tabs.nav-justified > .active > a,
+ .nav-tabs.nav-justified > .active > a:hover,
+ .nav-tabs.nav-justified > .active > a:focus {
+ border-bottom-color: #ffffff;
+ }
+}
+.nav-pills > li {
+ float: left;
+}
+.nav-pills > li > a {
+ border-radius: 0;
+}
+.nav-pills > li + li {
+ margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+ color: #ffffff;
+ background-color: #2780e3;
+}
+.nav-stacked > li {
+ float: none;
+}
+.nav-stacked > li + li {
+ margin-top: 2px;
+ margin-left: 0;
+}
+.nav-justified {
+ width: 100%;
+}
+.nav-justified > li {
+ float: none;
+}
+.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs-justified {
+ border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+ margin-right: 0;
+ border-radius: 0;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 0 0 0 0;
+ }
+ .nav-tabs-justified > .active > a,
+ .nav-tabs-justified > .active > a:hover,
+ .nav-tabs-justified > .active > a:focus {
+ border-bottom-color: #ffffff;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 21px;
+ border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-header {
+ float: left;
+ }
+}
+.navbar-collapse {
+ overflow-x: visible;
+ padding-right: 15px;
+ padding-left: 15px;
+ border-top: 1px solid transparent;
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
+ -webkit-overflow-scrolling: touch;
+}
+.navbar-collapse.in {
+ overflow-y: auto;
+}
+@media (min-width: 768px) {
+ .navbar-collapse {
+ width: auto;
+ border-top: 0;
+ box-shadow: none;
+ }
+ .navbar-collapse.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0;
+ overflow: visible !important;
+ }
+ .navbar-collapse.in {
+ overflow-y: visible;
+ }
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-static-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+ max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ max-height: 200px;
+ }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .container > .navbar-header,
+ .container-fluid > .navbar-header,
+ .container > .navbar-collapse,
+ .container-fluid > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.navbar-static-top {
+ z-index: 1000;
+ border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+ .navbar-static-top {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+@media (min-width: 768px) {
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0;
+ border-width: 1px 0 0;
+}
+.navbar-brand {
+ float: left;
+ padding: 14.5px 15px;
+ font-size: 19px;
+ line-height: 21px;
+ height: 50px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+.navbar-brand > img {
+ display: block;
+}
+@media (min-width: 768px) {
+ .navbar > .container .navbar-brand,
+ .navbar > .container-fluid .navbar-brand {
+ margin-left: -15px;
+ }
+}
+.navbar-toggle {
+ position: relative;
+ float: right;
+ margin-right: 15px;
+ padding: 9px 10px;
+ margin-top: 8px;
+ margin-bottom: 8px;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+.navbar-toggle:focus {
+ outline: 0;
+}
+.navbar-toggle .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+ margin-top: 4px;
+}
+@media (min-width: 768px) {
+ .navbar-toggle {
+ display: none;
+ }
+}
+.navbar-nav {
+ margin: 7.25px -15px;
+}
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 21px;
+}
+@media (max-width: 767px) {
+ .navbar-nav .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ box-shadow: none;
+ }
+ .navbar-nav .open .dropdown-menu > li > a,
+ .navbar-nav .open .dropdown-menu .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a {
+ line-height: 21px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-nav .open .dropdown-menu > li > a:focus {
+ background-image: none;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+ .navbar-nav > li {
+ float: left;
+ }
+ .navbar-nav > li > a {
+ padding-top: 14.5px;
+ padding-bottom: 14.5px;
+ }
+}
+.navbar-form {
+ margin-left: -15px;
+ margin-right: -15px;
+ padding: 10px 15px;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ margin-top: 3.5px;
+ margin-bottom: 3.5px;
+}
+@media (min-width: 768px) {
+ .navbar-form .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control-static {
+ display: inline-block;
+ }
+ .navbar-form .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .navbar-form .input-group .input-group-addon,
+ .navbar-form .input-group .input-group-btn,
+ .navbar-form .input-group .form-control {
+ width: auto;
+ }
+ .navbar-form .input-group > .form-control {
+ width: 100%;
+ }
+ .navbar-form .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio,
+ .navbar-form .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio label,
+ .navbar-form .checkbox label {
+ padding-left: 0;
+ }
+ .navbar-form .radio input[type="radio"],
+ .navbar-form .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .navbar-form .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+@media (max-width: 767px) {
+ .navbar-form .form-group {
+ margin-bottom: 5px;
+ }
+ .navbar-form .form-group:last-child {
+ margin-bottom: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-form {
+ width: auto;
+ border: 0;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+}
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ margin-bottom: 0;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.navbar-btn {
+ margin-top: 3.5px;
+ margin-bottom: 3.5px;
+}
+.navbar-btn.btn-sm {
+ margin-top: 9.5px;
+ margin-bottom: 9.5px;
+}
+.navbar-btn.btn-xs {
+ margin-top: 14px;
+ margin-bottom: 14px;
+}
+.navbar-text {
+ margin-top: 14.5px;
+ margin-bottom: 14.5px;
+}
+@media (min-width: 768px) {
+ .navbar-text {
+ float: left;
+ margin-left: 15px;
+ margin-right: 15px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -15px;
+ }
+ .navbar-right ~ .navbar-right {
+ margin-right: 0;
+ }
+}
+.navbar-default {
+ background-color: #222222;
+ border-color: #121212;
+}
+.navbar-default .navbar-brand {
+ color: #ffffff;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+ color: #ffffff;
+ background-color: none;
+}
+.navbar-default .navbar-text {
+ color: #ffffff;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #ffffff;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+ color: #ffffff;
+ background-color: #090909;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+ color: #ffffff;
+ background-color: #090909;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+ border-color: transparent;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+ background-color: #090909;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #ffffff;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #121212;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+ background-color: #090909;
+ color: #ffffff;
+}
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #ffffff;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ background-color: #090909;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ background-color: #090909;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+ }
+}
+.navbar-default .navbar-link {
+ color: #ffffff;
+}
+.navbar-default .navbar-link:hover {
+ color: #ffffff;
+}
+.navbar-default .btn-link {
+ color: #ffffff;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+ color: #ffffff;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+ color: #cccccc;
+}
+.navbar-inverse {
+ background-color: #2780e3;
+ border-color: #1967be;
+}
+.navbar-inverse .navbar-brand {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #ffffff;
+ background-color: none;
+}
+.navbar-inverse .navbar-text {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #ffffff;
+ background-color: #1967be;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #ffffff;
+ background-color: #1967be;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: transparent;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #1967be;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #ffffff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border-color: #1a6ecc;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ background-color: #1967be;
+ color: #ffffff;
+}
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+ border-color: #1967be;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+ background-color: #1967be;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #ffffff;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ background-color: #1967be;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ background-color: #1967be;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+ }
+}
+.navbar-inverse .navbar-link {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+ color: #ffffff;
+}
+.breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 21px;
+ list-style: none;
+ background-color: #f5f5f5;
+ border-radius: 0;
+}
+.breadcrumb > li {
+ display: inline-block;
+}
+.breadcrumb > li + li:before {
+ content: "/\00a0";
+ padding: 0 5px;
+ color: #cccccc;
+}
+.breadcrumb > .active {
+ color: #999999;
+}
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: 21px 0;
+ border-radius: 0;
+}
+.pagination > li {
+ display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+ position: relative;
+ float: left;
+ padding: 10px 18px;
+ line-height: 1.42857143;
+ text-decoration: none;
+ color: #2780e3;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ margin-left: -1px;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+ margin-left: 0;
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+ color: #165ba8;
+ background-color: #e6e6e6;
+ border-color: #dddddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+ z-index: 2;
+ color: #999999;
+ background-color: #f5f5f5;
+ border-color: #dddddd;
+ cursor: default;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+ color: #999999;
+ background-color: #ffffff;
+ border-color: #dddddd;
+ cursor: not-allowed;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+ padding: 18px 30px;
+ font-size: 19px;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+ padding: 5px 10px;
+ font-size: 13px;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.pager {
+ padding-left: 0;
+ margin: 21px 0;
+ list-style: none;
+ text-align: center;
+}
+.pager li {
+ display: inline;
+}
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 0;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #e6e6e6;
+}
+.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 > a:focus,
+.pager .disabled > span {
+ color: #999999;
+ background-color: #ffffff;
+ cursor: not-allowed;
+}
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #ffffff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.label:empty {
+ display: none;
+}
+.btn .label {
+ position: relative;
+ top: -1px;
+}
+.label-default {
+ background-color: #222222;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+ background-color: #090909;
+}
+.label-primary {
+ background-color: #2780e3;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+ background-color: #1967be;
+}
+.label-success {
+ background-color: #3fb618;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+ background-color: #2f8912;
+}
+.label-info {
+ background-color: #9954bb;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+ background-color: #7e3f9d;
+}
+.label-warning {
+ background-color: #ff7518;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+ background-color: #e45c00;
+}
+.label-danger {
+ background-color: #ff0039;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+ background-color: #cc002e;
+}
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: 13px;
+ font-weight: bold;
+ color: #ffffff;
+ line-height: 1;
+ vertical-align: baseline;
+ white-space: nowrap;
+ text-align: center;
+ background-color: #2780e3;
+ border-radius: 10px;
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+ top: 0;
+ padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: #2780e3;
+ background-color: #ffffff;
+}
+.list-group-item > .badge {
+ float: right;
+}
+.list-group-item > .badge + .badge {
+ margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
+.jumbotron {
+ padding: 30px 15px;
+ margin-bottom: 30px;
+ color: inherit;
+ background-color: #e6e6e6;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+ color: inherit;
+}
+.jumbotron p {
+ margin-bottom: 15px;
+ font-size: 23px;
+ font-weight: 200;
+}
+.jumbotron > hr {
+ border-top-color: #cccccc;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+ border-radius: 0;
+}
+.jumbotron .container {
+ max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+ .jumbotron {
+ padding: 48px 0;
+ }
+ .container .jumbotron,
+ .container-fluid .jumbotron {
+ padding-left: 60px;
+ padding-right: 60px;
+ }
+ .jumbotron h1,
+ .jumbotron .h1 {
+ font-size: 67.5px;
+ }
+}
+.thumbnail {
+ display: block;
+ padding: 4px;
+ margin-bottom: 21px;
+ line-height: 1.42857143;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 0;
+ -webkit-transition: border 0.2s ease-in-out;
+ -o-transition: border 0.2s ease-in-out;
+ transition: border 0.2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+ margin-left: auto;
+ margin-right: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: #2780e3;
+}
+.thumbnail .caption {
+ padding: 9px;
+ color: #333333;
+}
+.alert {
+ padding: 15px;
+ margin-bottom: 21px;
+ border: 1px solid transparent;
+ border-radius: 0;
+}
+.alert h4 {
+ margin-top: 0;
+ color: inherit;
+}
+.alert .alert-link {
+ font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+ margin-bottom: 0;
+}
+.alert > p + p {
+ margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+ padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+}
+.alert-success {
+ background-color: #3fb618;
+ border-color: #4e9f15;
+ color: #ffffff;
+}
+.alert-success hr {
+ border-top-color: #438912;
+}
+.alert-success .alert-link {
+ color: #e6e6e6;
+}
+.alert-info {
+ background-color: #9954bb;
+ border-color: #7643a8;
+ color: #ffffff;
+}
+.alert-info hr {
+ border-top-color: #693c96;
+}
+.alert-info .alert-link {
+ color: #e6e6e6;
+}
+.alert-warning {
+ background-color: #ff7518;
+ border-color: #ff4309;
+ color: #ffffff;
+}
+.alert-warning hr {
+ border-top-color: #ee3800;
+}
+.alert-warning .alert-link {
+ color: #e6e6e6;
+}
+.alert-danger {
+ background-color: #ff0039;
+ border-color: #f0005e;
+ color: #ffffff;
+}
+.alert-danger hr {
+ border-top-color: #d60054;
+}
+.alert-danger .alert-link {
+ color: #e6e6e6;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ overflow: hidden;
+ height: 21px;
+ margin-bottom: 21px;
+ background-color: #cccccc;
+ border-radius: 0;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+.progress-bar {
+ float: left;
+ width: 0%;
+ height: 100%;
+ font-size: 13px;
+ line-height: 21px;
+ color: #ffffff;
+ text-align: center;
+ background-color: #2780e3;
+ -webkit-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-transition: width 0.6s ease;
+ -o-transition: width 0.6s ease;
+ transition: width 0.6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+ 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: -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);
+ background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+ background-color: #3fb618;
+}
+.progress-striped .progress-bar-success {
+ 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: -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-bar-info {
+ background-color: #9954bb;
+}
+.progress-striped .progress-bar-info {
+ 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: -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-bar-warning {
+ background-color: #ff7518;
+}
+.progress-striped .progress-bar-warning {
+ 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: -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-bar-danger {
+ background-color: #ff0039;
+}
+.progress-striped .progress-bar-danger {
+ 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: -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);
+}
+.media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+.media,
+.media-body {
+ zoom: 1;
+ overflow: hidden;
+}
+.media-body {
+ width: 10000px;
+}
+.media-object {
+ display: block;
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+ display: table-cell;
+ vertical-align: top;
+}
+.media-middle {
+ vertical-align: middle;
+}
+.media-bottom {
+ vertical-align: bottom;
+}
+.media-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
+.list-group {
+ margin-bottom: 20px;
+ padding-left: 0;
+}
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+}
+.list-group-item:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+a.list-group-item {
+ color: #555555;
+}
+a.list-group-item .list-group-item-heading {
+ color: #333333;
+}
+a.list-group-item:hover,
+a.list-group-item:focus {
+ text-decoration: none;
+ color: #555555;
+ background-color: #f5f5f5;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+ background-color: #e6e6e6;
+ color: #999999;
+ cursor: not-allowed;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+ color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+ color: #999999;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ z-index: 2;
+ color: #ffffff;
+ background-color: #2780e3;
+ border-color: #dddddd;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+ color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+ color: #dceafa;
+}
+.list-group-item-success {
+ color: #ffffff;
+ background-color: #3fb618;
+}
+a.list-group-item-success {
+ color: #ffffff;
+}
+a.list-group-item-success .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+ color: #ffffff;
+ background-color: #379f15;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+ color: #fff;
+ background-color: #ffffff;
+ border-color: #ffffff;
+}
+.list-group-item-info {
+ color: #ffffff;
+ background-color: #9954bb;
+}
+a.list-group-item-info {
+ color: #ffffff;
+}
+a.list-group-item-info .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+ color: #ffffff;
+ background-color: #8d46b0;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+ color: #fff;
+ background-color: #ffffff;
+ border-color: #ffffff;
+}
+.list-group-item-warning {
+ color: #ffffff;
+ background-color: #ff7518;
+}
+a.list-group-item-warning {
+ color: #ffffff;
+}
+a.list-group-item-warning .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+ color: #ffffff;
+ background-color: #fe6600;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+ color: #fff;
+ background-color: #ffffff;
+ border-color: #ffffff;
+}
+.list-group-item-danger {
+ color: #ffffff;
+ background-color: #ff0039;
+}
+a.list-group-item-danger {
+ color: #ffffff;
+}
+a.list-group-item-danger .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+ color: #ffffff;
+ background-color: #e60033;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+ color: #fff;
+ background-color: #ffffff;
+ border-color: #ffffff;
+}
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
+.panel {
+ margin-bottom: 21px;
+ background-color: #ffffff;
+ border: 1px solid transparent;
+ border-radius: 0;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.panel-body {
+ padding: 15px;
+}
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-right-radius: -1;
+ border-top-left-radius: -1;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+ color: inherit;
+}
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 17px;
+ color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+ color: inherit;
+}
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #dddddd;
+ border-bottom-right-radius: -1;
+ border-bottom-left-radius: -1;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+ margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+ border-top: 0;
+ border-top-right-radius: -1;
+ border-top-left-radius: -1;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+ border-bottom: 0;
+ border-bottom-right-radius: -1;
+ border-bottom-left-radius: -1;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+ border-top-width: 0;
+}
+.list-group + .panel-footer {
+ border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+ margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+ border-top-right-radius: -1;
+ border-top-left-radius: -1;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+ border-top-left-radius: -1;
+ border-top-right-radius: -1;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+ border-top-left-radius: -1;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+ border-top-right-radius: -1;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+ border-bottom-right-radius: -1;
+ border-bottom-left-radius: -1;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+ border-bottom-left-radius: -1;
+ border-bottom-right-radius: -1;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+ border-bottom-left-radius: -1;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+ border-bottom-right-radius: -1;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+ border-top: 1px solid #dddddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+ border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+ border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+ border-bottom: 0;
+}
+.panel > .table-responsive {
+ border: 0;
+ margin-bottom: 0;
+}
+.panel-group {
+ margin-bottom: 21px;
+}
+.panel-group .panel {
+ margin-bottom: 0;
+ border-radius: 0;
+}
+.panel-group .panel + .panel {
+ margin-top: 5px;
+}
+.panel-group .panel-heading {
+ border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+ border-top: 1px solid #dddddd;
+}
+.panel-group .panel-footer {
+ border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+ border-bottom: 1px solid #dddddd;
+}
+.panel-default {
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading {
+ color: #333333;
+ background-color: #f5f5f5;
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #dddddd;
+}
+.panel-default > .panel-heading .badge {
+ color: #f5f5f5;
+ background-color: #333333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #dddddd;
+}
+.panel-primary {
+ border-color: #2780e3;
+}
+.panel-primary > .panel-heading {
+ color: #ffffff;
+ background-color: #2780e3;
+ border-color: #2780e3;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #2780e3;
+}
+.panel-primary > .panel-heading .badge {
+ color: #2780e3;
+ background-color: #ffffff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #2780e3;
+}
+.panel-success {
+ border-color: #4e9f15;
+}
+.panel-success > .panel-heading {
+ color: #ffffff;
+ background-color: #3fb618;
+ border-color: #4e9f15;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #4e9f15;
+}
+.panel-success > .panel-heading .badge {
+ color: #3fb618;
+ background-color: #ffffff;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #4e9f15;
+}
+.panel-info {
+ border-color: #7643a8;
+}
+.panel-info > .panel-heading {
+ color: #ffffff;
+ background-color: #9954bb;
+ border-color: #7643a8;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #7643a8;
+}
+.panel-info > .panel-heading .badge {
+ color: #9954bb;
+ background-color: #ffffff;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #7643a8;
+}
+.panel-warning {
+ border-color: #ff4309;
+}
+.panel-warning > .panel-heading {
+ color: #ffffff;
+ background-color: #ff7518;
+ border-color: #ff4309;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ff4309;
+}
+.panel-warning > .panel-heading .badge {
+ color: #ff7518;
+ background-color: #ffffff;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ff4309;
+}
+.panel-danger {
+ border-color: #f0005e;
+}
+.panel-danger > .panel-heading {
+ color: #ffffff;
+ background-color: #ff0039;
+ border-color: #f0005e;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #f0005e;
+}
+.panel-danger > .panel-heading .badge {
+ color: #ff0039;
+ background-color: #ffffff;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #f0005e;
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ height: 100%;
+ width: 100%;
+ border: 0;
+}
+.embed-responsive-16by9 {
+ padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+ padding-bottom: 75%;
+}
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-radius: 0;
+ -webkit-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-lg {
+ padding: 24px;
+ border-radius: 0;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: 0;
+}
+.close {
+ float: right;
+ font-size: 22.5px;
+ font-weight: bold;
+ line-height: 1;
+ color: #ffffff;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+.close:hover,
+.close:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ display: none;
+ overflow: hidden;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ -o-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+ -webkit-transition: -webkit-transform 0.3s ease-out;
+ -moz-transition: -moz-transform 0.3s ease-out;
+ -o-transition: -o-transform 0.3s ease-out;
+ transition: transform 0.3s ease-out;
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #ffffff;
+ border: 1px solid #999999;
+ border: 1px solid transparent;
+ border-radius: 0;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
+ background-clip: padding-box;
+ outline: 0;
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000000;
+}
+.modal-backdrop.fade {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.modal-backdrop.in {
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+.modal-header {
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+ min-height: 16.42857143px;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 20px;
+}
+.modal-footer {
+ padding: 20px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.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;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 1.4;
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.tooltip.in {
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.tooltip.top {
+ margin-top: -3px;
+ padding: 5px 0;
+}
+.tooltip.right {
+ margin-left: 3px;
+ padding: 0 5px;
+}
+.tooltip.bottom {
+ margin-top: 3px;
+ padding: 5px 0;
+}
+.tooltip.left {
+ margin-left: -3px;
+ padding: 0 5px;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #ffffff;
+ text-align: center;
+ text-decoration: none;
+ background-color: #000000;
+ border-radius: 0;
+}
+.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.top-left .tooltip-arrow {
+ bottom: 0;
+ right: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.top-right .tooltip-arrow {
+ bottom: 0;
+ left: 5px;
+ margin-bottom: -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;
+}
+.tooltip.bottom-left .tooltip-arrow {
+ top: 0;
+ right: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+ top: 0;
+ left: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ font-family: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+ font-size: 15px;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ background-color: #ffffff;
+ background-clip: padding-box;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0;
+ -webkit-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: 15px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-radius: -1 -1 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: 11px;
+}
+.popover > .arrow:after {
+ border-width: 10px;
+ content: "";
+}
+.popover.top > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-bottom-width: 0;
+ border-top-color: #999999;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ bottom: -11px;
+}
+.popover.top > .arrow:after {
+ content: " ";
+ bottom: 1px;
+ margin-left: -10px;
+ border-bottom-width: 0;
+ border-top-color: #ffffff;
+}
+.popover.right > .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-left-width: 0;
+ border-right-color: #999999;
+ border-right-color: rgba(0, 0, 0, 0.25);
+}
+.popover.right > .arrow:after {
+ content: " ";
+ left: 1px;
+ bottom: -10px;
+ border-left-width: 0;
+ border-right-color: #ffffff;
+}
+.popover.bottom > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: #999999;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+ top: -11px;
+}
+.popover.bottom > .arrow:after {
+ content: " ";
+ top: 1px;
+ margin-left: -10px;
+ border-top-width: 0;
+ border-bottom-color: #ffffff;
+}
+.popover.left > .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: #999999;
+ border-left-color: rgba(0, 0, 0, 0.25);
+}
+.popover.left > .arrow:after {
+ content: " ";
+ right: 1px;
+ border-right-width: 0;
+ border-left-color: #ffffff;
+ bottom: -10px;
+}
+.carousel {
+ position: relative;
+}
+.carousel-inner {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+}
+.carousel-inner > .item {
+ display: none;
+ position: relative;
+ -webkit-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,
+.carousel-inner > .item > a > img {
+ line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+ .carousel-inner > .item {
+ -webkit-transition: -webkit-transform 0.6s ease-in-out;
+ -moz-transition: -moz-transform 0.6s ease-in-out;
+ -o-transition: -o-transform 0.6s ease-in-out;
+ transition: transform 0.6s ease-in-out;
+ -webkit-backface-visibility: hidden;
+ -moz-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-perspective: 1000;
+ -moz-perspective: 1000;
+ perspective: 1000;
+ }
+ .carousel-inner > .item.next,
+ .carousel-inner > .item.active.right {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.prev,
+ .carousel-inner > .item.active.left {
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.next.left,
+ .carousel-inner > .item.prev.right,
+ .carousel-inner > .item.active {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ left: 0;
+ }
+}
+.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: 0;
+ left: 0;
+ bottom: 0;
+ width: 15%;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ font-size: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+.carousel-control.left {
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+.carousel-control.right {
+ left: auto;
+ right: 0;
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+.carousel-control:hover,
+.carousel-control:focus {
+ outline: 0;
+ color: #ffffff;
+ text-decoration: none;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ z-index: 5;
+ display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+ left: 50%;
+ margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+ right: 50%;
+ margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+ width: 20px;
+ height: 20px;
+ margin-top: -10px;
+ line-height: 1;
+ font-family: serif;
+}
+.carousel-control .icon-prev:before {
+ content: '\2039';
+}
+.carousel-control .icon-next:before {
+ content: '\203a';
+}
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ margin-left: -30%;
+ padding-left: 0;
+ list-style: none;
+ text-align: center;
+}
+.carousel-indicators li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ border: 1px solid #ffffff;
+ border-radius: 10px;
+ cursor: pointer;
+ background-color: #000 \9;
+ background-color: rgba(0, 0, 0, 0);
+}
+.carousel-indicators .active {
+ margin: 0;
+ width: 12px;
+ height: 12px;
+ background-color: #ffffff;
+}
+.carousel-caption {
+ position: absolute;
+ left: 15%;
+ right: 15%;
+ bottom: 20px;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+.carousel-caption .btn {
+ text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-prev,
+ .carousel-control .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -15px;
+ font-size: 30px;
+ }
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .icon-prev {
+ margin-left: -15px;
+ }
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-next {
+ margin-right: -15px;
+ }
+ .carousel-caption {
+ left: 20%;
+ right: 20%;
+ padding-bottom: 30px;
+ }
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+ content: " ";
+ display: table;
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+ clear: both;
+}
+.center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+.hidden {
+ display: none !important;
+}
+.affix {
+ position: fixed;
+}
+@-ms-viewport {
+ width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+ display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+ display: none !important;
+}
+@media (max-width: 767px) {
+ .visible-xs {
+ display: block !important;
+ }
+ table.visible-xs {
+ display: table;
+ }
+ tr.visible-xs {
+ display: table-row !important;
+ }
+ th.visible-xs,
+ td.visible-xs {
+ display: table-cell !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-block {
+ display: block !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline {
+ display: inline !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm {
+ display: block !important;
+ }
+ table.visible-sm {
+ display: table;
+ }
+ tr.visible-sm {
+ display: table-row !important;
+ }
+ th.visible-sm,
+ td.visible-sm {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-block {
+ display: block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md {
+ display: block !important;
+ }
+ table.visible-md {
+ display: table;
+ }
+ tr.visible-md {
+ display: table-row !important;
+ }
+ th.visible-md,
+ td.visible-md {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-block {
+ display: block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg {
+ display: block !important;
+ }
+ table.visible-lg {
+ display: table;
+ }
+ tr.visible-lg {
+ display: table-row !important;
+ }
+ th.visible-lg,
+ td.visible-lg {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-block {
+ display: block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
+.visible-print {
+ display: none !important;
+}
+@media print {
+ .visible-print {
+ display: block !important;
+ }
+ table.visible-print {
+ display: table;
+ }
+ tr.visible-print {
+ display: table-row !important;
+ }
+ th.visible-print,
+ td.visible-print {
+ display: table-cell !important;
+ }
+}
+.visible-print-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-block {
+ display: block !important;
+ }
+}
+.visible-print-inline {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline {
+ display: inline !important;
+ }
+}
+.visible-print-inline-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline-block {
+ display: inline-block !important;
+ }
+}
+@media print {
+ .hidden-print {
+ display: none !important;
+ }
+}
+
+/*# sourceMappingURL=01-vendor.css.map */ \ No newline at end of file
diff --git a/doc-src/02-app.css b/doc-src/02-app.css
new file mode 100644
index 00000000..c7bd41ff
--- /dev/null
+++ b/doc-src/02-app.css
@@ -0,0 +1,43 @@
+.masthead {
+ text-align: center;
+ border-bottom: 0;
+}
+.frontpage .talks div {
+ margin-bottom: 10px;
+}
+.nav-sidebar {
+ background-color: #f0f0f0;
+ margin-bottom: 20px;
+}
+.nav-sidebar li {
+ line-height: 1.1;
+}
+.nav-sidebar li > a,
+.nav-sidebar .nav-header {
+ padding-left: 20px;
+}
+.nav-sidebar .nav-header {
+ margin-top: 1em;
+ font-size: 1.2em;
+ font-weight: bold;
+}
+.nav-sidebar .active > a,
+.nav-sidebar .active > a:hover,
+.nav-sidebar .active > a:focus {
+ color: #fff;
+ background-color: #428bca;
+}
+.tablenum {
+ font-weight: bold;
+}
+.nowrap {
+ white-space: nowrap;
+}
+.page-header {
+ margin: 0px 0 22px;
+}
+.page-header h1 {
+ margin-top: 0px;
+}
+
+/*# sourceMappingURL=02-app.css.map */ \ No newline at end of file
diff --git a/doc-src/02-docstyle.css b/doc-src/02-docstyle.css
deleted file mode 100644
index 4b1ad76a..00000000
--- a/doc-src/02-docstyle.css
+++ /dev/null
@@ -1,20 +0,0 @@
-body {
- padding-top: 60px;
- padding-bottom: 40px;
-}
-
-.tablenum {
- font-weight: bold;
-}
-
-.nowrap {
- white-space: nowrap;
-}
-
-h1 {
- line-height: 1.1;
-}
-
-.page-header {
- margin: 0px 0 22px;
-}
diff --git a/doc-src/_layout.html b/doc-src/_layout.html
index c5fb6376..d0f42994 100644
--- a/doc-src/_layout.html
+++ b/doc-src/_layout.html
@@ -1,36 +1,44 @@
-<div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <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(idxpath)!@">mitmproxy $!VERSION!$ docs</a>
- </div><!--/.nav-collapse -->
- </div>
- </div>
-</div>
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>@!pageTitle!@</title>
+ $!header!$
+ </head>
+ <body>
+ <div class="navbar navbar-default navbar-static-top">
+ <div class="container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="@!urlTo("/index.html")!@">
+ <img height="20px" src="@!urlTo("mitmproxy-long.png")!@"/>
+ </a>
+ </div>
+ <div class="navbar-header navbar-right">
+ <a class="navbar-brand" hre="#">$!VERSION!$ docs</a>
+ </div>
+ </div>
+ </div>
-<div class="container">
- <div class="row">
- <div class="span3">
- <div class="well sidebar-nav">
- $!navbar!$
- </div>
- </div>
- <div class="span9">
- <div class="page-header">
- <h1>@!this.title!@</h1>
+ <div class="container">
+ <div class="row">
+ <div class="col-md-3">
+ $!navbar!$
+ </div>
+ <div class="col-md-9">
+ <div class="page-header">
+ <h1>@!this.title!@</h1>
+ </div>
+ $!body!$
+ </div>
+ </div>
</div>
- $!body!$
- </div>
- </div>
- <hr>
+ <div class="container">
+ <hr>
- <footer>
- <p>@!copyright!@</p>
- </footer>
-</div>
+ <footer>
+ <p>@!copyright!@</p>
+ </footer>
+ </div>
+ </body>
+</html>
diff --git a/doc-src/_nav.html b/doc-src/_nav.html
index 862b0056..a07684cb 100644
--- a/doc-src/_nav.html
+++ b/doc-src/_nav.html
@@ -1,4 +1,4 @@
-<ul class="nav nav-list">
+<ul class="nav nav-sidebar">
$!nav(idxpath, this, state)!$
$!nav("install.html", this, state)!$
$!nav("certinstall.html", this, state)!$
diff --git a/doc-src/_websitelayout.html b/doc-src/_websitelayout.html
deleted file mode 100644
index cd0d23e2..00000000
--- a/doc-src/_websitelayout.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<div class="navbar navbar-fixed-top">
- <div class="navbar-inner">
- <div class="container">
- <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(idxpath)!@">mitmproxy</a>
- <div class="nav">
- <ul class="nav">
- <li $!'class="active"' if this.match("/index.html", True) else ""!$> <a href="@!top!@/index.html">home</a> </li>
- <li $!'class="active"' if this.under("/doc") else ""!$><a href="@!top!@/doc/index.html">docs</a></li>
- <li $!'class="active"' if this.under("/about.html") else ""!$><a href="@!top!@/about.html">about</a></li>
- </ul>
- </div>
- </div>
- </div>
-</div>
-
-<div class="container">
- <div class="row">
-
- <div class="span3">
- <div class="well sidebar-nav">
- $!navbar!$
- </div>
- </div>
- <div class="span9">
- <div class="page-header">
- <h1>@!this.title!@</h1>
- </div>
- $!body!$
- </div>
- </div>
-
- <hr>
-
- <footer>
- <p>@!copyright!@</p>
- </footer>
-</div>
diff --git a/doc-src/dev/architecture.html b/doc-src/dev/architecture.html
index 8ab8821f..ae81b6c6 100644
--- a/doc-src/dev/architecture.html
+++ b/doc-src/dev/architecture.html
@@ -1,8 +1,8 @@
-To give you a better understanding of how mitmproxy works, mitmproxy's high-level architecture is detailed
-in the following graphic:
+To give you a better understanding of how mitmproxy works, mitmproxy's
+high-level architecture is detailed in the following graphic:
-<img src="@!urlTo('schematics/architecture.png')!@">
+<img class="img-responsive" src="@!urlTo('schematics/architecture.png')!@">
<a href="@!urlTo('schematics/architecture.pdf')!@">(architecture.pdf)</a>
<p>Please don't refrain from asking any further
-questions on the mailing list, the IRC channel or the GitHub issue tracker.</p> \ No newline at end of file
+questions on the mailing list, the IRC channel or the GitHub issue tracker.</p>
diff --git a/doc-src/dev/index.py b/doc-src/dev/index.py
index 0f2a6494..ddf100d0 100644
--- a/doc-src/dev/index.py
+++ b/doc-src/dev/index.py
@@ -1,8 +1,8 @@
from countershape import Page
pages = [
- Page("testing.html", "Testing"),
- Page("architecture.html", "Architecture"),
- Page("sslkeylogfile.html", "TLS Master Secrets"),
-# Page("addingviews.html", "Writing Content Views"),
+ Page("testing.html", "Testing"),
+ Page("architecture.html", "Architecture"),
+ Page("sslkeylogfile.html", "TLS Master Secrets"),
+ # Page("addingviews.html", "Writing Content Views"),
]
diff --git a/doc-src/features/index.py b/doc-src/features/index.py
index 693b4439..fdab1714 100644
--- a/doc-src/features/index.py
+++ b/doc-src/features/index.py
@@ -16,4 +16,4 @@ pages = [
Page("tcpproxy.html", "TCP Proxy"),
Page("upstreamcerts.html", "Upstream Certs"),
Page("upstreamproxy.html", "Upstream proxy mode"),
-] \ No newline at end of file
+]
diff --git a/doc-src/howmitmproxy.html b/doc-src/howmitmproxy.html
index 832a61a8..f114e145 100644
--- a/doc-src/howmitmproxy.html
+++ b/doc-src/howmitmproxy.html
@@ -26,7 +26,7 @@ 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"/>
+<img class="img-responsive" src="explicit.png"/>
<table class="table">
<tbody>
@@ -158,7 +158,7 @@ handshake. Luckily, this is almost never an issue in practice.
Lets put all of this together into the complete explicitly proxied HTTPS flow.
-<img src="explicit_https.png"/>
+<img class="img-responsive" src="explicit_https.png"/>
<table class="table">
<tbody>
@@ -250,7 +250,7 @@ mitmproxy, this takes the form of a built-in set of
that know how to talk to each platform's redirection mechanism. Once we have
this information, the process is fairly straight-forward.
-<img src="transparent.png"/>
+<img class="img-responsive" src="transparent.png"/>
<table class="table">
@@ -296,7 +296,7 @@ transparently proxying HTTP, and explicitly proxying HTTPS. We use the routing
mechanism to establish the upstream server address, and then proceed as for
explicit HTTPS connections to establish the CN and SANs, and cope with SNI.
-<img src="transparent_https.png"/>
+<img class="img-responsive" src="transparent_https.png"/>
<table class="table">
diff --git a/doc-src/index.py b/doc-src/index.py
index 52b9c31a..2ae9fafe 100644
--- a/doc-src/index.py
+++ b/doc-src/index.py
@@ -2,7 +2,7 @@ import os
import sys
import datetime
import countershape
-from countershape import Page, Directory, markup, model
+from countershape import Page, Directory, markup
import countershape.template
MITMPROXY_SRC = os.path.abspath(
@@ -15,10 +15,10 @@ ns.VERSION = version.VERSION
if ns.options.website:
ns.idxpath = "doc/index.html"
- this.layout = countershape.Layout("_websitelayout.html")
else:
ns.idxpath = "index.html"
- this.layout = countershape.Layout("_layout.html")
+
+this.layout = countershape.layout.FileLayout("_layout.html")
ns.title = countershape.template.Template(None, "<h1>@!this.title!@</h1>")
this.titlePrefix = "%s - " % version.NAMEVERSION
@@ -37,7 +37,7 @@ def mpath(p):
def example(s):
d = file(mpath(s)).read().rstrip()
extemp = """<div class="example">%s<div class="example_legend">(%s)</div></div>"""
- return extemp%(countershape.template.Syntax("py")(d), s)
+ return extemp % (countershape.template.Syntax("py")(d), s)
ns.example = example
@@ -52,7 +52,8 @@ def nav(page, current, state):
else:
pre = "<li>"
p = state.application.getPage(page)
- return pre + '<a href="%s">%s</a></li>'%(model.UrlTo(page), p.title)
+ return pre + \
+ '<a href="%s">%s</a></li>' % (countershape.widgets.UrlTo(page), p.title)
ns.nav = nav
ns.navbar = countershape.template.File(None, "_nav.html")
diff --git a/doc-src/mitmproxy-long.png b/doc-src/mitmproxy-long.png
new file mode 100644
index 00000000..f9397d1e
--- /dev/null
+++ b/doc-src/mitmproxy-long.png
Binary files differ
diff --git a/doc-src/mitmproxy.html b/doc-src/mitmproxy.html
index d41c1b21..7261c238 100644
--- a/doc-src/mitmproxy.html
+++ b/doc-src/mitmproxy.html
@@ -7,13 +7,13 @@ documentation from any __mitmproxy__ screen.
## Flow list
-The flow list shows an index of captured flows in chronological order.
+The flow list shows an index of captured flows in chronological order.
-<img src="@!urlTo('screenshots/mitmproxy.png')!@"/>
+<img class="img-responsive" src="@!urlTo('screenshots/mitmproxy.png')!@"/>
- __1__: A GET request, returning a 302 Redirect response.
- __2__: A GET request, returning 16.75kb of text/html data.
-- __3__: A replayed request.
+- __3__: A replayed request.
- __4__: Intercepted flows are indicated with orange text. The user may edit
these flows, and then accept them (using the _a_ key) to continue. In this
case, the request has been intercepted on the way to the server.
@@ -32,7 +32,7 @@ interfaces.
The __Flow View__ lets you inspect and manipulate a single flow:
-<img src="@!urlTo('screenshots/mitmproxy-flowview.png')!@"/>
+<img class="img-responsive" src="@!urlTo('screenshots/mitmproxy-flowview.png')!@"/>
- __1__: Flow summary.
- __2__: The Request/Response tabs, showing you which part of the flow you are
@@ -53,11 +53,11 @@ using the _m_ key.
Much of the data that we'd like to interact with in mitmproxy is structured.
For instance, headers, queries and form data can all be thought of as a list of
key/value pairs. Mitmproxy has a built-in editor that lays this type of data
-out in a grid for easy manipulation.
+out in a grid for easy manipulation.
At the moment, the Grid Editor is used in four parts of mitmproxy:
-- Editing request or response headers (_e_ for edit, then _h_ for headers in flow view)
+- Editing request or response headers (_e_ for edit, then _h_ for headers in flow view)
- Editing a query string (_e_ for edit, then _q_ for query in flow view)
- Editing a URL-encoded form (_e_ for edit, then _f_ for form in flow view)
- Editing replacement patterns (_R_ globally)
@@ -65,13 +65,13 @@ At the moment, the Grid Editor is used in four parts of mitmproxy:
If there is is no data, an empty editor will be started to let you add some.
Here is the editor showing the headers from a request:
-<img src="@!urlTo('screenshots/mitmproxy-kveditor.png')!@"/>
+<img class="img-responsive" src="@!urlTo('screenshots/mitmproxy-kveditor.png')!@"/>
To edit, navigate to the key or value you want to modify using the arrow or vi
navigation keys, and press enter. The background color will change to show that
you are in edit mode for the specified field:
-<img src="@!urlTo('screenshots/mitmproxy-kveditor-editmode.png')!@"/>
+<img class="img-responsive" src="@!urlTo('screenshots/mitmproxy-kveditor-editmode.png')!@"/>
Modify the field as desired, then press escape to exit edit mode when you're
done. You can also add a row (_a_ key), delete a row (_d_ key), spawn an
@@ -83,12 +83,12 @@ help (_?_ key) for more.
__mitmproxy__'s interception functionality lets you pause an HTTP request or
response, inspect and modify it, and then accept it to send it on to the server
-or client.
+or client.
### 1: Set an interception pattern
-<img src="@!urlTo('mitmproxy-intercept-filt.png')!@"/>
+<img class="img-responsive" src="@!urlTo('mitmproxy-intercept-filt.png')!@"/>
We press _i_ to set an interception pattern. In this case, the __~q__ filter
pattern tells __mitmproxy__ to intercept all requests. For complete filter
@@ -97,19 +97,19 @@ document, or the built-in help function in __mitmproxy__.
### 2: Intercepted connections are indicated with orange text:
-<img src="@!urlTo('mitmproxy-intercept-mid.png')!@"/>
+<img class="img-responsive" src="@!urlTo('mitmproxy-intercept-mid.png')!@"/>
### 3: You can now view and modify the request:
-<img src="@!urlTo('mitmproxy-intercept-options.png')!@"/>
+<img class="img-responsive" src="@!urlTo('mitmproxy-intercept-options.png')!@"/>
In this case, we viewed the request by selecting it, pressed _e_ for "edit"
and _m_ for "method" to change the HTTP request method.
### 4: Accept the intercept to continue:
-<img src="@!urlTo('mitmproxy-intercept-result.png')!@"/>
+<img class="img-responsive" src="@!urlTo('mitmproxy-intercept-result.png')!@"/>
Finally, we press _a_ to accept the modified request, which is then sent on to
the server. In this case, we changed the request from an HTTP GET to
-OPTIONS, and Google's server has responded with a 405 "Method not allowed".
+OPTIONS, and Google's server has responded with a 405 "Method not allowed".
diff --git a/doc-src/modes.html b/doc-src/modes.html
index 8870009d..b5a38696 100644
--- a/doc-src/modes.html
+++ b/doc-src/modes.html
@@ -9,7 +9,7 @@ variety of scenarios:
Now, which one should you pick? Use this flow chart:
-<img src="@!urlTo('schematics/proxy-modes-flowchart.png')!@"/>
+<img class="img-responsive" src="@!urlTo('schematics/proxy-modes-flowchart.png')!@"/>
<div class="page-header">
<h1>Regular Proxy</h1>
@@ -31,7 +31,7 @@ these cases, you need to use mitmproxy's transparent mode.
If you are proxying an external device, your network will probably look like this:
-<img src="@!urlTo('schematics/proxy-modes-regular.png')!@">
+<img class="img-responsive" src="@!urlTo('schematics/proxy-modes-regular.png')!@">
The square brackets signify the source and destination IP addresses. Your
client explicitly connects to mitmproxy and mitmproxy explicitly connects
@@ -48,7 +48,7 @@ below, a machine running mitmproxy has been inserted between the router and
the internet:
<a href="@!urlTo('schematics/proxy-modes-transparent-1.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-transparent-1.png')!@">
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-transparent-1.png')!@">
</a>
The square brackets signify the source and destination IP addresses. Round
@@ -60,7 +60,7 @@ remove the target information, leaving mitmproxy unable to determine the real
destination.
<a href="@!urlTo('schematics/proxy-modes-transparent-wrong.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-transparent-wrong.png')!@"></a>
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-transparent-wrong.png')!@"></a>
<h2>Common Configurations</h2>
@@ -79,7 +79,7 @@ intact, is to simply configure the client with the mitmproxy box as the
default gateway.
<a href="@!urlTo('schematics/proxy-modes-transparent-2.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-transparent-2.png')!@"></a>
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-transparent-2.png')!@"></a>
In this scenario, we would:
@@ -98,7 +98,7 @@ for your device.
Setting the custom gateway on clients can be automated by serving the settings
out to clients over DHCP. This lets set up an interception network where all
-clients are proxied automatically, which can save time and effort.
+clients are proxied automatically, which can save time and effort.
<div class="well">
@@ -141,7 +141,7 @@ packet filter you're using. In most cases, the configuration will look like
this:
<a href="@!urlTo('schematics/proxy-modes-transparent-3.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-transparent-3.png')!@">
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-transparent-3.png')!@">
</a>
@@ -154,7 +154,7 @@ Internet. Using reverse proxy mode, you can use mitmproxy to act like a normal
HTTP server:
<a href="@!urlTo('schematics/proxy-modes-reverse.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-reverse.png')!@">
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-reverse.png')!@">
</a>
There are various use-cases:
@@ -215,8 +215,8 @@ appliance, you can use mitmproxy's upstream mode. In upstream mode, all
requests are unconditionally transferred to an upstream proxy of your choice.
<a href="@!urlTo('schematics/proxy-modes-upstream.png')!@">
- <img src="@!urlTo('schematics/proxy-modes-upstream.png')!@"></a>
+ <img class="img-responsive" src="@!urlTo('schematics/proxy-modes-upstream.png')!@"></a>
mitmproxy supports both explicit HTTP and explicit HTTPS in upstream proxy
mode. You could in theory chain multiple mitmproxy instances in a row, but
-that doesn't make any sense in practice (i.e. outside of our tests).
+that doesn't make any sense in practice (i.e. outside of our tests).
diff --git a/doc-src/tutorials/gamecenter.html b/doc-src/tutorials/gamecenter.html
index 15380c20..af11b5bb 100644
--- a/doc-src/tutorials/gamecenter.html
+++ b/doc-src/tutorials/gamecenter.html
@@ -15,14 +15,14 @@ Worm](http://itunes.apple.com/us/app/super-mega-worm/id388541990?mt=8) - a
great little retro-apocalyptic sidescroller for the iPhone:
<center>
- <img src="@!urlTo('tutorials/supermega.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/supermega.png')!@"/>
</center>
After finishing a game (take your time), watch the traffic flowing through
mitmproxy:
<center>
- <img src="@!urlTo('tutorials/one.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/one.png')!@"/>
</center>
We see a bunch of things we might expect - initialisation, the retrieval of
@@ -97,7 +97,7 @@ replay.
## The glorious result and some intrigue
<center>
- <img src="@!urlTo('tutorials/leaderboard.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/leaderboard.png')!@"/>
</center>
And that's it - according to the records, I am the greatest Super Mega Worm
diff --git a/doc-src/tutorials/index.py b/doc-src/tutorials/index.py
index 1cb04679..3bfe7c12 100644
--- a/doc-src/tutorials/index.py
+++ b/doc-src/tutorials/index.py
@@ -4,4 +4,4 @@ pages = [
Page("30second.html", "Client playback: a 30 second example"),
Page("gamecenter.html", "Setting highscores on Apple's GameCenter"),
Page("transparent-dhcp.html", "Transparently proxify virtual machines")
-] \ No newline at end of file
+]
diff --git a/doc-src/tutorials/transparent-dhcp.html b/doc-src/tutorials/transparent-dhcp.html
index c34dd700..6c648c0d 100644
--- a/doc-src/tutorials/transparent-dhcp.html
+++ b/doc-src/tutorials/transparent-dhcp.html
@@ -4,10 +4,10 @@ This walkthrough illustrates how to set up transparent proxying with mitmproxy.
The network setup is simple: `internet <--> proxy vm <--> (virtual) internal network`.
For the proxy machine, *eth0* represents the outgoing network. *eth1* is connected to the internal network that will be proxified, using a static ip (192.168.3.1).
<hr>VirtualBox configuration:
- <img src="@!urlTo('tutorials/transparent-dhcp/step1_vbox_eth0.png')!@"/><br><br>
- <img src="@!urlTo('tutorials/transparent-dhcp/step1_vbox_eth1.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/transparent-dhcp/step1_vbox_eth0.png')!@"/><br><br>
+ <img class="img-responsive" src="@!urlTo('tutorials/transparent-dhcp/step1_vbox_eth1.png')!@"/>
<br>Proxy VM:
- <img src="@!urlTo('tutorials/transparent-dhcp/step1_proxy.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/transparent-dhcp/step1_proxy.png')!@"/>
<hr>
2. **Configure DHCP and DNS**
We use dnsmasq to provide DHCP and DNS in our internal network.
@@ -34,7 +34,7 @@ This walkthrough illustrates how to set up transparent proxying with mitmproxy.
`sudo service dnsmasq restart`
<hr>
Your proxied machine's network settings should now look similar to this:
- <img src="@!urlTo('tutorials/transparent-dhcp/step2_proxied_vm.png')!@"/>
+ <img class="img-responsive" src="@!urlTo('tutorials/transparent-dhcp/step2_proxied_vm.png')!@"/>
<hr>
3. **Set up traffic redirection to mitmproxy**
diff --git a/examples/add_header.py b/examples/add_header.py
index 291741cb..0c0593d1 100644
--- a/examples/add_header.py
+++ b/examples/add_header.py
@@ -1,2 +1,2 @@
def response(context, flow):
- flow.response.headers["newheader"] = ["foo"] \ No newline at end of file
+ flow.response.headers["newheader"] = ["foo"]
diff --git a/examples/change_upstream_proxy.py b/examples/change_upstream_proxy.py
index 74a43bd0..7782dd84 100644
--- a/examples/change_upstream_proxy.py
+++ b/examples/change_upstream_proxy.py
@@ -1,10 +1,13 @@
# This scripts demonstrates how mitmproxy can switch to a second/different upstream proxy
# in upstream proxy mode.
#
-# Usage: mitmdump -U http://default-upstream-proxy.local:8080/ -s "change_upstream_proxy.py host"
+# Usage: mitmdump -U http://default-upstream-proxy.local:8080/ -s
+# "change_upstream_proxy.py host"
from libmproxy.protocol.http import send_connect_request
alternative_upstream_proxy = ("localhost", 8082)
+
+
def should_redirect(flow):
return flow.request.host == "example.com"
@@ -15,7 +18,12 @@ def request(context, flow):
# If you want to change the target server, you should modify flow.request.host and flow.request.port
# flow.live.change_server should only be used by inline scripts to change the upstream proxy,
# unless you are sure that you know what you are doing.
- server_changed = flow.live.change_server(alternative_upstream_proxy, persistent_change=True)
+ server_changed = flow.live.change_server(
+ alternative_upstream_proxy,
+ persistent_change=True)
if flow.request.scheme == "https" and server_changed:
- send_connect_request(flow.live.c.server_conn, flow.request.host, flow.request.port)
+ send_connect_request(
+ flow.live.c.server_conn,
+ flow.request.host,
+ flow.request.port)
flow.live.c.establish_ssl(server=True)
diff --git a/examples/dns_spoofing.py b/examples/dns_spoofing.py
index cfba7c54..dddf172c 100644
--- a/examples/dns_spoofing.py
+++ b/examples/dns_spoofing.py
@@ -25,11 +25,13 @@ mitmproxy -p 443 -R https2http://localhost:8000
def request(context, flow):
if flow.client_conn.ssl_established:
# TLS SNI or Host header
- flow.request.host = flow.client_conn.connection.get_servername() or flow.request.pretty_host(hostheader=True)
+ flow.request.host = flow.client_conn.connection.get_servername(
+ ) or flow.request.pretty_host(hostheader=True)
- # If you use a https2http location as default destination, these attributes need to be corrected as well:
+ # If you use a https2http location as default destination, these
+ # attributes need to be corrected as well:
flow.request.port = 443
flow.request.scheme = "https"
else:
# Host header
- flow.request.host = flow.request.pretty_host(hostheader=True) \ No newline at end of file
+ flow.request.host = flow.request.pretty_host(hostheader=True)
diff --git a/examples/dup_and_replay.py b/examples/dup_and_replay.py
index 3d9279cc..9ba91d3b 100644
--- a/examples/dup_and_replay.py
+++ b/examples/dup_and_replay.py
@@ -1,4 +1,4 @@
def request(context, flow):
f = context.duplicate_flow(flow)
f.request.path = "/changed"
- context.replay_request(f) \ No newline at end of file
+ context.replay_request(f)
diff --git a/examples/filt.py b/examples/filt.py
index cce2a48a..d2daf9a2 100644
--- a/examples/filt.py
+++ b/examples/filt.py
@@ -3,12 +3,14 @@
from libmproxy import filt
+
def start(context, argv):
- if len(argv) != 2:
- raise ValueError("Usage: -s 'filt.py FILTER'")
- context.filter = filt.parse(argv[1])
+ if len(argv) != 2:
+ raise ValueError("Usage: -s 'filt.py FILTER'")
+ context.filter = filt.parse(argv[1])
+
def response(context, flow):
- if flow.match(context.filter):
- print("Flow matches filter:")
- print(flow)
+ if flow.match(context.filter):
+ print("Flow matches filter:")
+ print(flow)
diff --git a/examples/flowbasic b/examples/flowbasic
index c71debc9..083d7663 100755
--- a/examples/flowbasic
+++ b/examples/flowbasic
@@ -36,7 +36,8 @@ class MyMaster(flow.FlowMaster):
config = proxy.ProxyConfig(
port=8080,
- cadir="~/.mitmproxy/" # use ~/.mitmproxy/mitmproxy-ca.pem as default CA file.
+ # use ~/.mitmproxy/mitmproxy-ca.pem as default CA file.
+ cadir="~/.mitmproxy/"
)
state = flow.State()
server = ProxyServer(config)
diff --git a/examples/flowwriter.py b/examples/flowwriter.py
index f411ec45..be2f285e 100644
--- a/examples/flowwriter.py
+++ b/examples/flowwriter.py
@@ -17,4 +17,4 @@ def start(context, argv):
def response(context, flow):
if random.choice([True, False]):
- context.flow_writer.add(flow) \ No newline at end of file
+ context.flow_writer.add(flow)
diff --git a/examples/har_extractor.py b/examples/har_extractor.py
index 5c228ece..1a76fa1f 100644
--- a/examples/har_extractor.py
+++ b/examples/har_extractor.py
@@ -83,7 +83,8 @@ def response(context, flow):
# Calculate the connect_time for this server_conn. Afterwards add it to
# seen list, in order to avoid the connect_time being present in entries
# that use an existing connection.
- connect_time = flow.server_conn.timestamp_tcp_setup - flow.server_conn.timestamp_start
+ connect_time = flow.server_conn.timestamp_tcp_setup - \
+ flow.server_conn.timestamp_start
context.seen_server.add(flow.server_conn)
if flow.server_conn.timestamp_ssl_setup is not None:
@@ -91,7 +92,8 @@ def response(context, flow):
# the start of the successful tcp setup and the successful ssl
# setup. If no ssl setup has been made it is left as -1 since it
# doesn't apply to this connection.
- ssl_time = flow.server_conn.timestamp_ssl_setup - flow.server_conn.timestamp_tcp_setup
+ ssl_time = flow.server_conn.timestamp_ssl_setup - \
+ flow.server_conn.timestamp_tcp_setup
# Calculate the raw timings from the different timestamps present in the
# request and response object. For lack of a way to measure it dns timings
@@ -110,7 +112,8 @@ def response(context, flow):
# HAR timings are integers in ms, so we have to re-encode the raw timings to
# that format.
- timings = dict([(key, int(1000 * value)) for key, value in timings_raw.iteritems()])
+ timings = dict([(key, int(1000 * value))
+ for key, value in timings_raw.iteritems()])
# The full_time is the sum of all timings. Timings set to -1 will be ignored
# as per spec.
@@ -119,20 +122,27 @@ def response(context, flow):
if item > -1:
full_time += item
- started_date_time = datetime.fromtimestamp(flow.request.timestamp_start, tz=utc).isoformat()
+ started_date_time = datetime.fromtimestamp(
+ flow.request.timestamp_start,
+ tz=utc).isoformat()
- request_query_string = [{"name": k, "value": v} for k, v in flow.request.get_query()]
+ request_query_string = [{"name": k, "value": v}
+ for k, v in flow.request.get_query()]
request_http_version = ".".join([str(v) for v in flow.request.httpversion])
# Cookies are shaped as tuples by MITMProxy.
- request_cookies = [{"name": k.strip(), "value": v[0]} for k, v in (flow.request.get_cookies() or {}).iteritems()]
+ request_cookies = [{"name": k.strip(), "value": v[0]}
+ for k, v in (flow.request.get_cookies() or {}).iteritems()]
request_headers = [{"name": k, "value": v} for k, v in flow.request.headers]
request_headers_size = len(str(flow.request.headers))
request_body_size = len(flow.request.content)
- response_http_version = ".".join([str(v) for v in flow.response.httpversion])
+ response_http_version = ".".join(
+ [str(v) for v in flow.response.httpversion])
# Cookies are shaped as tuples by MITMProxy.
- response_cookies = [{"name": k.strip(), "value": v[0]} for k, v in (flow.response.get_cookies() or {}).iteritems()]
- response_headers = [{"name": k, "value": v} for k, v in flow.response.headers]
+ response_cookies = [{"name": k.strip(), "value": v[0]}
+ for k, v in (flow.response.get_cookies() or {}).iteritems()]
+ response_headers = [{"name": k, "value": v}
+ for k, v in flow.response.headers]
response_headers_size = len(str(flow.response.headers))
response_body_size = len(flow.response.content)
response_body_decoded_size = len(flow.response.get_decoded_content())
@@ -140,33 +150,43 @@ def response(context, flow):
response_mime_type = flow.response.headers.get_first('Content-Type', '')
response_redirect_url = flow.response.headers.get_first('Location', '')
- entry = HAR.entries({"startedDateTime": started_date_time,
- "time": full_time,
- "request": {"method": flow.request.method,
- "url": flow.request.url,
- "httpVersion": request_http_version,
- "cookies": request_cookies,
- "headers": request_headers,
- "queryString": request_query_string,
- "headersSize": request_headers_size,
- "bodySize": request_body_size, },
- "response": {"status": flow.response.code,
- "statusText": flow.response.msg,
- "httpVersion": response_http_version,
- "cookies": response_cookies,
- "headers": response_headers,
- "content": {"size": response_body_size,
- "compression": response_body_compression,
- "mimeType": response_mime_type},
- "redirectURL": response_redirect_url,
- "headersSize": response_headers_size,
- "bodySize": response_body_size, },
- "cache": {},
- "timings": timings, })
+ entry = HAR.entries(
+ {
+ "startedDateTime": started_date_time,
+ "time": full_time,
+ "request": {
+ "method": flow.request.method,
+ "url": flow.request.url,
+ "httpVersion": request_http_version,
+ "cookies": request_cookies,
+ "headers": request_headers,
+ "queryString": request_query_string,
+ "headersSize": request_headers_size,
+ "bodySize": request_body_size,
+ },
+ "response": {
+ "status": flow.response.code,
+ "statusText": flow.response.msg,
+ "httpVersion": response_http_version,
+ "cookies": response_cookies,
+ "headers": response_headers,
+ "content": {
+ "size": response_body_size,
+ "compression": response_body_compression,
+ "mimeType": response_mime_type},
+ "redirectURL": response_redirect_url,
+ "headersSize": response_headers_size,
+ "bodySize": response_body_size,
+ },
+ "cache": {},
+ "timings": timings,
+ })
# If the current url is in the page list of context.HARLog or does not have
# a referrer we add it as a new pages object.
- if flow.request.url in context.HARLog.get_page_list() or flow.request.headers.get('Referer', None) is None:
+ if flow.request.url in context.HARLog.get_page_list() or flow.request.headers.get(
+ 'Referer',
+ None) is None:
page_id = context.HARLog.create_page_id()
context.HARLog.add(
HAR.pages({
@@ -231,4 +251,4 @@ def print_attributes(obj, filter_string=None, hide_privates=False):
if filter_string is not None and filter_string not in attr:
continue
value = getattr(obj, attr)
- print "%s.%s" % ('obj', attr), value, type(value) \ No newline at end of file
+ print "%s.%s" % ('obj', attr), value, type(value)
diff --git a/examples/iframe_injector.py b/examples/iframe_injector.py
index 72563bed..b2fa2d26 100644
--- a/examples/iframe_injector.py
+++ b/examples/iframe_injector.py
@@ -16,7 +16,12 @@ def response(context, flow):
with decoded(flow.response): # Remove content encoding (gzip, ...)
html = BeautifulSoup(flow.response.content)
if html.body:
- iframe = html.new_tag("iframe", src=context.iframe_url, frameborder=0, height=0, width=0)
+ iframe = html.new_tag(
+ "iframe",
+ src=context.iframe_url,
+ frameborder=0,
+ height=0,
+ width=0)
html.body.insert(0, iframe)
flow.response.content = str(html)
- context.log("Iframe inserted.") \ No newline at end of file
+ context.log("Iframe inserted.")
diff --git a/examples/ignore_websocket.py b/examples/ignore_websocket.py
index f7a94bdf..b52f18f8 100644
--- a/examples/ignore_websocket.py
+++ b/examples/ignore_websocket.py
@@ -24,6 +24,7 @@ def done(context):
HTTPRequest._headers_to_strip_off.append("Connection")
HTTPRequest._headers_to_strip_off.append("Upgrade")
+
@concurrent
def response(context, flow):
value = flow.response.headers.get_first("Connection", None)
@@ -32,4 +33,4 @@ def response(context, flow):
flow.client_conn.send(flow.response.assemble())
# ...and then delegate to tcp passthrough.
TCPHandler(flow.live.c, log=False).handle_messages()
- flow.reply(KILL) \ No newline at end of file
+ flow.reply(KILL)
diff --git a/examples/mitmproxywrapper.py b/examples/mitmproxywrapper.py
index 2f3750e9..239642d7 100755
--- a/examples/mitmproxywrapper.py
+++ b/examples/mitmproxywrapper.py
@@ -14,23 +14,29 @@ import contextlib
import os
import sys
+
class Wrapper(object):
-
+
def __init__(self, port, extra_arguments=None):
self.port = port
self.extra_arguments = extra_arguments
def run_networksetup_command(self, *arguments):
- return subprocess.check_output(['sudo', 'networksetup'] + list(arguments))
+ return subprocess.check_output(
+ ['sudo', 'networksetup'] + list(arguments))
def proxy_state_for_service(self, service):
- state = self.run_networksetup_command('-getwebproxy', service).splitlines()
+ state = self.run_networksetup_command(
+ '-getwebproxy',
+ service).splitlines()
return dict([re.findall(r'([^:]+): (.*)', line)[0] for line in state])
def enable_proxy_for_service(self, service):
print 'Enabling proxy on {}...'.format(service)
for subcommand in ['-setwebproxy', '-setsecurewebproxy']:
- self.run_networksetup_command(subcommand, service, '127.0.0.1', str(self.port))
+ self.run_networksetup_command(
+ subcommand, service, '127.0.0.1', str(
+ self.port))
def disable_proxy_for_service(self, service):
print 'Disabling proxy on {}...'.format(service)
@@ -39,14 +45,20 @@ class Wrapper(object):
def interface_name_to_service_name_map(self):
order = self.run_networksetup_command('-listnetworkserviceorder')
- mapping = re.findall(r'\(\d+\)\s(.*)$\n\(.*Device: (.+)\)$', order, re.MULTILINE)
+ mapping = re.findall(
+ r'\(\d+\)\s(.*)$\n\(.*Device: (.+)\)$',
+ order,
+ re.MULTILINE)
return dict([(b, a) for (a, b) in mapping])
def run_command_with_input(self, command, input):
- popen = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ popen = subprocess.Popen(
+ command,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
(stdout, stderr) = popen.communicate(input)
return stdout
-
+
def primary_interace_name(self):
scutil_script = 'get State:/Network/Global/IPv4\nd.show\n'
stdout = self.run_command_with_input('/usr/sbin/scutil', scutil_script)
@@ -54,13 +66,15 @@ class Wrapper(object):
return interface
def primary_service_name(self):
- return self.interface_name_to_service_name_map()[self.primary_interace_name()]
+ return self.interface_name_to_service_name_map()[
+ self.primary_interace_name()]
def proxy_enabled_for_service(self, service):
return self.proxy_state_for_service(service)['Enabled'] == 'Yes'
def toggle_proxy(self):
- new_state = not self.proxy_enabled_for_service(self.primary_service_name())
+ new_state = not self.proxy_enabled_for_service(
+ self.primary_service_name())
for service_name in self.connected_service_names():
if self.proxy_enabled_for_service(service_name) and not new_state:
self.disable_proxy_for_service(service_name)
@@ -74,8 +88,11 @@ class Wrapper(object):
service_names = []
for service_id in service_ids:
- scutil_script = 'show Setup:/Network/Service/{}\n'.format(service_id)
- stdout = self.run_command_with_input('/usr/sbin/scutil', scutil_script)
+ scutil_script = 'show Setup:/Network/Service/{}\n'.format(
+ service_id)
+ stdout = self.run_command_with_input(
+ '/usr/sbin/scutil',
+ scutil_script)
service_name, = re.findall(r'UserDefinedName\s*:\s*(.+)', stdout)
service_names.append(service_name)
@@ -102,7 +119,7 @@ class Wrapper(object):
for service_name in connected_service_names:
if not self.proxy_enabled_for_service(service_name):
self.enable_proxy_for_service(service_name)
-
+
yield
for service_name in connected_service_names:
@@ -119,15 +136,23 @@ class Wrapper(object):
def main(cls):
parser = argparse.ArgumentParser(
description='Helper tool for OS X proxy configuration and mitmproxy.',
- epilog='Any additional arguments will be passed on unchanged to mitmproxy.'
- )
- parser.add_argument('-t', '--toggle', action='store_true', help='just toggle the proxy configuration')
+ epilog='Any additional arguments will be passed on unchanged to mitmproxy.')
+ parser.add_argument(
+ '-t',
+ '--toggle',
+ action='store_true',
+ help='just toggle the proxy configuration')
# parser.add_argument('--honeyproxy', action='store_true', help='run honeyproxy instead of mitmproxy')
- parser.add_argument('-p', '--port', type=int, help='override the default port of 8080', default=8080)
+ parser.add_argument(
+ '-p',
+ '--port',
+ type=int,
+ help='override the default port of 8080',
+ default=8080)
args, extra_arguments = parser.parse_known_args()
wrapper = cls(port=args.port, extra_arguments=extra_arguments)
-
+
if args.toggle:
wrapper.toggle_proxy()
# elif args.honeyproxy:
@@ -139,4 +164,3 @@ class Wrapper(object):
if __name__ == '__main__':
Wrapper.ensure_superuser()
Wrapper.main()
-
diff --git a/examples/modify_form.py b/examples/modify_form.py
index 3d93e392..37ba2fac 100644
--- a/examples/modify_form.py
+++ b/examples/modify_form.py
@@ -1,6 +1,7 @@
def request(context, flow):
- if "application/x-www-form-urlencoded" in flow.request.headers["content-type"]:
+ if "application/x-www-form-urlencoded" in flow.request.headers[
+ "content-type"]:
form = flow.request.get_form_urlencoded()
form["mitmproxy"] = ["rocks"]
- flow.request.set_form_urlencoded(form) \ No newline at end of file
+ flow.request.set_form_urlencoded(form)
diff --git a/examples/modify_querystring.py b/examples/modify_querystring.py
index 1dd4807a..7f31a48f 100644
--- a/examples/modify_querystring.py
+++ b/examples/modify_querystring.py
@@ -3,4 +3,4 @@ def request(context, flow):
q = flow.request.get_query()
if q:
q["mitmproxy"] = ["rocks"]
- flow.request.set_query(q) \ No newline at end of file
+ flow.request.set_query(q)
diff --git a/examples/modify_response_body.py b/examples/modify_response_body.py
index 4afd0421..68d3d4ab 100644
--- a/examples/modify_response_body.py
+++ b/examples/modify_response_body.py
@@ -6,10 +6,13 @@ from libmproxy.protocol.http import decoded
def start(context, argv):
if len(argv) != 3:
raise ValueError('Usage: -s "modify-response-body.py old new"')
- # You may want to use Python's argparse for more sophisticated argument parsing.
+ # You may want to use Python's argparse for more sophisticated argument
+ # parsing.
context.old, context.new = argv[1], argv[2]
def response(context, flow):
with decoded(flow.response): # automatically decode gzipped responses.
- flow.response.content = flow.response.content.replace(context.old, context.new) \ No newline at end of file
+ flow.response.content = flow.response.content.replace(
+ context.old,
+ context.new)
diff --git a/examples/nonblocking.py b/examples/nonblocking.py
index 481c0407..f96b7f40 100644
--- a/examples/nonblocking.py
+++ b/examples/nonblocking.py
@@ -6,4 +6,4 @@ from libmproxy.script import concurrent
def request(context, flow):
print "handle request: %s%s" % (flow.request.host, flow.request.path)
time.sleep(5)
- print "start request: %s%s" % (flow.request.host, flow.request.path) \ No newline at end of file
+ print "start request: %s%s" % (flow.request.host, flow.request.path)
diff --git a/examples/proxapp.py b/examples/proxapp.py
index d777d522..4d8e7b58 100644
--- a/examples/proxapp.py
+++ b/examples/proxapp.py
@@ -21,4 +21,4 @@ def start(context, argv):
# SSL works too, but the magic domain needs to be resolvable from the mitmproxy machine due to mitmproxy's design.
# mitmproxy will connect to said domain and use serve its certificate (unless --no-upstream-cert is set)
# but won't send any data.
- context.app_registry.add(app, "example.com", 443) \ No newline at end of file
+ context.app_registry.add(app, "example.com", 443)
diff --git a/examples/read_dumpfile b/examples/read_dumpfile
index f5818483..9da604cc 100644
--- a/examples/read_dumpfile
+++ b/examples/read_dumpfile
@@ -4,7 +4,8 @@
#
from libmproxy import flow
-import json, sys
+import json
+import sys
with open("logfile", "rb") as logfile:
freader = flow.FlowReader(logfile)
@@ -14,5 +15,5 @@ with open("logfile", "rb") as logfile:
print(f.request.host)
json.dump(f.get_state(), sys.stdout, indent=4)
print ""
- except flow.FlowReadError, v:
+ except flow.FlowReadError as v:
print "Flow file corrupted. Stopped loading."
diff --git a/examples/redirect_requests.py b/examples/redirect_requests.py
index d9a3bfc5..48512f1b 100644
--- a/examples/redirect_requests.py
+++ b/examples/redirect_requests.py
@@ -8,7 +8,8 @@ This example shows two ways to redirect flows to other destinations.
def request(context, flow):
# pretty_host(hostheader=True) takes the Host: header of the request into account,
- # which is useful in transparent mode where we usually only have the IP otherwise.
+ # which is useful in transparent mode where we usually only have the IP
+ # otherwise.
# Method 1: Answer with a locally generated response
if flow.request.pretty_host(hostheader=True).endswith("example.com"):
diff --git a/examples/stream.py b/examples/stream.py
index 7d5efc1e..3adbe437 100644
--- a/examples/stream.py
+++ b/examples/stream.py
@@ -2,4 +2,4 @@ def responseheaders(context, flow):
"""
Enables streaming for all responses.
"""
- flow.response.stream = True \ No newline at end of file
+ flow.response.stream = True
diff --git a/examples/stream_modify.py b/examples/stream_modify.py
index 56d26e6d..e3f1f3cf 100644
--- a/examples/stream_modify.py
+++ b/examples/stream_modify.py
@@ -11,7 +11,7 @@ Be aware that content replacement isn't trivial:
def modify(chunks):
"""
chunks is a generator that can be used to iterate over all chunks.
- Each chunk is a (prefix, content, suffix) tuple.
+ Each chunk is a (prefix, content, suffix) tuple.
For example, in the case of chunked transfer encoding: ("3\r\n","foo","\r\n")
"""
for prefix, content, suffix in chunks:
@@ -19,4 +19,4 @@ def modify(chunks):
def responseheaders(context, flow):
- flow.response.stream = modify \ No newline at end of file
+ flow.response.stream = modify
diff --git a/examples/stub.py b/examples/stub.py
index c5cdad9c..d5502a47 100644
--- a/examples/stub.py
+++ b/examples/stub.py
@@ -1,12 +1,15 @@
"""
This is a script stub, with definitions for all events.
"""
+
+
def start(context, argv):
"""
Called once on script startup, before any other events.
"""
context.log("start")
+
def clientconnect(context, conn_handler):
"""
Called when a client initiates a connection to the proxy. Note that a
@@ -14,6 +17,7 @@ def clientconnect(context, conn_handler):
"""
context.log("clientconnect")
+
def serverconnect(context, conn_handler):
"""
Called when the proxy initiates a connection to the target server. Note that a
@@ -21,6 +25,7 @@ def serverconnect(context, conn_handler):
"""
context.log("serverconnect")
+
def request(context, flow):
"""
Called when a client request has been received.
@@ -36,12 +41,14 @@ def responseheaders(context, flow):
"""
context.log("responseheaders")
+
def response(context, flow):
"""
Called when a server response has been received.
"""
context.log("response")
+
def error(context, flow):
"""
Called when a flow error has occured, e.g. invalid server responses, or
@@ -50,12 +57,14 @@ def error(context, flow):
"""
context.log("error")
+
def clientdisconnect(context, conn_handler):
"""
Called when a client disconnects from the proxy.
"""
context.log("clientdisconnect")
+
def done(context):
"""
Called once on script shutdown, after any other events.
diff --git a/examples/upsidedownternet.py b/examples/upsidedownternet.py
index 738eb11f..a6de97e4 100644
--- a/examples/upsidedownternet.py
+++ b/examples/upsidedownternet.py
@@ -2,6 +2,7 @@ import cStringIO
from PIL import Image
from libmproxy.protocol.http import decoded
+
def response(context, flow):
if flow.response.headers.get_first("content-type", "").startswith("image"):
with decoded(flow.response): # automatically decode gzipped responses.
@@ -13,4 +14,4 @@ def response(context, flow):
flow.response.content = s2.getvalue()
flow.response.headers["content-type"] = ["image/png"]
except: # Unknown image types etc.
- pass \ No newline at end of file
+ pass
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index c68745a9..eb24bed7 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -65,7 +65,7 @@ def parse_replace_hook(s):
patt, regex, replacement = _parse_hook(s)
try:
re.compile(regex)
- except re.error, e:
+ except re.error as e:
raise ParseException("Malformed replacement regex: %s" % str(e.message))
return patt, regex, replacement
@@ -127,7 +127,6 @@ def parse_server_spec_special(url):
return ret
-
def get_common_options(options):
stickycookie, stickyauth = None, None
if options.stickycookie_filt:
@@ -142,17 +141,17 @@ def get_common_options(options):
for i in options.replace:
try:
p = parse_replace_hook(i)
- except ParseException, e:
+ except ParseException as e:
raise configargparse.ArgumentTypeError(e.message)
reps.append(p)
for i in options.replace_file:
try:
patt, rex, path = parse_replace_hook(i)
- except ParseException, e:
+ except ParseException as e:
raise configargparse.ArgumentTypeError(e.message)
try:
v = open(path, "rb").read()
- except IOError, e:
+ except IOError as e:
raise configargparse.ArgumentTypeError(
"Could not read replace file: %s" % path
)
@@ -162,7 +161,7 @@ def get_common_options(options):
for i in options.setheader:
try:
p = parse_setheader(i)
- except ParseException, e:
+ except ParseException as e:
raise configargparse.ArgumentTypeError(e.message)
setheaders.append(p)
@@ -221,7 +220,7 @@ def common_options(parser):
parser.add_argument(
"--cadir",
action="store", type=str, dest="cadir", default=config.CA_DIR,
- help="Location of the default mitmproxy CA files. (%s)"%config.CA_DIR
+ help="Location of the default mitmproxy CA files. (%s)" % config.CA_DIR
)
parser.add_argument(
"--host",
@@ -482,9 +481,10 @@ def common_options(parser):
)
group.add_argument(
"--replay-ignore-host",
- action="store_true", dest="replay_ignore_host", default=False,
- help="Ignore request's destination host while searching for a saved flow to replay"
- )
+ action="store_true",
+ dest="replay_ignore_host",
+ default=False,
+ help="Ignore request's destination host while searching for a saved flow to replay")
group = parser.add_argument_group(
"Replacements",
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index 527ed07d..8f39e283 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -85,10 +85,10 @@ class ConsoleState(flow.State):
return self.view[pos], pos
def get_next(self, pos):
- return self.get_from_pos(pos+1)
+ return self.get_from_pos(pos + 1)
def get_prev(self, pos):
- return self.get_from_pos(pos-1)
+ return self.get_from_pos(pos - 1)
def delete_flow(self, f):
if f in self.view and self.view.index(f) <= self.focus:
@@ -255,7 +255,7 @@ class ConsoleMaster(flow.FlowMaster):
try:
f = file(path, mode)
self.start_stream(f, None)
- except IOError, v:
+ except IOError as v:
return str(v)
self.stream_path = path
@@ -263,22 +263,24 @@ class ConsoleMaster(flow.FlowMaster):
status, val = s.run(method, f)
if val:
if status:
- self.add_event("Method %s return: %s"%(method, val), "debug")
+ self.add_event("Method %s return: %s" % (method, val), "debug")
else:
- self.add_event("Method %s error: %s"%(method, val[1]), "error")
+ self.add_event(
+ "Method %s error: %s" %
+ (method, val[1]), "error")
def run_script_once(self, command, f):
if not command:
return
- self.add_event("Running script on flow: %s"%command, "debug")
+ self.add_event("Running script on flow: %s" % command, "debug")
try:
s = script.Script(command, self)
- except script.ScriptError, v:
+ except script.ScriptError as v:
signals.status_message.send(
message = "Error loading script."
)
- self.add_event("Error loading script:\n%s"%v.args[0], "error")
+ self.add_event("Error loading script:\n%s" % v.args[0], "error")
return
if f.request:
@@ -562,7 +564,7 @@ class ConsoleMaster(flow.FlowMaster):
for i in flows:
fw.add(i)
f.close()
- except IOError, v:
+ except IOError as v:
signals.status_message.send(message=v.strerror)
def save_one_flow(self, path, flow):
@@ -575,13 +577,13 @@ class ConsoleMaster(flow.FlowMaster):
if not path:
return
ret = self.load_flows_path(path)
- return ret or "Flows loaded from %s"%path
+ return ret or "Flows loaded from %s" % path
def load_flows_path(self, path):
reterr = None
try:
flow.FlowMaster.load_flows_file(self, path)
- except flow.FlowReadError, v:
+ except flow.FlowReadError as v:
reterr = str(v)
signals.flowlist_change.send(self)
return reterr
@@ -652,7 +654,8 @@ class ConsoleMaster(flow.FlowMaster):
)
def process_flow(self, f):
- if self.state.intercept and f.match(self.state.intercept) and not f.request.is_replay:
+ if self.state.intercept and f.match(
+ self.state.intercept) and not f.request.is_replay:
f.intercept(self)
else:
f.reply()
@@ -674,7 +677,7 @@ class ConsoleMaster(flow.FlowMaster):
self.eventlist.append(e)
if len(self.eventlist) > EVENTLOG_SIZE:
self.eventlist.pop(0)
- self.eventlist.set_focus(len(self.eventlist)-1)
+ self.eventlist.set_focus(len(self.eventlist) - 1)
# Handlers
def handle_error(self, f):
diff --git a/libmproxy/console/common.py b/libmproxy/console/common.py
index b920a11f..3180170d 100644
--- a/libmproxy/console/common.py
+++ b/libmproxy/console/common.py
@@ -164,7 +164,7 @@ def raw_format_flow(f, focus, extended, padding):
4: "code_400",
5: "code_500",
}
- ccol = codes.get(f["resp_code"]/100, "code_other")
+ ccol = codes.get(f["resp_code"] / 100, "code_other")
resp.append(fcol(SYMBOL_RETURN, ccol))
if f["resp_is_replay"]:
resp.append(fcol(SYMBOL_REPLAY, "replay"))
@@ -200,7 +200,7 @@ def save_data(path, data, master, state):
try:
with file(path, "wb") as f:
f.write(data)
- except IOError, v:
+ except IOError as v:
signals.status_message.send(message=v.strerror)
@@ -214,7 +214,7 @@ def ask_save_overwite(path, data, master, state):
save_data(path, data, master, state)
signals.status_prompt_onekey.send(
- prompt = "'"+path+"' already exists. Overwite?",
+ prompt = "'" + path + "' already exists. Overwite?",
keys = (
("yes", "y"),
("no", "n"),
diff --git a/libmproxy/console/contentview.py b/libmproxy/console/contentview.py
index a121dfab..2b3c6def 100644
--- a/libmproxy/console/contentview.py
+++ b/libmproxy/console/contentview.py
@@ -21,12 +21,12 @@ from ..contrib.wbxml.ASCommandResponse import ASCommandResponse
try:
import pyamf
from pyamf import remoting, flex
-except ImportError: # pragma nocover
+except ImportError: # pragma nocover
pyamf = None
try:
import cssutils
-except ImportError: # pragma nocover
+except ImportError: # pragma nocover
cssutils = None
else:
cssutils.log.setLevel(logging.CRITICAL)
@@ -36,7 +36,7 @@ else:
cssutils.ser.prefs.indentClosingBrace = False
cssutils.ser.prefs.validOnly = False
-VIEW_CUTOFF = 1024*50
+VIEW_CUTOFF = 1024 * 50
def _view_text(content, total, limit):
@@ -59,7 +59,7 @@ def trailer(clen, txt, limit):
txt.append(
urwid.Text(
[
- ("highlight", "... %s of data not shown. Press "%netlib.utils.pretty_size(rem)),
+ ("highlight", "... %s of data not shown. Press " % netlib.utils.pretty_size(rem)),
("key", "f"),
("highlight", " to load all data.")
]
@@ -76,7 +76,7 @@ class ViewAuto:
ctype = hdrs.get_first("content-type")
if ctype:
ct = utils.parse_content_type(ctype) if ctype else None
- ct = "%s/%s"%(ct[0], ct[1])
+ ct = "%s/%s" % (ct[0], ct[1])
if ct in content_types_map:
return content_types_map[ct][0](hdrs, content, limit)
elif utils.isXML(content):
@@ -227,7 +227,7 @@ class ViewURLEncoded:
lines = utils.urldecode(content)
if lines:
body = common.format_keyvals(
- [(k+":", v) for (k, v) in lines],
+ [(k + ":", v) for (k, v) in lines],
key = "header",
val = "text"
)
@@ -304,7 +304,6 @@ if pyamf:
if not envelope:
return None
-
txt = []
for target, message in iter(envelope):
if isinstance(message, pyamf.remoting.Request):
@@ -315,13 +314,13 @@ if pyamf:
else:
txt.append(urwid.Text([
("header", "Response: "),
- ("text", "%s, code %s"%(target, message.status)),
+ ("text", "%s, code %s" % (target, message.status)),
]))
s = json.dumps(self.unpack(message), indent=4)
txt.extend(_view_text(s[:limit], len(s), limit))
- return "AMF v%s"%envelope.amfVersion, txt
+ return "AMF v%s" % envelope.amfVersion, txt
class ViewJavaScript:
@@ -375,7 +374,7 @@ class ViewImage:
return None
parts = [
("Format", str(img.format_description)),
- ("Size", "%s x %s px"%img.size),
+ ("Size", "%s x %s px" % img.size),
("Mode", str(img.mode)),
]
for i in sorted(img.info.keys()):
@@ -401,7 +400,7 @@ class ViewImage:
key = "header",
val = "text"
)
- return "%s image"%img.format, fmt
+ return "%s image" % img.format, fmt
class ViewProtobuf:
@@ -526,7 +525,7 @@ def get_content_view(viewmode, hdrItems, content, limit, logfunc, is_request):
decoded = encoding.decode(enc, content)
if decoded:
content = decoded
- msg.append("[decoded %s]"%enc)
+ msg.append("[decoded %s]" % enc)
try:
ret = viewmode(hdrs, content, limit)
# Third-party viewers can fail in unexpected ways...
diff --git a/libmproxy/console/flowdetailview.py b/libmproxy/console/flowdetailview.py
index 48845a62..40769c95 100644
--- a/libmproxy/console/flowdetailview.py
+++ b/libmproxy/console/flowdetailview.py
@@ -34,7 +34,7 @@ def flowdetails(state, flow):
if c:
text.append(urwid.Text([("head", "Server Certificate:")]))
parts = [
- ["Type", "%s, %s bits"%c.keyinfo],
+ ["Type", "%s, %s bits" % c.keyinfo],
["SHA1 digest", c.digest("sha1")],
["Valid to", str(c.notafter)],
["Valid from", str(c.notbefore)],
diff --git a/libmproxy/console/flowlist.py b/libmproxy/console/flowlist.py
index 6ab45bad..fd071569 100644
--- a/libmproxy/console/flowlist.py
+++ b/libmproxy/console/flowlist.py
@@ -50,7 +50,7 @@ class EventListBox(urwid.ListBox):
elif key == "G":
self.set_focus(0)
elif key == "g":
- self.set_focus(len(self.master.eventlist)-1)
+ self.set_focus(len(self.master.eventlist) - 1)
return urwid.ListBox.keypress(self, size, key)
@@ -76,7 +76,8 @@ class BodyPile(urwid.Pile):
def keypress(self, size, key):
if key == "tab":
- self.focus_position = (self.focus_position + 1)%len(self.widget_list)
+ self.focus_position = (
+ self.focus_position + 1) % len(self.widget_list)
if self.focus_position == 1:
self.widget_list[1].header = self.active_header
else:
@@ -157,7 +158,8 @@ class ConnectionItem(urwid.WidgetWrap):
callback = self.master.server_playback_path
)
- def keypress(self, (maxcol,), key):
+ def keypress(self, xxx_todo_changeme, key):
+ (maxcol,) = xxx_todo_changeme
key = common.shortcuts(key)
if key == "a":
self.flow.accept_intercept(self.master)
diff --git a/libmproxy/console/flowview.py b/libmproxy/console/flowview.py
index 632b725e..43a40d69 100644
--- a/libmproxy/console/flowview.py
+++ b/libmproxy/console/flowview.py
@@ -24,42 +24,42 @@ def _mkhelp():
("e", "edit request/response"),
("f", "load full body data"),
("m", "change body display mode for this entity"),
- (None,
- common.highlight_key("automatic", "a") +
- [("text", ": automatic detection")]
- ),
- (None,
- common.highlight_key("hex", "e") +
- [("text", ": Hex")]
- ),
- (None,
- common.highlight_key("html", "h") +
- [("text", ": HTML")]
- ),
- (None,
- common.highlight_key("image", "i") +
- [("text", ": Image")]
- ),
- (None,
- common.highlight_key("javascript", "j") +
- [("text", ": JavaScript")]
- ),
- (None,
- common.highlight_key("json", "s") +
- [("text", ": JSON")]
- ),
- (None,
- common.highlight_key("urlencoded", "u") +
- [("text", ": URL-encoded data")]
- ),
- (None,
- common.highlight_key("raw", "r") +
- [("text", ": raw data")]
- ),
- (None,
- common.highlight_key("xml", "x") +
- [("text", ": XML")]
- ),
+ (None,
+ common.highlight_key("automatic", "a") +
+ [("text", ": automatic detection")]
+ ),
+ (None,
+ common.highlight_key("hex", "e") +
+ [("text", ": Hex")]
+ ),
+ (None,
+ common.highlight_key("html", "h") +
+ [("text", ": HTML")]
+ ),
+ (None,
+ common.highlight_key("image", "i") +
+ [("text", ": Image")]
+ ),
+ (None,
+ common.highlight_key("javascript", "j") +
+ [("text", ": JavaScript")]
+ ),
+ (None,
+ common.highlight_key("json", "s") +
+ [("text", ": JSON")]
+ ),
+ (None,
+ common.highlight_key("urlencoded", "u") +
+ [("text", ": URL-encoded data")]
+ ),
+ (None,
+ common.highlight_key("raw", "r") +
+ [("text", ": raw data")]
+ ),
+ (None,
+ common.highlight_key("xml", "x") +
+ [("text", ": XML")]
+ ),
("M", "change default body display mode"),
("p", "previous flow"),
("P", "copy response(content/headers) to clipboard"),
@@ -123,13 +123,13 @@ class FlowView(tabs.Tabs):
def __init__(self, master, state, flow, tab_offset):
self.master, self.state, self.flow = master, state, flow
tabs.Tabs.__init__(self,
- [
- (self.tab_request, self.view_request),
- (self.tab_response, self.view_response),
- (self.tab_details, self.view_details),
- ],
- tab_offset
- )
+ [
+ (self.tab_request, self.view_request),
+ (self.tab_response, self.view_response),
+ (self.tab_details, self.view_details),
+ ],
+ tab_offset
+ )
self.show()
self.last_displayed_body = None
signals.flow_change.connect(self.sig_flow_change)
@@ -173,7 +173,7 @@ class FlowView(tabs.Tabs):
False
)
if full:
- limit = sys.maxint
+ limit = sys.maxsize
else:
limit = contentview.VIEW_CUTOFF
description, text_objects = cache.get(
@@ -197,7 +197,7 @@ class FlowView(tabs.Tabs):
def conn_text(self, conn):
if conn:
txt = common.format_keyvals(
- [(h+":", v) for (h, v) in conn.headers.lst],
+ [(h + ":", v) for (h, v) in conn.headers.lst],
key = "header",
val = "text"
)
@@ -217,7 +217,7 @@ class FlowView(tabs.Tabs):
" ",
('heading', "["),
('heading_key', "m"),
- ('heading', (":%s]"%viewmode.name)),
+ ('heading', (":%s]" % viewmode.name)),
],
align="right"
)
@@ -272,8 +272,9 @@ class FlowView(tabs.Tabs):
except ValueError:
return None
import BaseHTTPServer
- if BaseHTTPServer.BaseHTTPRequestHandler.responses.has_key(int(code)):
- response.msg = BaseHTTPServer.BaseHTTPRequestHandler.responses[int(code)][0]
+ if int(code) in BaseHTTPServer.BaseHTTPRequestHandler.responses:
+ response.msg = BaseHTTPServer.BaseHTTPRequestHandler.responses[
+ int(code)][0]
signals.flow_change.send(self, flow = self.flow)
def set_resp_msg(self, msg):
@@ -494,7 +495,7 @@ class FlowView(tabs.Tabs):
elif key == "d":
if self.state.flow_count() == 1:
self.master.view_flowlist()
- elif self.state.view.index(self.flow) == len(self.state.view)-1:
+ elif self.state.view.index(self.flow) == len(self.state.view) - 1:
self.view_prev_flow(self.flow)
else:
self.view_next_flow(self.flow)
@@ -615,7 +616,7 @@ class FlowView(tabs.Tabs):
if conn.content:
t = conn.headers["content-type"] or [None]
t = t[0]
- if os.environ.has_key("EDITOR") or os.environ.has_key("PAGER"):
+ if "EDITOR" in os.environ or "PAGER" in os.environ:
self.master.spawn_external_viewer(conn.content, t)
else:
signals.status_message.send(
diff --git a/libmproxy/console/grideditor.py b/libmproxy/console/grideditor.py
index 5a2da59f..b20e54e4 100644
--- a/libmproxy/console/grideditor.py
+++ b/libmproxy/console/grideditor.py
@@ -175,6 +175,7 @@ class GridWalker(urwid.ListWalker):
and errors is a set with an entry of each offset in rows that is an
error.
"""
+
def __init__(self, lst, editor):
self.lst = [(i, set([])) for i in lst]
self.editor = editor
@@ -225,7 +226,7 @@ class GridWalker(urwid.ListWalker):
def delete_focus(self):
if self.lst:
del self.lst[self.focus]
- self.focus = min(len(self.lst)-1, self.focus)
+ self.focus = min(len(self.lst) - 1, self.focus)
self._modified()
def _insert(self, pos):
@@ -266,14 +267,14 @@ class GridWalker(urwid.ListWalker):
self._modified()
def right(self):
- self.focus_col = min(self.focus_col + 1, len(self.editor.columns)-1)
+ self.focus_col = min(self.focus_col + 1, len(self.editor.columns) - 1)
self._modified()
def tab_next(self):
self.stop_edit()
- if self.focus_col < len(self.editor.columns)-1:
+ if self.focus_col < len(self.editor.columns) - 1:
self.focus_col += 1
- elif self.focus != len(self.lst)-1:
+ elif self.focus != len(self.lst) - 1:
self.focus_col = 0
self.focus += 1
self._modified()
@@ -297,14 +298,14 @@ class GridWalker(urwid.ListWalker):
self._modified()
def get_next(self, pos):
- if pos+1 >= len(self.lst):
+ if pos + 1 >= len(self.lst):
return None, None
- return GridRow(None, False, self.editor, self.lst[pos+1]), pos+1
+ return GridRow(None, False, self.editor, self.lst[pos + 1]), pos + 1
def get_prev(self, pos):
- if pos-1 < 0:
+ if pos - 1 < 0:
return None, None
- return GridRow(None, False, self.editor, self.lst[pos-1]), pos-1
+ return GridRow(None, False, self.editor, self.lst[pos - 1]), pos - 1
class GridListBox(urwid.ListBox):
@@ -387,7 +388,7 @@ class GridEditor(urwid.WidgetWrap):
d = file(p, "rb").read()
self.walker.set_current_value(d, unescaped)
self.walker._modified()
- except IOError, v:
+ except IOError as v:
return str(v)
def set_subeditor_value(self, val, focus, focus_col):
@@ -418,7 +419,7 @@ class GridEditor(urwid.WidgetWrap):
elif key == "G":
self.walker.set_focus(0)
elif key == "g":
- self.walker.set_focus(len(self.walker.lst)-1)
+ self.walker.set_focus(len(self.walker.lst) - 1)
elif key in ["h", "left"]:
self.walker.left()
elif key in ["l", "right"]:
@@ -633,7 +634,7 @@ class ScriptEditor(GridEditor):
def is_error(self, col, val):
try:
script.Script.parse_command(val)
- except script.ScriptError, v:
+ except script.ScriptError as v:
return str(v)
diff --git a/libmproxy/console/help.py b/libmproxy/console/help.py
index cbd5bef8..4e81a566 100644
--- a/libmproxy/console/help.py
+++ b/libmproxy/console/help.py
@@ -6,7 +6,7 @@ from . import common, signals
from .. import filt, version
footer = [
- ("heading", 'mitmproxy v%s '%version.VERSION),
+ ("heading", 'mitmproxy v%s ' % version.VERSION),
('heading_key', "q"), ":back ",
]
@@ -33,7 +33,12 @@ class HelpView(urwid.ListBox):
("pg up/down", "page up/down"),
("arrows", "up, down, left, right"),
]
- text.extend(common.format_keyvals(keys, key="key", val="text", indent=4))
+ text.extend(
+ common.format_keyvals(
+ keys,
+ key="key",
+ val="text",
+ indent=4))
text.append(urwid.Text([("head", "\n\nGlobal keys:\n")]))
keys = [
@@ -52,15 +57,15 @@ class HelpView(urwid.ListBox):
f = []
for i in filt.filt_unary:
f.append(
- ("~%s"%i.code, i.help)
+ ("~%s" % i.code, i.help)
)
for i in filt.filt_rex:
f.append(
- ("~%s regex"%i.code, i.help)
+ ("~%s regex" % i.code, i.help)
)
for i in filt.filt_int:
f.append(
- ("~%s int"%i.code, i.help)
+ ("~%s int" % i.code, i.help)
)
f.sort()
f.extend(
@@ -75,7 +80,7 @@ class HelpView(urwid.ListBox):
text.append(
urwid.Text(
- [
+ [
"\n",
("text", " Regexes are Python-style.\n"),
("text", " Regexes can be specified as quoted strings.\n"),
@@ -83,13 +88,13 @@ class HelpView(urwid.ListBox):
("text", " Expressions with no operators are regex matches against URL.\n"),
("text", " Default binary operator is &.\n"),
("head", "\n Examples:\n"),
- ]
+ ]
)
)
examples = [
- ("google\.com", "Url containing \"google.com"),
- ("~q ~b test", "Requests where body contains \"test\""),
- ("!(~q & ~t \"text/html\")", "Anything but requests with a text/html content type."),
+ ("google\.com", "Url containing \"google.com"),
+ ("~q ~b test", "Requests where body contains \"test\""),
+ ("!(~q & ~t \"text/html\")", "Anything but requests with a text/html content type."),
]
text.extend(
common.format_keyvals(examples, key="key", val="text", indent=4)
diff --git a/libmproxy/console/options.py b/libmproxy/console/options.py
index c728123f..58a4d469 100644
--- a/libmproxy/console/options.py
+++ b/libmproxy/console/options.py
@@ -8,6 +8,7 @@ footer = [
('heading_key', "C"), ":clear all ",
]
+
def _mkhelp():
text = []
keys = [
diff --git a/libmproxy/console/palettes.py b/libmproxy/console/palettes.py
index 6490eb73..ea3d1b62 100644
--- a/libmproxy/console/palettes.py
+++ b/libmproxy/console/palettes.py
@@ -270,7 +270,7 @@ class SolarizedDark(LowDark):
# Status bar & heading
heading = (sol_base2, sol_base01),
- heading_key = (sol_blue+",bold", sol_base01),
+ heading_key = (sol_blue + ",bold", sol_base01),
heading_inactive = (sol_base1, sol_base02),
# Help
diff --git a/libmproxy/console/pathedit.py b/libmproxy/console/pathedit.py
index 53cda3be..dccec14a 100644
--- a/libmproxy/console/pathedit.py
+++ b/libmproxy/console/pathedit.py
@@ -32,7 +32,7 @@ class _PathCompleter:
files = glob.glob(os.path.join(path, "*"))
prefix = txt
else:
- files = glob.glob(path+"*")
+ files = glob.glob(path + "*")
prefix = os.path.dirname(txt)
prefix = prefix or "./"
for f in files:
diff --git a/libmproxy/console/searchable.py b/libmproxy/console/searchable.py
index a9572ae3..627d595d 100644
--- a/libmproxy/console/searchable.py
+++ b/libmproxy/console/searchable.py
@@ -37,7 +37,7 @@ class Searchable(urwid.ListBox):
self.set_focus(0)
self.walker._modified()
elif key == "g":
- self.set_focus(len(self.walker)-1)
+ self.set_focus(len(self.walker) - 1)
self.walker._modified()
else:
return super(self.__class__, self).keypress(size, key)
@@ -74,11 +74,11 @@ class Searchable(urwid.ListBox):
return
# Start search at focus + 1
if backwards:
- rng = xrange(len(self.body)-1, -1, -1)
+ rng = xrange(len(self.body) - 1, -1, -1)
else:
rng = xrange(1, len(self.body) + 1)
for i in rng:
- off = (self.focus_position + i)%len(self.body)
+ off = (self.focus_position + i) % len(self.body)
w = self.body[off]
txt = self.get_text(w)
if txt and self.search_term in txt:
diff --git a/libmproxy/console/select.py b/libmproxy/console/select.py
index 61ee50e4..bf96a785 100644
--- a/libmproxy/console/select.py
+++ b/libmproxy/console/select.py
@@ -2,6 +2,7 @@ import urwid
from . import common
+
class _OptionWidget(urwid.WidgetWrap):
def __init__(self, option, text, shortcut, active, focus):
self.option = option
@@ -47,14 +48,14 @@ class OptionWalker(urwid.ListWalker):
return self.options[self.focus].render(True), self.focus
def get_next(self, pos):
- if pos >= len(self.options)-1:
+ if pos >= len(self.options) - 1:
return None, None
- return self.options[pos+1].render(False), pos+1
+ return self.options[pos + 1].render(False), pos + 1
def get_prev(self, pos):
if pos <= 0:
return None, None
- return self.options[pos-1].render(False), pos-1
+ return self.options[pos - 1].render(False), pos - 1
class Heading:
@@ -69,6 +70,8 @@ class Heading:
_neg = lambda: False
+
+
class Option:
def __init__(self, text, shortcut, getstate=None, activate=None):
self.text = text
@@ -77,7 +80,12 @@ class Option:
self.activate = activate or _neg
def render(self, focus):
- return _OptionWidget(self, self.text, self.shortcut, self.getstate(), focus)
+ return _OptionWidget(
+ self,
+ self.text,
+ self.shortcut,
+ self.getstate(),
+ focus)
class Select(urwid.ListBox):
@@ -92,7 +100,7 @@ class Select(urwid.ListBox):
for i in options:
if hasattr(i, "shortcut") and i.shortcut:
if i.shortcut in self.keymap:
- raise ValueError("Duplicate shortcut key: %s"%i.shortcut)
+ raise ValueError("Duplicate shortcut key: %s" % i.shortcut)
self.keymap[i.shortcut] = i
def keypress(self, size, key):
diff --git a/libmproxy/console/statusbar.py b/libmproxy/console/statusbar.py
index 37ceef94..7eb2131b 100644
--- a/libmproxy/console/statusbar.py
+++ b/libmproxy/console/statusbar.py
@@ -58,7 +58,7 @@ class ActionBar(urwid.WidgetWrap):
mkup = []
for i, e in enumerate(keys):
mkup.extend(common.highlight_key(e[0], e[1]))
- if i < len(keys)-1:
+ if i < len(keys) - 1:
mkup.append(",")
prompt.extend(mkup)
prompt.append(")? ")
@@ -136,14 +136,14 @@ class StatusBar(urwid.WidgetWrap):
if self.master.client_playback:
r.append("[")
r.append(("heading_key", "cplayback"))
- r.append(":%s to go]"%self.master.client_playback.count())
+ r.append(":%s to go]" % self.master.client_playback.count())
if self.master.server_playback:
r.append("[")
r.append(("heading_key", "splayback"))
if self.master.nopop:
- r.append(":%s in file]"%self.master.server_playback.count())
+ r.append(":%s in file]" % self.master.server_playback.count())
else:
- r.append(":%s to go]"%self.master.server_playback.count())
+ r.append(":%s to go]" % self.master.server_playback.count())
if self.master.get_ignore_filter():
r.append("[")
r.append(("heading_key", "I"))
@@ -155,23 +155,23 @@ class StatusBar(urwid.WidgetWrap):
if self.master.state.intercept_txt:
r.append("[")
r.append(("heading_key", "i"))
- r.append(":%s]"%self.master.state.intercept_txt)
+ r.append(":%s]" % self.master.state.intercept_txt)
if self.master.state.limit_txt:
r.append("[")
r.append(("heading_key", "l"))
- r.append(":%s]"%self.master.state.limit_txt)
+ r.append(":%s]" % self.master.state.limit_txt)
if self.master.stickycookie_txt:
r.append("[")
r.append(("heading_key", "t"))
- r.append(":%s]"%self.master.stickycookie_txt)
+ r.append(":%s]" % self.master.stickycookie_txt)
if self.master.stickyauth_txt:
r.append("[")
r.append(("heading_key", "u"))
- r.append(":%s]"%self.master.stickyauth_txt)
+ r.append(":%s]" % self.master.stickyauth_txt)
if self.master.state.default_body_view.name != "Auto":
r.append("[")
r.append(("heading_key", "M"))
- r.append(":%s]"%self.master.state.default_body_view.name)
+ r.append(":%s]" % self.master.state.default_body_view.name)
opts = []
if self.master.anticache:
@@ -196,22 +196,22 @@ class StatusBar(urwid.WidgetWrap):
)
if opts:
- r.append("[%s]"%(":".join(opts)))
+ r.append("[%s]" % (":".join(opts)))
if self.master.server.config.mode in ["reverse", "upstream"]:
dst = self.master.server.config.mode.dst
scheme = "https" if dst[0] else "http"
if dst[1] != dst[0]:
scheme += "2https" if dst[1] else "http"
- r.append("[dest:%s]"%utils.unparse_url(scheme, *dst[2:]))
+ r.append("[dest:%s]" % utils.unparse_url(scheme, *dst[2:]))
if self.master.scripts:
r.append("[")
r.append(("heading_key", "s"))
- r.append("cripts:%s]"%len(self.master.scripts))
+ r.append("cripts:%s]" % len(self.master.scripts))
# r.append("[lt:%0.3f]"%self.master.looptime)
if self.master.stream:
- r.append("[W:%s]"%self.master.stream_path)
+ r.append("[W:%s]" % self.master.stream_path)
return r
@@ -222,14 +222,14 @@ class StatusBar(urwid.WidgetWrap):
else:
offset = min(self.master.state.focus + 1, fc)
t = [
- ('heading', ("[%s/%s]"%(offset, fc)).ljust(9))
+ ('heading', ("[%s/%s]" % (offset, fc)).ljust(9))
]
if self.master.server.bound:
host = self.master.server.address.host
if host == "0.0.0.0":
host = "*"
- boundaddr = "[%s:%s]"%(host, self.master.server.address.port)
+ boundaddr = "[%s:%s]" % (host, self.master.server.address.port)
else:
boundaddr = ""
t.extend(self.get_status())
diff --git a/libmproxy/console/tabs.py b/libmproxy/console/tabs.py
index 2c46e59e..953f6b12 100644
--- a/libmproxy/console/tabs.py
+++ b/libmproxy/console/tabs.py
@@ -1,5 +1,6 @@
import urwid
+
class Tabs(urwid.WidgetWrap):
def __init__(self, tabs, tab_offset=0):
urwid.WidgetWrap.__init__(self, "")
@@ -15,10 +16,10 @@ class Tabs(urwid.WidgetWrap):
def keypress(self, size, key):
if key in ["tab", "l"]:
- self.tab_offset = (self.tab_offset + 1)%(len(self.tabs))
+ self.tab_offset = (self.tab_offset + 1) % (len(self.tabs))
self.show()
elif key == "h":
- self.tab_offset = (self.tab_offset - 1)%(len(self.tabs))
+ self.tab_offset = (self.tab_offset - 1) % (len(self.tabs))
self.show()
return self._w.keypress(size, key)
diff --git a/libmproxy/controller.py b/libmproxy/controller.py
index 9ca89184..98a3aec7 100644
--- a/libmproxy/controller.py
+++ b/libmproxy/controller.py
@@ -1,11 +1,14 @@
from __future__ import absolute_import
-import Queue, threading
+import Queue
+import threading
+
class DummyReply:
"""
A reply object that does nothing. Useful when we need an object to seem
like it has a channel, and during testing.
"""
+
def __init__(self):
self.acked = False
@@ -19,6 +22,7 @@ class Reply:
This object is used to respond to the message through the return
channel.
"""
+
def __init__(self, obj):
self.obj = obj
self.q = Queue.Queue()
@@ -67,11 +71,13 @@ class Slave(threading.Thread):
Slaves get a channel end-point through which they can send messages to
the master.
"""
+
def __init__(self, channel, server):
self.channel, self.server = channel, server
self.server.set_channel(channel)
threading.Thread.__init__(self)
- self.name = "SlaveThread (%s:%s)" % (self.server.address.host, self.server.address.port)
+ self.name = "SlaveThread (%s:%s)" % (
+ self.server.address.host, self.server.address.port)
def run(self):
self.server.serve_forever()
@@ -81,6 +87,7 @@ class Master(object):
"""
Masters get and respond to messages from slaves.
"""
+
def __init__(self, server):
"""
server may be None if no server is needed.
diff --git a/libmproxy/dump.py b/libmproxy/dump.py
index ac9c273f..ee8c65a0 100644
--- a/libmproxy/dump.py
+++ b/libmproxy/dump.py
@@ -53,7 +53,7 @@ class Options(object):
def str_response(resp):
- r = "%s %s"%(resp.code, resp.msg)
+ r = "%s %s" % (resp.code, resp.msg)
if resp.is_replay:
r = "[replay] " + r
return r
@@ -64,7 +64,7 @@ def str_request(f, showhost):
c = f.client_conn.address.host
else:
c = "[replay]"
- r = "%s %s %s"%(c, f.request.method, f.request.pretty_url(showhost))
+ r = "%s %s %s" % (c, f.request.method, f.request.pretty_url(showhost))
if f.request.stickycookie:
r = "[stickycookie] " + r
return r
@@ -102,7 +102,7 @@ class DumpMaster(flow.FlowMaster):
try:
f = file(path, options.outfile[1])
self.start_stream(f, self.filt)
- except IOError, v:
+ except IOError as v:
raise DumpError(v.strerror)
if options.replacements:
@@ -140,7 +140,7 @@ class DumpMaster(flow.FlowMaster):
if options.rfile:
try:
self.load_flows_file(options.rfile)
- except flow.FlowReadError, v:
+ except flow.FlowReadError as v:
self.add_event("Flow file corrupted.", "error")
raise DumpError(v)
@@ -181,12 +181,18 @@ class DumpMaster(flow.FlowMaster):
if not utils.isBin(content):
try:
jsn = json.loads(content)
- print(self.indent(4, json.dumps(jsn, indent=2)), file=self.outfile)
+ print(
+ self.indent(
+ 4,
+ json.dumps(
+ jsn,
+ indent=2)),
+ file=self.outfile)
except ValueError:
print(self.indent(4, content), file=self.outfile)
else:
d = netlib.utils.hexdump(content)
- d = "\n".join("%s\t%s %s"%i for i in d)
+ d = "\n".join("%s\t%s %s" % i for i in d)
print(self.indent(4, d), file=self.outfile)
if self.o.flow_detail >= 2:
print("", file=self.outfile)
@@ -208,7 +214,12 @@ class DumpMaster(flow.FlowMaster):
sz = "(content missing)"
else:
sz = netlib.utils.pretty_size(len(f.response.content))
- print(" << %s %s" % (str_response(f.response), sz), file=self.outfile)
+ print(
+ " << %s %s" %
+ (str_response(
+ f.response),
+ sz),
+ file=self.outfile)
self._print_message(f.response)
if f.error:
diff --git a/libmproxy/encoding.py b/libmproxy/encoding.py
index 0fd90870..f107eb5f 100644
--- a/libmproxy/encoding.py
+++ b/libmproxy/encoding.py
@@ -3,12 +3,14 @@
"""
from __future__ import absolute_import
import cStringIO
-import gzip, zlib
+import gzip
+import zlib
__ALL__ = ["ENCODINGS"]
ENCODINGS = set(["identity", "gzip", "deflate"])
+
def decode(e, content):
encoding_map = {
"identity": identity,
@@ -19,6 +21,7 @@ def decode(e, content):
return None
return encoding_map[e](content)
+
def encode(e, content):
encoding_map = {
"identity": identity,
@@ -29,6 +32,7 @@ def encode(e, content):
return None
return encoding_map[e](content)
+
def identity(content):
"""
Returns content unchanged. Identity is the default value of
@@ -36,6 +40,7 @@ def identity(content):
"""
return content
+
def decode_gzip(content):
gfile = gzip.GzipFile(fileobj=cStringIO.StringIO(content))
try:
@@ -43,6 +48,7 @@ def decode_gzip(content):
except (IOError, EOFError):
return None
+
def encode_gzip(content):
s = cStringIO.StringIO()
gf = gzip.GzipFile(fileobj=s, mode='wb')
@@ -50,6 +56,7 @@ def encode_gzip(content):
gf.close()
return s.getvalue()
+
def decode_deflate(content):
"""
Returns decompressed data for DEFLATE. Some servers may respond with
@@ -67,6 +74,7 @@ def decode_deflate(content):
except zlib.error:
return None
+
def encode_deflate(content):
"""
Returns compressed content, always including zlib header and checksum.
diff --git a/libmproxy/filt.py b/libmproxy/filt.py
index 40b2f6c9..3081eb94 100644
--- a/libmproxy/filt.py
+++ b/libmproxy/filt.py
@@ -32,16 +32,17 @@
rex Equivalent to ~u rex
"""
from __future__ import absolute_import
-import re, sys
+import re
+import sys
from .contrib import pyparsing as pp
from .protocol.http import decoded
class _Token:
def dump(self, indent=0, fp=sys.stdout):
- print >> fp, "\t"*indent, self.__class__.__name__,
+ print >> fp, "\t" * indent, self.__class__.__name__,
if hasattr(self, "expr"):
- print >> fp, "(%s)"%self.expr,
+ print >> fp, "(%s)" % self.expr,
print >> fp
@@ -54,6 +55,7 @@ class _Action(_Token):
class FErr(_Action):
code = "e"
help = "Match error"
+
def __call__(self, f):
return True if f.error else False
@@ -61,6 +63,7 @@ class FErr(_Action):
class FReq(_Action):
code = "q"
help = "Match request with no response"
+
def __call__(self, f):
if not f.response:
return True
@@ -69,6 +72,7 @@ class FReq(_Action):
class FResp(_Action):
code = "s"
help = "Match response"
+
def __call__(self, f):
return True if f.response else False
@@ -79,7 +83,7 @@ class _Rex(_Action):
try:
self.re = re.compile(self.expr)
except:
- raise ValueError, "Cannot compile expression."
+ raise ValueError("Cannot compile expression.")
def _check_content_type(expr, o):
@@ -100,6 +104,7 @@ class FAsset(_Action):
"image/.*",
"application/x-shockwave-flash"
]
+
def __call__(self, f):
if f.response:
for i in self.ASSET_TYPES:
@@ -111,6 +116,7 @@ class FAsset(_Action):
class FContentType(_Rex):
code = "t"
help = "Content-type header"
+
def __call__(self, f):
if _check_content_type(self.expr, f.request):
return True
@@ -122,6 +128,7 @@ class FContentType(_Rex):
class FRequestContentType(_Rex):
code = "tq"
help = "Request Content-Type header"
+
def __call__(self, f):
return _check_content_type(self.expr, f.request)
@@ -129,6 +136,7 @@ class FRequestContentType(_Rex):
class FResponseContentType(_Rex):
code = "ts"
help = "Response Content-Type header"
+
def __call__(self, f):
if f.response:
return _check_content_type(self.expr, f.response)
@@ -138,6 +146,7 @@ class FResponseContentType(_Rex):
class FHead(_Rex):
code = "h"
help = "Header"
+
def __call__(self, f):
if f.request.headers.match_re(self.expr):
return True
@@ -149,6 +158,7 @@ class FHead(_Rex):
class FHeadRequest(_Rex):
code = "hq"
help = "Request header"
+
def __call__(self, f):
if f.request.headers.match_re(self.expr):
return True
@@ -157,6 +167,7 @@ class FHeadRequest(_Rex):
class FHeadResponse(_Rex):
code = "hs"
help = "Response header"
+
def __call__(self, f):
if f.response and f.response.headers.match_re(self.expr):
return True
@@ -165,6 +176,7 @@ class FHeadResponse(_Rex):
class FBod(_Rex):
code = "b"
help = "Body"
+
def __call__(self, f):
if f.request and f.request.content:
with decoded(f.request):
@@ -180,6 +192,7 @@ class FBod(_Rex):
class FBodRequest(_Rex):
code = "bq"
help = "Request body"
+
def __call__(self, f):
if f.request and f.request.content:
with decoded(f.request):
@@ -190,6 +203,7 @@ class FBodRequest(_Rex):
class FBodResponse(_Rex):
code = "bs"
help = "Response body"
+
def __call__(self, f):
if f.response and f.response.content:
with decoded(f.response):
@@ -200,6 +214,7 @@ class FBodResponse(_Rex):
class FMethod(_Rex):
code = "m"
help = "Method"
+
def __call__(self, f):
return bool(re.search(self.expr, f.request.method, re.IGNORECASE))
@@ -207,6 +222,7 @@ class FMethod(_Rex):
class FDomain(_Rex):
code = "d"
help = "Domain"
+
def __call__(self, f):
return bool(re.search(self.expr, f.request.host, re.IGNORECASE))
@@ -215,6 +231,7 @@ class FUrl(_Rex):
code = "u"
help = "URL"
# FUrl is special, because it can be "naked".
+
@classmethod
def make(klass, s, loc, toks):
if len(toks) > 1:
@@ -233,6 +250,7 @@ class _Int(_Action):
class FCode(_Int):
code = "c"
help = "HTTP response code"
+
def __call__(self, f):
if f.response and f.response.code == self.num:
return True
@@ -243,9 +261,9 @@ class FAnd(_Token):
self.lst = lst
def dump(self, indent=0, fp=sys.stdout):
- print >> fp, "\t"*indent, self.__class__.__name__
+ print >> fp, "\t" * indent, self.__class__.__name__
for i in self.lst:
- i.dump(indent+1, fp)
+ i.dump(indent + 1, fp)
def __call__(self, f):
return all(i(f) for i in self.lst)
@@ -256,9 +274,9 @@ class FOr(_Token):
self.lst = lst
def dump(self, indent=0, fp=sys.stdout):
- print >> fp, "\t"*indent, self.__class__.__name__
+ print >> fp, "\t" * indent, self.__class__.__name__
for i in self.lst:
- i.dump(indent+1, fp)
+ i.dump(indent + 1, fp)
def __call__(self, f):
return any(i(f) for i in self.lst)
@@ -269,7 +287,7 @@ class FNot(_Token):
self.itm = itm[0]
def dump(self, indent=0, fp=sys.stdout):
- print >> fp, "\t"*indent, self.__class__.__name__
+ print >> fp, "\t" * indent, self.__class__.__name__
self.itm.dump(indent + 1, fp)
def __call__(self, f):
@@ -299,26 +317,28 @@ filt_rex = [
filt_int = [
FCode
]
+
+
def _make():
# Order is important - multi-char expressions need to come before narrow
# ones.
parts = []
for klass in filt_unary:
- f = pp.Literal("~%s"%klass.code)
+ f = pp.Literal("~%s" % klass.code)
f.setParseAction(klass.make)
parts.append(f)
- simplerex = "".join(c for c in pp.printables if c not in "()~'\"")
+ simplerex = "".join(c for c in pp.printables if c not in "()~'\"")
rex = pp.Word(simplerex) |\
- pp.QuotedString("\"", escChar='\\') |\
- pp.QuotedString("'", escChar='\\')
+ pp.QuotedString("\"", escChar='\\') |\
+ pp.QuotedString("'", escChar='\\')
for klass in filt_rex:
- f = pp.Literal("~%s"%klass.code) + rex.copy()
+ f = pp.Literal("~%s" % klass.code) + rex.copy()
f.setParseAction(klass.make)
parts.append(f)
for klass in filt_int:
- f = pp.Literal("~%s"%klass.code) + pp.Word(pp.nums)
+ f = pp.Literal("~%s" % klass.code) + pp.Word(pp.nums)
f.setParseAction(klass.make)
parts.append(f)
@@ -328,14 +348,20 @@ def _make():
parts.append(f)
atom = pp.MatchFirst(parts)
- expr = pp.operatorPrecedence(
- atom,
- [
- (pp.Literal("!").suppress(), 1, pp.opAssoc.RIGHT, lambda x: FNot(*x)),
- (pp.Literal("&").suppress(), 2, pp.opAssoc.LEFT, lambda x: FAnd(*x)),
- (pp.Literal("|").suppress(), 2, pp.opAssoc.LEFT, lambda x: FOr(*x)),
- ]
- )
+ expr = pp.operatorPrecedence(atom,
+ [(pp.Literal("!").suppress(),
+ 1,
+ pp.opAssoc.RIGHT,
+ lambda x: FNot(*x)),
+ (pp.Literal("&").suppress(),
+ 2,
+ pp.opAssoc.LEFT,
+ lambda x: FAnd(*x)),
+ (pp.Literal("|").suppress(),
+ 2,
+ pp.opAssoc.LEFT,
+ lambda x: FOr(*x)),
+ ])
expr = pp.OneOrMore(expr)
return expr.setParseAction(lambda x: FAnd(x) if len(x) != 1 else x)
bnf = _make()
@@ -355,15 +381,15 @@ def parse(s):
help = []
for i in filt_unary:
help.append(
- ("~%s"%i.code, i.help)
+ ("~%s" % i.code, i.help)
)
for i in filt_rex:
help.append(
- ("~%s regex"%i.code, i.help)
+ ("~%s regex" % i.code, i.help)
)
for i in filt_int:
help.append(
- ("~%s int"%i.code, i.help)
+ ("~%s int" % i.code, i.help)
)
help.sort()
help.extend(
@@ -373,4 +399,4 @@ help.extend(
("|", "or"),
("(...)", "grouping"),
]
-) \ No newline at end of file
+)
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 553bfd84..6154e3d7 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -162,7 +162,8 @@ class StreamLargeBodies(object):
r.headers, is_request, flow.request.method, code
)
if not (0 <= expected_size <= self.max_size):
- r.stream = r.stream or True # r.stream may already be a callable, which we want to preserve.
+ # r.stream may already be a callable, which we want to preserve.
+ r.stream = r.stream or True
class ClientPlaybackState:
@@ -200,8 +201,16 @@ class ClientPlaybackState:
class ServerPlaybackState:
- def __init__(self, headers, flows, exit, nopop, ignore_params, ignore_content,
- ignore_payload_params, ignore_host):
+ def __init__(
+ self,
+ headers,
+ flows,
+ exit,
+ nopop,
+ ignore_params,
+ ignore_content,
+ ignore_payload_params,
+ ignore_host):
"""
headers: Case-insensitive list of request headers that should be
included in request-response matching.
@@ -459,8 +468,9 @@ class FlowStore(FlowList):
Notifies the state that a flow has been updated.
The flow must be present in the state.
"""
- for view in self.views:
- view._update(f)
+ if f in self:
+ for view in self.views:
+ view._update(f)
def _remove(self, f):
"""
@@ -531,7 +541,8 @@ class State(object):
def flow_count(self):
return len(self.flows)
- # TODO: All functions regarding flows that don't cause side-effects should be moved into FlowStore.
+ # TODO: All functions regarding flows that don't cause side-effects should
+ # be moved into FlowStore.
def index(self, f):
return self.flows.index(f)
@@ -659,7 +670,7 @@ class FlowMaster(controller.Master):
"""
try:
s = script.Script(command, self)
- except script.ScriptError, v:
+ except script.ScriptError as v:
return v.args[0]
self.scripts.append(s)
@@ -723,8 +734,17 @@ class FlowMaster(controller.Master):
def stop_client_playback(self):
self.client_playback = None
- def start_server_playback(self, flows, kill, headers, exit, nopop, ignore_params,
- ignore_content, ignore_payload_params, ignore_host):
+ def start_server_playback(
+ self,
+ flows,
+ kill,
+ headers,
+ exit,
+ nopop,
+ ignore_params,
+ ignore_content,
+ ignore_payload_params,
+ ignore_host):
"""
flows: List of flows.
kill: Boolean, should we kill requests not part of the replay?
@@ -733,9 +753,15 @@ class FlowMaster(controller.Master):
ignore_payload_params: list of content params to ignore in server replay
ignore_host: true if request host should be ignored in server replay
"""
- self.server_playback = ServerPlaybackState(headers, flows, exit, nopop,
- ignore_params, ignore_content,
- ignore_payload_params, ignore_host)
+ self.server_playback = ServerPlaybackState(
+ headers,
+ flows,
+ exit,
+ nopop,
+ ignore_params,
+ ignore_content,
+ ignore_payload_params,
+ ignore_host)
self.kill_nonreplay = kill
def stop_server_playback(self):
@@ -785,23 +811,36 @@ class FlowMaster(controller.Master):
this method creates a new artificial and minimalist request also adds it to flowlist
"""
c = ClientConnection.from_state(dict(
- address=dict(address=(host, port), use_ipv6=False),
- clientcert=None
- ))
+ address=dict(address=(host, port), use_ipv6=False),
+ clientcert=None
+ ))
s = ServerConnection.from_state(dict(
- address=dict(address=(host, port), use_ipv6=False),
- state=[],
- source_address=None, #source_address=dict(address=(host, port), use_ipv6=False),
- cert=None,
- sni=host,
- ssl_established=True
- ))
- f = http.HTTPFlow(c,s);
+ address=dict(address=(host, port), use_ipv6=False),
+ state=[],
+ source_address=None,
+ # source_address=dict(address=(host, port), use_ipv6=False),
+ cert=None,
+ sni=host,
+ ssl_established=True
+ ))
+ f = http.HTTPFlow(c, s)
headers = ODictCaseless()
- req = http.HTTPRequest("absolute", method, scheme, host, port, path, (1, 1), headers, None,
- None, None, None)
+ req = http.HTTPRequest(
+ "absolute",
+ method,
+ scheme,
+ host,
+ port,
+ path,
+ (1,
+ 1),
+ headers,
+ None,
+ None,
+ None,
+ None)
f.request = req
return self.load_flow(f)
@@ -812,7 +851,8 @@ class FlowMaster(controller.Master):
if self.server and self.server.config.mode == "reverse":
f.request.host, f.request.port = self.server.config.mode.dst[2:]
- f.request.scheme = "https" if self.server.config.mode.dst[1] else "http"
+ f.request.scheme = "https" if self.server.config.mode.dst[
+ 1] else "http"
f.reply = controller.DummyReply()
if f.request:
@@ -839,7 +879,7 @@ class FlowMaster(controller.Master):
try:
f = file(path, "rb")
freader = FlowReader(f)
- except IOError, v:
+ except IOError as v:
raise FlowReadError(v.strerror)
return self.load_flows(freader)
@@ -880,7 +920,8 @@ class FlowMaster(controller.Master):
f.backup()
f.request.is_replay = True
if f.request.content:
- f.request.headers["Content-Length"] = [str(len(f.request.content))]
+ f.request.headers[
+ "Content-Length"] = [str(len(f.request.content))]
f.response = None
f.error = None
self.process_new_request(f)
@@ -1031,7 +1072,7 @@ class FlowReader:
"""
off = 0
try:
- while 1:
+ while True:
data = tnetstring.load(self.fo)
if tuple(data["version"][:2]) != version.IVERSION[:2]:
v = ".".join(str(i) for i in data["version"])
@@ -1040,7 +1081,7 @@ class FlowReader:
)
off = self.fo.tell()
yield handle.protocols[data["type"]]["flow"].from_state(data)
- except ValueError, v:
+ except ValueError as v:
# Error is due to EOF
if self.fo.tell() == off and self.fo.read() == '':
return
diff --git a/libmproxy/main.py b/libmproxy/main.py
index 32ab738e..73e6c62b 100644
--- a/libmproxy/main.py
+++ b/libmproxy/main.py
@@ -70,7 +70,7 @@ def get_server(dummy_server, options):
else:
try:
return ProxyServer(options)
- except ProxyServerError, v:
+ except ProxyServerError as v:
print(str(v), file=sys.stderr)
sys.exit(1)
diff --git a/libmproxy/onboarding/app.py b/libmproxy/onboarding/app.py
index 37f05e96..6edd74b1 100644
--- a/libmproxy/onboarding/app.py
+++ b/libmproxy/onboarding/app.py
@@ -45,7 +45,10 @@ class PEM(tornado.web.RequestHandler):
def get(self):
p = os.path.join(self.request.master.server.config.cadir, self.filename)
self.set_header("Content-Type", "application/x-x509-ca-cert")
- self.set_header("Content-Disposition", "inline; filename={}".format(self.filename))
+ self.set_header(
+ "Content-Disposition",
+ "inline; filename={}".format(
+ self.filename))
with open(p, "rb") as f:
self.write(f.read())
@@ -59,7 +62,10 @@ class P12(tornado.web.RequestHandler):
def get(self):
p = os.path.join(self.request.master.server.config.cadir, self.filename)
self.set_header("Content-Type", "application/x-pkcs12")
- self.set_header("Content-Disposition", "inline; filename={}".format(self.filename))
+ self.set_header(
+ "Content-Disposition",
+ "inline; filename={}".format(
+ self.filename))
with open(p, "rb") as f:
self.write(f.read())
@@ -78,7 +84,6 @@ application = tornado.web.Application(
}
),
],
- #debug=True
+ # debug=True
)
mapp = Adapter(application)
-
diff --git a/libmproxy/platform/linux.py b/libmproxy/platform/linux.py
index d5cfec90..e60a9950 100644
--- a/libmproxy/platform/linux.py
+++ b/libmproxy/platform/linux.py
@@ -1,4 +1,5 @@
-import socket, struct
+import socket
+import struct
# Python socket module does not have this constant
SO_ORIGINAL_DST = 80
diff --git a/libmproxy/platform/osx.py b/libmproxy/platform/osx.py
index 810e5e5f..c5922850 100644
--- a/libmproxy/platform/osx.py
+++ b/libmproxy/platform/osx.py
@@ -21,6 +21,7 @@ class Resolver(object):
peer = csock.getpeername()
stxt = subprocess.check_output(self.STATECMD, stderr=subprocess.STDOUT)
if "sudo: a password is required" in stxt:
- raise RuntimeError("Insufficient privileges to access pfctl. "
- "See http://mitmproxy.org/doc/transparent/osx.html for details.")
+ raise RuntimeError(
+ "Insufficient privileges to access pfctl. "
+ "See http://mitmproxy.org/doc/transparent/osx.html for details.")
return pf.lookup(peer[0], peer[1], stxt)
diff --git a/libmproxy/platform/windows.py b/libmproxy/platform/windows.py
index 066a377d..5133d056 100644
--- a/libmproxy/platform/windows.py
+++ b/libmproxy/platform/windows.py
@@ -197,9 +197,12 @@ class TransparentProxy(object):
self.driver = WinDivert()
self.driver.register()
- self.request_filter = custom_filter or " or ".join(("tcp.DstPort == %d" % p) for p in redirect_ports)
+ self.request_filter = custom_filter or " or ".join(
+ ("tcp.DstPort == %d" %
+ p) for p in redirect_ports)
self.request_forward_handle = None
- self.request_forward_thread = threading.Thread(target=self.request_forward)
+ self.request_forward_thread = threading.Thread(
+ target=self.request_forward)
self.request_forward_thread.daemon = True
self.addr_pid_map = dict()
@@ -235,17 +238,25 @@ class TransparentProxy(object):
# Block all ICMP requests (which are sent on Windows by default).
# In layman's terms: If we don't do this, our proxy machine tells the client that it can directly connect to the
# real gateway if they are on the same network.
- self.icmp_handle = self.driver.open_handle(filter="icmp", layer=Layer.NETWORK, flags=Flag.DROP)
-
- self.response_handle = self.driver.open_handle(filter=self.response_filter, layer=Layer.NETWORK)
+ self.icmp_handle = self.driver.open_handle(
+ filter="icmp",
+ layer=Layer.NETWORK,
+ flags=Flag.DROP)
+
+ self.response_handle = self.driver.open_handle(
+ filter=self.response_filter,
+ layer=Layer.NETWORK)
self.response_thread.start()
if self.mode == "forward" or self.mode == "both":
- self.request_forward_handle = self.driver.open_handle(filter=self.request_filter,
- layer=Layer.NETWORK_FORWARD)
+ self.request_forward_handle = self.driver.open_handle(
+ filter=self.request_filter,
+ layer=Layer.NETWORK_FORWARD)
self.request_forward_thread.start()
if self.mode == "local" or self.mode == "both":
- self.request_local_handle = self.driver.open_handle(filter=self.request_filter, layer=Layer.NETWORK)
+ self.request_local_handle = self.driver.open_handle(
+ filter=self.request_filter,
+ layer=Layer.NETWORK)
self.request_local_thread.start()
def shutdown(self):
@@ -266,14 +277,17 @@ class TransparentProxy(object):
try:
raw_packet, metadata = handle.recv()
return self.driver.parse_packet(raw_packet), metadata
- except WindowsError, e:
+ except WindowsError as e:
if e.winerror == 995:
return None, None
else:
raise
def fetch_pids(self):
- ret = windll.iphlpapi.GetTcpTable2(byref(self.tcptable2), byref(self.tcptable2_size), 0)
+ ret = windll.iphlpapi.GetTcpTable2(
+ byref(
+ self.tcptable2), byref(
+ self.tcptable2_size), 0)
if ret == ERROR_INSUFFICIENT_BUFFER:
self.tcptable2 = MIB_TCPTABLE2(self.tcptable2_size.value)
self.fetch_pids()
@@ -299,7 +313,8 @@ class TransparentProxy(object):
self.fetch_pids()
# If this fails, we most likely have a connection from an external client to
- # a local server on 80/443. In this, case we always want to proxy the request.
+ # a local server on 80/443. In this, case we always want to proxy
+ # the request.
pid = self.addr_pid_map.get(client, None)
if pid not in self.trusted_pids:
@@ -325,7 +340,8 @@ class TransparentProxy(object):
server = (packet.dst_addr, packet.dst_port)
if client in self.client_server_map:
- del self.client_server_map[client] # Force re-add to mark as "newest" entry in the dict.
+ # Force re-add to mark as "newest" entry in the dict.
+ del self.client_server_map[client]
while len(self.client_server_map) > self.connection_cache_size:
self.client_server_map.popitem(False)
@@ -335,7 +351,8 @@ class TransparentProxy(object):
metadata.direction = Direction.INBOUND
packet = self.driver.update_packet_checksums(packet)
- # Use any handle thats on the NETWORK layer - request_local may be unavailable.
+ # Use any handle thats on the NETWORK layer - request_local may be
+ # unavailable.
self.response_handle.send((packet.raw, metadata))
def response(self):
@@ -361,15 +378,32 @@ class TransparentProxy(object):
if __name__ == "__main__":
- parser = configargparse.ArgumentParser(description="Windows Transparent Proxy")
- parser.add_argument('--mode', choices=['forward', 'local', 'both'], default="both",
- help='redirection operation mode: "forward" to only redirect forwarded packets, '
- '"local" to only redirect packets originating from the local machine')
+ parser = configargparse.ArgumentParser(
+ description="Windows Transparent Proxy")
+ parser.add_argument(
+ '--mode',
+ choices=[
+ 'forward',
+ 'local',
+ 'both'],
+ default="both",
+ help='redirection operation mode: "forward" to only redirect forwarded packets, '
+ '"local" to only redirect packets originating from the local machine')
group = parser.add_mutually_exclusive_group()
- group.add_argument("--redirect-ports", nargs="+", type=int, default=[80, 443], metavar="80",
- help="ports that should be forwarded to the proxy")
- group.add_argument("--custom-filter", default=None, metavar="WINDIVERT_FILTER",
- help="Custom WinDivert interception rule.")
+ group.add_argument(
+ "--redirect-ports",
+ nargs="+",
+ type=int,
+ default=[
+ 80,
+ 443],
+ metavar="80",
+ help="ports that should be forwarded to the proxy")
+ group.add_argument(
+ "--custom-filter",
+ default=None,
+ metavar="WINDIVERT_FILTER",
+ help="Custom WinDivert interception rule.")
parser.add_argument("--proxy-addr", default=False,
help="Proxy Server Address")
parser.add_argument("--proxy-port", type=int, default=8080,
@@ -391,4 +425,4 @@ if __name__ == "__main__":
except KeyboardInterrupt:
print(" * Shutting down...")
proxy.shutdown()
- print(" * Shut down.") \ No newline at end of file
+ print(" * Shut down.")
diff --git a/libmproxy/protocol/__init__.py b/libmproxy/protocol/__init__.py
index f5d6a2d0..bbc20dba 100644
--- a/libmproxy/protocol/__init__.py
+++ b/libmproxy/protocol/__init__.py
@@ -1 +1 @@
-from .primitives import * \ No newline at end of file
+from .primitives import *
diff --git a/libmproxy/protocol/handle.py b/libmproxy/protocol/handle.py
index 100c7368..49cb3c1b 100644
--- a/libmproxy/protocol/handle.py
+++ b/libmproxy/protocol/handle.py
@@ -6,6 +6,7 @@ protocols = {
'tcp': dict(handler=tcp.TCPHandler)
}
+
def protocol_handler(protocol):
"""
@type protocol: str
@@ -14,4 +15,6 @@ def protocol_handler(protocol):
if protocol in protocols:
return protocols[protocol]["handler"]
- raise NotImplementedError("Unknown Protocol: %s" % protocol) # pragma: nocover \ No newline at end of file
+ raise NotImplementedError(
+ "Unknown Protocol: %s" %
+ protocol) # pragma: nocover
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index 324a188f..91e74567 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -305,7 +305,18 @@ class HTTPRequest(HTTPMessage):
@classmethod
def from_state(cls, state):
- f = cls(None, None, None, None, None, None, None, None, None, None, None)
+ f = cls(
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None,
+ None)
f.load_state(state)
return f
@@ -315,7 +326,12 @@ class HTTPRequest(HTTPMessage):
)
@classmethod
- def from_stream(cls, rfile, include_body=True, body_size_limit=None, wfile=None):
+ def from_stream(
+ cls,
+ rfile,
+ include_body=True,
+ body_size_limit=None,
+ wfile=None):
"""
Parse an HTTP request from a file stream
@@ -403,7 +419,8 @@ class HTTPRequest(HTTPMessage):
self.host,
self.port)]
- # If content is defined (i.e. not None or CONTENT_MISSING), we always add a content-length header.
+ # If content is defined (i.e. not None or CONTENT_MISSING), we always
+ # add a content-length header.
if self.content or self.content == "":
headers["Content-Length"] = [str(len(self.content))]
@@ -460,9 +477,9 @@ class HTTPRequest(HTTPMessage):
decode appropriately.
"""
if self.headers["accept-encoding"]:
- self.headers["accept-encoding"] = [', '.join(
- e for e in encoding.ENCODINGS if e in self.headers["accept-encoding"][0]
- )]
+ self.headers["accept-encoding"] = [
+ ', '.join(
+ e for e in encoding.ENCODINGS if e in self.headers["accept-encoding"][0])]
def update_host_header(self):
"""
@@ -489,13 +506,22 @@ class HTTPRequest(HTTPMessage):
Returns an empty ODict if there is no data or the content-type
indicates non-form data.
"""
- if self.content and self.headers.in_any("content-type", HDR_FORM_URLENCODED, True):
- return odict.ODict(utils.urldecode(self.content))
+ if self.content and self.headers.in_any(
+ "content-type",
+ HDR_FORM_URLENCODED,
+ True):
+ return odict.ODict(utils.urldecode(self.content))
return odict.ODict([])
def get_form_multipart(self):
- if self.content and self.headers.in_any("content-type", HDR_FORM_MULTIPART, True):
- return odict.ODict(utils.multipartdecode(self.headers, self.content))
+ if self.content and self.headers.in_any(
+ "content-type",
+ HDR_FORM_MULTIPART,
+ True):
+ return odict.ODict(
+ utils.multipartdecode(
+ self.headers,
+ self.content))
return odict.ODict([])
def set_form_urlencoded(self, odict):
@@ -664,8 +690,15 @@ class HTTPResponse(HTTPMessage):
timestamp_end: Timestamp indicating when request transmission ended
"""
- def __init__(self, httpversion, code, msg, headers, content, timestamp_start=None,
- timestamp_end=None):
+ def __init__(
+ self,
+ httpversion,
+ code,
+ msg,
+ headers,
+ content,
+ timestamp_start=None,
+ timestamp_end=None):
assert isinstance(headers, odict.ODictCaseless) or headers is None
HTTPMessage.__init__(
self,
@@ -710,7 +743,12 @@ class HTTPResponse(HTTPMessage):
)
@classmethod
- def from_stream(cls, rfile, request_method, include_body=True, body_size_limit=None):
+ def from_stream(
+ cls,
+ rfile,
+ request_method,
+ include_body=True,
+ body_size_limit=None):
"""
Parse an HTTP response from a file stream
"""
@@ -760,7 +798,8 @@ class HTTPResponse(HTTPMessage):
if not preserve_transfer_encoding:
del headers['Transfer-Encoding']
- # If content is defined (i.e. not None or CONTENT_MISSING), we always add a content-length header.
+ # If content is defined (i.e. not None or CONTENT_MISSING), we always
+ # add a content-length header.
if self.content or self.content == "":
headers["Content-Length"] = [str(len(self.content))]
@@ -1008,7 +1047,7 @@ class HTTPHandler(ProtocolHandler):
include_body=False
)
break
- except (tcp.NetLibError, http.HttpErrorConnClosed), v:
+ except (tcp.NetLibError, http.HttpErrorConnClosed) as v:
self.c.log(
"error in server communication: %s" % repr(v),
level="debug"
@@ -1079,7 +1118,8 @@ class HTTPHandler(ProtocolHandler):
if request_reply is None or request_reply == KILL:
raise KillSignal()
- self.process_server_address(flow) # The inline script may have changed request.host
+ # The inline script may have changed request.host
+ self.process_server_address(flow)
if isinstance(request_reply, HTTPResponse):
flow.response = request_reply
@@ -1090,7 +1130,9 @@ class HTTPHandler(ProtocolHandler):
# we can safely set it as the final attribute value here.
flow.server_conn = self.c.server_conn
- self.c.log("response", "debug", [flow.response._assemble_first_line()])
+ self.c.log(
+ "response", "debug", [
+ flow.response._assemble_first_line()])
response_reply = self.c.channel.ask("response", flow)
if response_reply is None or response_reply == KILL:
raise KillSignal()
@@ -1117,7 +1159,8 @@ class HTTPHandler(ProtocolHandler):
}
)
)
- if not self.process_connect_request((flow.request.host, flow.request.port)):
+ if not self.process_connect_request(
+ (flow.request.host, flow.request.port)):
return False
# If the user has changed the target server on this connection,
@@ -1130,7 +1173,7 @@ class HTTPHandler(ProtocolHandler):
http.HttpError,
proxy.ProxyError,
tcp.NetLibError,
- ), e:
+ ) as e:
self.handle_error(e, flow)
except KillSignal:
self.c.log("Connection killed", "info")
@@ -1226,7 +1269,8 @@ class HTTPHandler(ProtocolHandler):
# Determine .scheme, .host and .port attributes
# For absolute-form requests, they are directly given in the request.
# For authority-form requests, we only need to determine the request scheme.
- # For relative-form requests, we need to determine host and port as well.
+ # For relative-form requests, we need to determine host and port as
+ # well.
if not request.scheme:
request.scheme = "https" if flow.server_conn and flow.server_conn.ssl_established else "http"
if not request.host:
@@ -1253,8 +1297,8 @@ class HTTPHandler(ProtocolHandler):
flow.server_conn = self.c.server_conn
self.c.establish_server_connection()
self.c.client_conn.send(
- ('HTTP/%s.%s 200 ' % (request.httpversion[0],request.httpversion[1])) +
- 'Connection established\r\n' +
+ ('HTTP/%s.%s 200 ' % (request.httpversion[0], request.httpversion[1])) +
+ 'Connection established\r\n' +
'Content-Length: 0\r\n' +
('Proxy-agent: %s\r\n' % self.c.config.server_version) +
'\r\n'
@@ -1372,10 +1416,15 @@ class HTTPHandler(ProtocolHandler):
semantics. Returns True, if so.
"""
close_connection = (
- http.connection_close(flow.request.httpversion, flow.request.headers) or
- http.connection_close(flow.response.httpversion, flow.response.headers) or
- http.expected_http_body_size(flow.response.headers, False, flow.request.method,
- flow.response.code) == -1)
+ http.connection_close(
+ flow.request.httpversion,
+ flow.request.headers) or http.connection_close(
+ flow.response.httpversion,
+ flow.response.headers) or http.expected_http_body_size(
+ flow.response.headers,
+ False,
+ flow.request.method,
+ flow.response.code) == -1)
if close_connection:
if flow.request.form_in == "authority" and flow.response.code == 200:
# Workaround for
diff --git a/libmproxy/protocol/primitives.py b/libmproxy/protocol/primitives.py
index f9c22e1a..2f8ea3e0 100644
--- a/libmproxy/protocol/primitives.py
+++ b/libmproxy/protocol/primitives.py
@@ -24,6 +24,7 @@ class Error(stateobject.StateObject):
msg: Message describing the error
timestamp: Seconds since the epoch
"""
+
def __init__(self, msg, timestamp=None):
"""
@type msg: str
@@ -59,6 +60,7 @@ class Flow(stateobject.StateObject):
A Flow is a collection of objects representing a single transaction.
This class is usually subclassed for each protocol, e.g. HTTPFlow.
"""
+
def __init__(self, type, client_conn, server_conn, live=None):
self.type = type
self.id = str(uuid.uuid4())
@@ -165,12 +167,12 @@ class Flow(stateobject.StateObject):
master.handle_accept_intercept(self)
-
class ProtocolHandler(object):
"""
A ProtocolHandler implements an application-layer protocol, e.g. HTTP.
See: libmproxy.protocol.http.HTTPHandler
"""
+
def __init__(self, c):
self.c = c
"""@type: libmproxy.proxy.server.ConnectionHandler"""
@@ -209,13 +211,20 @@ class LiveConnection(object):
interface with a live connection, without exposing the internals
of the ConnectionHandler.
"""
+
def __init__(self, c):
self.c = c
"""@type: libmproxy.proxy.server.ConnectionHandler"""
self._backup_server_conn = None
"""@type: libmproxy.proxy.connection.ServerConnection"""
- def change_server(self, address, ssl=None, sni=None, force=False, persistent_change=False):
+ def change_server(
+ self,
+ address,
+ ssl=None,
+ sni=None,
+ force=False,
+ persistent_change=False):
"""
Change the server connection to the specified address.
@returns:
diff --git a/libmproxy/protocol/tcp.py b/libmproxy/protocol/tcp.py
index 5314b577..0feb77c6 100644
--- a/libmproxy/protocol/tcp.py
+++ b/libmproxy/protocol/tcp.py
@@ -79,7 +79,8 @@ class TCPHandler(ProtocolHandler):
),
"info"
)
- # Do not use dst.connection.send here, which may raise OpenSSL-specific errors.
+ # Do not use dst.connection.send here, which may raise
+ # OpenSSL-specific errors.
dst.send(contents)
else:
# socket.socket.send supports raw bytearrays/memoryviews
diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py
index dfde2958..3f579669 100644
--- a/libmproxy/proxy/config.py
+++ b/libmproxy/proxy/config.py
@@ -81,16 +81,27 @@ class ProxyConfig:
self.check_tcp = HostMatcher(tcp_hosts)
self.authenticator = authenticator
self.cadir = os.path.expanduser(cadir)
- self.certstore = certutils.CertStore.from_store(self.cadir, CONF_BASENAME)
+ self.certstore = certutils.CertStore.from_store(
+ self.cadir,
+ CONF_BASENAME)
for spec, cert in certs:
self.certstore.add_cert_file(spec, cert)
self.certforward = certforward
- self.openssl_method_client, self.openssl_options_client = version_to_openssl(ssl_version_client)
- self.openssl_method_server, self.openssl_options_server = version_to_openssl(ssl_version_server)
+ self.openssl_method_client, self.openssl_options_client = version_to_openssl(
+ ssl_version_client)
+ self.openssl_method_server, self.openssl_options_server = version_to_openssl(
+ ssl_version_server)
self.ssl_ports = ssl_ports
-sslversion_choices = ("all", "secure", "SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2")
+sslversion_choices = (
+ "all",
+ "secure",
+ "SSLv2",
+ "SSLv3",
+ "TLSv1",
+ "TLSv1_1",
+ "TLSv1_2")
def version_to_openssl(version):
@@ -119,7 +130,8 @@ def process_proxy_options(parser, options):
if options.transparent_proxy:
c += 1
if not platform.resolver:
- return parser.error("Transparent mode not supported on this platform.")
+ return parser.error(
+ "Transparent mode not supported on this platform.")
mode = "transparent"
if options.socks_proxy:
c += 1
@@ -133,28 +145,33 @@ def process_proxy_options(parser, options):
mode = "upstream"
upstream_server = options.upstream_proxy
if c > 1:
- return parser.error("Transparent, SOCKS5, reverse and upstream proxy mode "
- "are mutually exclusive.")
+ return parser.error(
+ "Transparent, SOCKS5, reverse and upstream proxy mode "
+ "are mutually exclusive.")
if options.clientcerts:
options.clientcerts = os.path.expanduser(options.clientcerts)
- if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts):
+ if not os.path.exists(
+ options.clientcerts) or not os.path.isdir(
+ options.clientcerts):
return parser.error(
- "Client certificate directory does not exist or is not a directory: %s" % options.clientcerts
- )
+ "Client certificate directory does not exist or is not a directory: %s" %
+ options.clientcerts)
if (options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd):
if options.auth_singleuser:
if len(options.auth_singleuser.split(':')) != 2:
- return parser.error("Invalid single-user specification. Please use the format username:password")
+ return parser.error(
+ "Invalid single-user specification. Please use the format username:password")
username, password = options.auth_singleuser.split(':')
password_manager = http_auth.PassManSingleUser(username, password)
elif options.auth_nonanonymous:
password_manager = http_auth.PassManNonAnon()
elif options.auth_htpasswd:
try:
- password_manager = http_auth.PassManHtpasswd(options.auth_htpasswd)
- except ValueError, v:
+ password_manager = http_auth.PassManHtpasswd(
+ options.auth_htpasswd)
+ except ValueError as v:
return parser.error(v.message)
authenticator = http_auth.BasicProxyAuth(password_manager, "mitmproxy")
else:
@@ -203,15 +220,18 @@ def process_proxy_options(parser, options):
def ssl_option_group(parser):
group = parser.add_argument_group("SSL")
group.add_argument(
- "--cert", dest='certs', default=[], type=str,
- metavar="SPEC", action="append",
+ "--cert",
+ dest='certs',
+ default=[],
+ type=str,
+ metavar="SPEC",
+ action="append",
help='Add an SSL certificate. SPEC is of the form "[domain=]path". '
- 'The domain may include a wildcard, and is equal to "*" if not specified. '
- 'The file at path is a certificate in PEM format. If a private key is included in the PEM, '
- 'it is used, else the default key in the conf dir is used. '
- 'The PEM file should contain the full certificate chain, with the leaf certificate as the first entry. '
- 'Can be passed multiple times.'
- )
+ 'The domain may include a wildcard, and is equal to "*" if not specified. '
+ 'The file at path is a certificate in PEM format. If a private key is included in the PEM, '
+ 'it is used, else the default key in the conf dir is used. '
+ 'The PEM file should contain the full certificate chain, with the leaf certificate as the first entry. '
+ 'Can be passed multiple times.')
group.add_argument(
"--cert-forward", action="store_true",
dest="certforward", default=False,
@@ -238,11 +258,15 @@ def ssl_option_group(parser):
help="Don't connect to upstream server to look up certificate details."
)
group.add_argument(
- "--ssl-port", action="append", type=int, dest="ssl_ports", default=list(TRANSPARENT_SSL_PORTS),
+ "--ssl-port",
+ action="append",
+ type=int,
+ dest="ssl_ports",
+ default=list(TRANSPARENT_SSL_PORTS),
metavar="PORT",
help="Can be passed multiple times. Specify destination ports which are assumed to be SSL. "
- "Defaults to %s." % str(TRANSPARENT_SSL_PORTS)
- )
+ "Defaults to %s." %
+ str(TRANSPARENT_SSL_PORTS))
group.add_argument(
"--ssl-version-client", dest="ssl_version_client",
default="secure", action="store",
diff --git a/libmproxy/proxy/connection.py b/libmproxy/proxy/connection.py
index 1eeae16f..5219023b 100644
--- a/libmproxy/proxy/connection.py
+++ b/libmproxy/proxy/connection.py
@@ -7,7 +7,9 @@ from .. import stateobject, utils
class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
def __init__(self, client_connection, address, server):
- if client_connection: # Eventually, this object is restored from state. We don't have a connection then.
+ # Eventually, this object is restored from state. We don't have a
+ # connection then.
+ if client_connection:
tcp.BaseHandler.__init__(self, client_connection, address, server)
else:
self.connection = None
@@ -39,15 +41,18 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
def get_state(self, short=False):
d = super(ClientConnection, self).get_state(short)
d.update(
- address={"address": self.address(), "use_ipv6": self.address.use_ipv6},
- clientcert=self.cert.to_pem() if self.clientcert else None
- )
+ address={
+ "address": self.address(),
+ "use_ipv6": self.address.use_ipv6},
+ clientcert=self.cert.to_pem() if self.clientcert else None)
return d
def load_state(self, state):
super(ClientConnection, self).load_state(state)
- self.address = tcp.Address(**state["address"]) if state["address"] else None
- self.clientcert = certutils.SSLCert.from_pem(state["clientcert"]) if state["clientcert"] else None
+ self.address = tcp.Address(
+ **state["address"]) if state["address"] else None
+ self.clientcert = certutils.SSLCert.from_pem(
+ state["clientcert"]) if state["clientcert"] else None
def copy(self):
return copy.copy(self)
@@ -114,7 +119,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
address={"address": self.address(),
"use_ipv6": self.address.use_ipv6},
source_address= ({"address": self.source_address(),
- "use_ipv6": self.source_address.use_ipv6} if self.source_address else None),
+ "use_ipv6": self.source_address.use_ipv6} if self.source_address else None),
cert=self.cert.to_pem() if self.cert else None
)
return d
@@ -122,9 +127,12 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
def load_state(self, state):
super(ServerConnection, self).load_state(state)
- self.address = tcp.Address(**state["address"]) if state["address"] else None
- self.source_address = tcp.Address(**state["source_address"]) if state["source_address"] else None
- self.cert = certutils.SSLCert.from_pem(state["cert"]) if state["cert"] else None
+ self.address = tcp.Address(
+ **state["address"]) if state["address"] else None
+ self.source_address = tcp.Address(
+ **state["source_address"]) if state["source_address"] else None
+ self.cert = certutils.SSLCert.from_pem(
+ state["cert"]) if state["cert"] else None
@classmethod
def from_state(cls, state):
@@ -147,7 +155,9 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
def establish_ssl(self, clientcerts, sni, **kwargs):
clientcert = None
if clientcerts:
- path = os.path.join(clientcerts, self.address.host.encode("idna")) + ".pem"
+ path = os.path.join(
+ clientcerts,
+ self.address.host.encode("idna")) + ".pem"
if os.path.exists(path):
clientcert = path
self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
diff --git a/libmproxy/proxy/primitives.py b/libmproxy/proxy/primitives.py
index c0ae424d..9e7dae9a 100644
--- a/libmproxy/proxy/primitives.py
+++ b/libmproxy/proxy/primitives.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from netlib import socks
+
class ProxyError(Exception):
def __init__(self, code, message, headers=None):
super(ProxyError, self).__init__(message)
@@ -61,7 +62,7 @@ class TransparentProxyMode(ProxyMode):
def get_upstream_server(self, client_conn):
try:
dst = self.resolver.original_addr(client_conn.connection)
- except Exception, e:
+ except Exception as e:
raise ProxyError(502, "Transparent mode failure: %s" % str(e))
if dst[1] in self.sslports:
@@ -87,7 +88,9 @@ class Socks5ProxyMode(ProxyMode):
guess = ""
raise socks.SocksError(
socks.REP.GENERAL_SOCKS_SERVER_FAILURE,
- guess + "Invalid SOCKS version. Expected 0x05, got 0x%x" % msg.ver)
+ guess +
+ "Invalid SOCKS version. Expected 0x05, got 0x%x" %
+ msg.ver)
def get_upstream_server(self, client_conn):
try:
@@ -117,13 +120,15 @@ class Socks5ProxyMode(ProxyMode):
"mitmproxy only supports SOCKS5 CONNECT."
)
- # We do not connect here yet, as the clientconnect event has not been handled yet.
+ # We do not connect here yet, as the clientconnect event has not
+ # been handled yet.
connect_reply = socks.Message(
socks.VERSION.SOCKS5,
socks.REP.SUCCEEDED,
socks.ATYP.DOMAINNAME,
- client_conn.address # dummy value, we don't have an upstream connection yet.
+ # dummy value, we don't have an upstream connection yet.
+ client_conn.address
)
connect_reply.to_file(client_conn.wfile)
client_conn.wfile.flush()
@@ -161,4 +166,4 @@ class UpstreamProxyMode(_ConstDestinationProxyMode):
class Log:
def __init__(self, msg, level="info"):
self.msg = msg
- self.level = level \ No newline at end of file
+ self.level = level
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index a72f9aba..e1587df1 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -34,7 +34,7 @@ class ProxyServer(tcp.TCPServer):
self.config = config
try:
tcp.TCPServer.__init__(self, (config.host, config.port))
- except socket.error, v:
+ except socket.error as v:
raise ProxyServerError('Error starting proxy server: ' + repr(v))
self.channel = None
@@ -46,16 +46,30 @@ class ProxyServer(tcp.TCPServer):
self.channel = channel
def handle_client_connection(self, conn, client_address):
- h = ConnectionHandler(self.config, conn, client_address, self, self.channel)
+ h = ConnectionHandler(
+ self.config,
+ conn,
+ client_address,
+ self,
+ self.channel)
h.handle()
h.finish()
class ConnectionHandler:
- def __init__(self, config, client_connection, client_address, server, channel):
+ def __init__(
+ self,
+ config,
+ client_connection,
+ client_address,
+ server,
+ channel):
self.config = config
"""@type: libmproxy.proxy.config.ProxyConfig"""
- self.client_conn = ClientConnection(client_connection, client_address, server)
+ self.client_conn = ClientConnection(
+ client_connection,
+ client_address,
+ server)
"""@type: libmproxy.proxy.connection.ClientConnection"""
self.server_conn = None
"""@type: libmproxy.proxy.connection.ServerConnection"""
@@ -70,17 +84,23 @@ class ConnectionHandler:
# Can we already identify the target server and connect to it?
client_ssl, server_ssl = False, False
conn_kwargs = dict()
- upstream_info = self.config.mode.get_upstream_server(self.client_conn)
+ upstream_info = self.config.mode.get_upstream_server(
+ self.client_conn)
if upstream_info:
self.set_server_address(upstream_info[2:])
client_ssl, server_ssl = upstream_info[:2]
if self.config.check_ignore(self.server_conn.address):
- self.log("Ignore host: %s:%s" % self.server_conn.address(), "info")
+ self.log(
+ "Ignore host: %s:%s" %
+ self.server_conn.address(),
+ "info")
self.conntype = "tcp"
conn_kwargs["log"] = False
client_ssl, server_ssl = False, False
else:
- pass # No upstream info from the metadata: upstream info in the protocol (e.g. HTTP absolute-form)
+ # No upstream info from the metadata: upstream info in the
+ # protocol (e.g. HTTP absolute-form)
+ pass
self.channel.ask("clientconnect", self)
@@ -92,11 +112,17 @@ class ConnectionHandler:
self.establish_ssl(client=client_ssl, server=server_ssl)
if self.config.check_tcp(self.server_conn.address):
- self.log("Generic TCP mode for host: %s:%s" % self.server_conn.address(), "info")
+ self.log(
+ "Generic TCP mode for host: %s:%s" %
+ self.server_conn.address(),
+ "info")
self.conntype = "tcp"
# Delegate handling to the protocol handler
- protocol_handler(self.conntype)(self, **conn_kwargs).handle_messages()
+ protocol_handler(
+ self.conntype)(
+ self,
+ **conn_kwargs).handle_messages()
self.log("clientdisconnect", "info")
self.channel.tell("clientdisconnect", self)
@@ -104,7 +130,8 @@ class ConnectionHandler:
except ProxyError as e:
protocol_handler(self.conntype)(self, **conn_kwargs).handle_error(e)
except Exception:
- import traceback, sys
+ import traceback
+ import sys
self.log(traceback.format_exc(), "error")
print >> sys.stderr, traceback.format_exc()
@@ -112,7 +139,8 @@ class ConnectionHandler:
print >> sys.stderr, "Please lodge a bug report at: https://github.com/mitmproxy/mitmproxy"
finally:
# Make sure that we close the server connection in any case.
- # The client connection is closed by the ProxyServer and does not have be handled here.
+ # The client connection is closed by the ProxyServer and does not
+ # have be handled here.
self.del_server_connection()
def del_server_connection(self):
@@ -122,8 +150,10 @@ class ConnectionHandler:
if self.server_conn and self.server_conn.connection:
self.server_conn.finish()
self.server_conn.close()
- self.log("serverdisconnect", "debug", ["%s:%s" % (self.server_conn.address.host,
- self.server_conn.address.port)])
+ self.log(
+ "serverdisconnect", "debug", [
+ "%s:%s" %
+ (self.server_conn.address.host, self.server_conn.address.port)])
self.channel.tell("serverdisconnect", self)
self.server_conn = None
@@ -141,7 +171,9 @@ class ConnectionHandler:
if self.server_conn:
self.del_server_connection()
- self.log("Set new server address: %s:%s" % (address.host, address.port), "debug")
+ self.log(
+ "Set new server address: %s:%s" %
+ (address.host, address.port), "debug")
self.server_conn = ServerConnection(address)
def establish_server_connection(self, ask=True):
@@ -155,12 +187,16 @@ class ConnectionHandler:
"""
if self.server_conn.connection:
return
- self.log("serverconnect", "debug", ["%s:%s" % self.server_conn.address()[:2]])
+ self.log(
+ "serverconnect", "debug", [
+ "%s:%s" %
+ self.server_conn.address()[
+ :2]])
if ask:
self.channel.ask("serverconnect", self)
try:
self.server_conn.connect()
- except tcp.NetLibError, v:
+ except tcp.NetLibError as v:
raise ProxyError(502, v)
def establish_ssl(self, client=False, server=False, sni=None):
@@ -237,7 +273,8 @@ class ConnectionHandler:
self.server_conn.state = state
# Receiving new_sni where had_ssl is False is a weird case that happens when the workaround for
- # https://github.com/mitmproxy/mitmproxy/issues/427 is active. In this case, we want to establish SSL as well.
+ # https://github.com/mitmproxy/mitmproxy/issues/427 is active. In this
+ # case, we want to establish SSL as well.
if had_ssl or new_sni:
self.establish_ssl(server=True, sni=sni)
@@ -246,8 +283,10 @@ class ConnectionHandler:
def log(self, msg, level, subs=()):
msg = [
- "%s:%s: %s" % (self.client_conn.address.host, self.client_conn.address.port, msg)
- ]
+ "%s:%s: %s" %
+ (self.client_conn.address.host,
+ self.client_conn.address.port,
+ msg)]
for i in subs:
msg.append(" -> " + i)
msg = "\n".join(msg)
@@ -255,11 +294,13 @@ class ConnectionHandler:
def find_cert(self):
if self.config.certforward and self.server_conn.ssl_established:
- return self.server_conn.cert, self.config.certstore.gen_pkey(self.server_conn.cert), None
+ return self.server_conn.cert, self.config.certstore.gen_pkey(
+ self.server_conn.cert), None
else:
host = self.server_conn.address.host
sans = []
- if self.server_conn.ssl_established and (not self.config.no_upstream_cert):
+ if self.server_conn.ssl_established and (
+ not self.config.no_upstream_cert):
upstream_cert = self.server_conn.cert
sans.extend(upstream_cert.altnames)
if upstream_cert.cn:
@@ -291,8 +332,11 @@ class ConnectionHandler:
# - We established SSL with the server previously
# - We initially wanted to establish SSL with the server,
# but the server refused to negotiate without SNI.
- if self.server_conn.ssl_established or hasattr(self.server_conn, "may_require_sni"):
- self.server_reconnect(sni) # reconnect to upstream server with SNI
+ if self.server_conn.ssl_established or hasattr(
+ self.server_conn,
+ "may_require_sni"):
+ # reconnect to upstream server with SNI
+ self.server_reconnect(sni)
# Now, change client context to reflect changed certificate:
cert, key, chain_file = self.find_cert()
new_context = self.client_conn.create_ssl_context(
@@ -308,4 +352,7 @@ class ConnectionHandler:
# make dang sure it doesn't happen.
except: # pragma: no cover
import traceback
- self.log("Error in handle_sni:\r\n" + traceback.format_exc(), "error")
+ self.log(
+ "Error in handle_sni:\r\n" +
+ traceback.format_exc(),
+ "error")
diff --git a/libmproxy/script.py b/libmproxy/script.py
index be226004..4c550342 100644
--- a/libmproxy/script.py
+++ b/libmproxy/script.py
@@ -1,7 +1,11 @@
from __future__ import absolute_import
-import os, traceback, threading, shlex
+import os
+import traceback
+import threading
+import shlex
from . import controller
+
class ScriptError(Exception):
pass
@@ -56,6 +60,7 @@ class Script:
s = Script(argv, master)
s.load()
"""
+
def __init__(self, command, master):
self.command = command
self.argv = self.parse_command(command)
@@ -73,9 +78,11 @@ class Script:
args = shlex.split(command)
args[0] = os.path.expanduser(args[0])
if not os.path.exists(args[0]):
- raise ScriptError(("Script file not found: %s.\r\n"
- "If you script path contains spaces, "
- "make sure to wrap it in additional quotes, e.g. -s \"'./foo bar/baz.py' --args\".") % args[0])
+ raise ScriptError(
+ ("Script file not found: %s.\r\n"
+ "If you script path contains spaces, "
+ "make sure to wrap it in additional quotes, e.g. -s \"'./foo bar/baz.py' --args\".") %
+ args[0])
elif not os.path.isfile(args[0]):
raise ScriptError("Not a file: %s" % args[0])
return args
@@ -90,7 +97,7 @@ class Script:
ns = {}
try:
execfile(self.argv[0], ns, ns)
- except Exception, v:
+ except Exception as v:
raise ScriptError(traceback.format_exc(v))
self.ns = ns
r = self.run("start", self.argv)
@@ -114,7 +121,7 @@ class Script:
if f:
try:
return (True, f(self.ctx, *args, **kwargs))
- except Exception, v:
+ except Exception as v:
return (False, (v, traceback.format_exc(v)))
else:
return (False, None)
@@ -133,7 +140,7 @@ class ReplyProxy(object):
return
self.original_reply(*args, **kwargs)
- def __getattr__ (self, k):
+ def __getattr__(self, k):
return getattr(self.original_reply, k)
@@ -145,7 +152,8 @@ def _handle_concurrent_reply(fn, o, *args, **kwargs):
def run():
fn(*args, **kwargs)
- reply_proxy() # If the script did not call .reply(), we have to do it now.
+ # If the script did not call .reply(), we have to do it now.
+ reply_proxy()
ScriptThread(target=run).start()
@@ -154,8 +162,15 @@ class ScriptThread(threading.Thread):
def concurrent(fn):
- if fn.func_name in ("request", "response", "error", "clientconnect", "serverconnect", "clientdisconnect"):
+ if fn.func_name in (
+ "request",
+ "response",
+ "error",
+ "clientconnect",
+ "serverconnect",
+ "clientdisconnect"):
def _concurrent(ctx, obj):
_handle_concurrent_reply(fn, obj, ctx, obj)
return _concurrent
- raise NotImplementedError("Concurrent decorator not supported for this method.")
+ raise NotImplementedError(
+ "Concurrent decorator not supported for this method.")
diff --git a/libmproxy/tnetstring.py b/libmproxy/tnetstring.py
index 58519675..bed8405f 100644
--- a/libmproxy/tnetstring.py
+++ b/libmproxy/tnetstring.py
@@ -72,13 +72,14 @@ __ver_major__ = 0
__ver_minor__ = 2
__ver_patch__ = 0
__ver_sub__ = ""
-__version__ = "%d.%d.%d%s" % (__ver_major__,__ver_minor__,__ver_patch__,__ver_sub__)
+__version__ = "%d.%d.%d%s" % (
+ __ver_major__, __ver_minor__, __ver_patch__, __ver_sub__)
from collections import deque
-def dumps(value,encoding=None):
+def dumps(value, encoding=None):
"""dumps(object,encoding=None) -> string
This function dumps a python object as a tnetstring.
@@ -90,21 +91,21 @@ def dumps(value,encoding=None):
# consider the _gdumps() function instead; it's a standard top-down
# generator that's simpler to understand but much less efficient.
q = deque()
- _rdumpq(q,0,value,encoding)
+ _rdumpq(q, 0, value, encoding)
return "".join(q)
-def dump(value,file,encoding=None):
+def dump(value, file, encoding=None):
"""dump(object,file,encoding=None)
This function dumps a python object as a tnetstring and writes it to
the given file.
"""
- file.write(dumps(value,encoding))
+ file.write(dumps(value, encoding))
file.flush()
-def _rdumpq(q,size,value,encoding=None):
+def _rdumpq(q, size, value, encoding=None):
"""Dump value as a tnetstring, to a deque instance, last chunks first.
This function generates the tnetstring representation of the given value,
@@ -129,7 +130,7 @@ def _rdumpq(q,size,value,encoding=None):
if value is False:
write("5:false!")
return size + 8
- if isinstance(value,(int,long)):
+ if isinstance(value, (int, long)):
data = str(value)
ldata = len(data)
span = str(ldata)
@@ -138,7 +139,7 @@ def _rdumpq(q,size,value,encoding=None):
write(":")
write(span)
return size + 2 + len(span) + ldata
- if isinstance(value,(float,)):
+ if isinstance(value, (float,)):
# Use repr() for float rather than str().
# It round-trips more accurately.
# Probably unnecessary in later python versions that
@@ -151,7 +152,7 @@ def _rdumpq(q,size,value,encoding=None):
write(":")
write(span)
return size + 2 + len(span) + ldata
- if isinstance(value,str):
+ if isinstance(value, str):
lvalue = len(value)
span = str(lvalue)
write(",")
@@ -159,26 +160,26 @@ def _rdumpq(q,size,value,encoding=None):
write(":")
write(span)
return size + 2 + len(span) + lvalue
- if isinstance(value,(list,tuple,)):
+ if isinstance(value, (list, tuple,)):
write("]")
init_size = size = size + 1
for item in reversed(value):
- size = _rdumpq(q,size,item,encoding)
+ size = _rdumpq(q, size, item, encoding)
span = str(size - init_size)
write(":")
write(span)
return size + 1 + len(span)
- if isinstance(value,dict):
+ if isinstance(value, dict):
write("}")
init_size = size = size + 1
- for (k,v) in value.iteritems():
- size = _rdumpq(q,size,v,encoding)
- size = _rdumpq(q,size,k,encoding)
+ for (k, v) in value.iteritems():
+ size = _rdumpq(q, size, v, encoding)
+ size = _rdumpq(q, size, k, encoding)
span = str(size - init_size)
write(":")
write(span)
return size + 1 + len(span)
- if isinstance(value,unicode):
+ if isinstance(value, unicode):
if encoding is None:
raise ValueError("must specify encoding to dump unicode strings")
value = value.encode(encoding)
@@ -192,7 +193,7 @@ def _rdumpq(q,size,value,encoding=None):
raise ValueError("unserializable object")
-def _gdumps(value,encoding):
+def _gdumps(value, encoding):
"""Generate fragments of value dumped as a tnetstring.
This is the naive dumping algorithm, implemented as a generator so that
@@ -207,24 +208,24 @@ def _gdumps(value,encoding):
yield "4:true!"
elif value is False:
yield "5:false!"
- elif isinstance(value,(int,long)):
+ elif isinstance(value, (int, long)):
data = str(value)
yield str(len(data))
yield ":"
yield data
yield "#"
- elif isinstance(value,(float,)):
+ elif isinstance(value, (float,)):
data = repr(value)
yield str(len(data))
yield ":"
yield data
yield "^"
- elif isinstance(value,(str,)):
+ elif isinstance(value, (str,)):
yield str(len(value))
yield ":"
yield value
yield ","
- elif isinstance(value,(list,tuple,)):
+ elif isinstance(value, (list, tuple,)):
sub = []
for item in value:
sub.extend(_gdumps(item))
@@ -233,9 +234,9 @@ def _gdumps(value,encoding):
yield ":"
yield sub
yield "]"
- elif isinstance(value,(dict,)):
+ elif isinstance(value, (dict,)):
sub = []
- for (k,v) in value.iteritems():
+ for (k, v) in value.iteritems():
sub.extend(_gdumps(k))
sub.extend(_gdumps(v))
sub = "".join(sub)
@@ -243,7 +244,7 @@ def _gdumps(value,encoding):
yield ":"
yield sub
yield "}"
- elif isinstance(value,(unicode,)):
+ elif isinstance(value, (unicode,)):
if encoding is None:
raise ValueError("must specify encoding to dump unicode strings")
value = value.encode(encoding)
@@ -255,7 +256,7 @@ def _gdumps(value,encoding):
raise ValueError("unserializable object")
-def loads(string,encoding=None):
+def loads(string, encoding=None):
"""loads(string,encoding=None) -> object
This function parses a tnetstring into a python object.
@@ -263,10 +264,10 @@ def loads(string,encoding=None):
# No point duplicating effort here. In the C-extension version,
# loads() is measurably faster then pop() since it can avoid
# the overhead of building a second string.
- return pop(string,encoding)[0]
+ return pop(string, encoding)[0]
-def load(file,encoding=None):
+def load(file, encoding=None):
"""load(file,encoding=None) -> object
This function reads a tnetstring from a file and parses it into a
@@ -324,21 +325,20 @@ def load(file,encoding=None):
if type == "]":
l = []
while data:
- (item,data) = pop(data,encoding)
+ (item, data) = pop(data, encoding)
l.append(item)
return l
if type == "}":
d = {}
while data:
- (key,data) = pop(data,encoding)
- (val,data) = pop(data,encoding)
+ (key, data) = pop(data, encoding)
+ (val, data) = pop(data, encoding)
d[key] = val
return d
raise ValueError("unknown type tag")
-
-def pop(string,encoding=None):
+def pop(string, encoding=None):
"""pop(string,encoding=None) -> (object, remain)
This function parses a tnetstring into a python object.
@@ -347,12 +347,12 @@ def pop(string,encoding=None):
"""
# Parse out data length, type and remaining string.
try:
- (dlen,rest) = string.split(":",1)
+ (dlen, rest) = string.split(":", 1)
dlen = int(dlen)
except ValueError:
raise ValueError("not a tnetstring: missing or invalid length prefix")
try:
- (data,type,remain) = (rest[:dlen],rest[dlen],rest[dlen+1:])
+ (data, type, remain) = (rest[:dlen], rest[dlen], rest[dlen + 1:])
except IndexError:
# This fires if len(rest) < dlen, meaning we don't need
# to further validate that data is the right length.
@@ -360,40 +360,40 @@ def pop(string,encoding=None):
# Parse the data based on the type tag.
if type == ",":
if encoding is not None:
- return (data.decode(encoding),remain)
- return (data,remain)
+ return (data.decode(encoding), remain)
+ return (data, remain)
if type == "#":
try:
- return (int(data),remain)
+ return (int(data), remain)
except ValueError:
raise ValueError("not a tnetstring: invalid integer literal")
if type == "^":
try:
- return (float(data),remain)
+ return (float(data), remain)
except ValueError:
raise ValueError("not a tnetstring: invalid float literal")
if type == "!":
if data == "true":
- return (True,remain)
+ return (True, remain)
elif data == "false":
- return (False,remain)
+ return (False, remain)
else:
raise ValueError("not a tnetstring: invalid boolean literal")
if type == "~":
if data:
raise ValueError("not a tnetstring: invalid null literal")
- return (None,remain)
+ return (None, remain)
if type == "]":
l = []
while data:
- (item,data) = pop(data,encoding)
+ (item, data) = pop(data, encoding)
l.append(item)
- return (l,remain)
+ return (l, remain)
if type == "}":
d = {}
while data:
- (key,data) = pop(data,encoding)
- (val,data) = pop(data,encoding)
+ (key, data) = pop(data, encoding)
+ (val, data) = pop(data, encoding)
d[key] = val
- return (d,remain)
+ return (d, remain)
raise ValueError("unknown type tag")
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index 7d0e369b..a29a53f5 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -1,8 +1,14 @@
from __future__ import absolute_import
-import os, datetime, urllib, re
-import time, functools, cgi
+import os
+import datetime
+import urllib
+import re
+import time
+import functools
+import cgi
import json
+
def timestamp():
"""
Returns a serializable UTC timestamp.
@@ -91,7 +97,7 @@ def multipartdecode(hdrs, content):
match = rx.search(parts[1])
if match:
key = match.group(1)
- value = "".join(parts[3+parts[2:].index(""):])
+ value = "".join(parts[3 + parts[2:].index(""):])
r.append((key, value))
return r
return []
@@ -107,8 +113,8 @@ def pretty_duration(secs):
for limit, formatter in formatters:
if secs >= limit:
return formatter.format(secs)
- #less than 1 sec
- return "{:.0f}ms".format(secs*1000)
+ # less than 1 sec
+ return "{:.0f}ms".format(secs * 1000)
class Data:
@@ -126,7 +132,7 @@ class Data:
"""
fullpath = os.path.join(self.dirname, path)
if not os.path.exists(fullpath):
- raise ValueError, "dataPath: %s does not exist."%fullpath
+ raise ValueError("dataPath: %s does not exist." % fullpath)
return fullpath
pkg_data = Data(__name__)
@@ -135,10 +141,11 @@ class LRUCache:
"""
A simple LRU cache for generated values.
"""
+
def __init__(self, size=100):
self.size = size
self.cache = {}
- self.cacheList = []
+ self.cacheList = []
def get(self, gen, *args):
"""
@@ -147,7 +154,7 @@ class LRUCache:
*args: A list of immutable arguments, used to establish identiy by
*the cache, and passed to gen to generate values.
"""
- if self.cache.has_key(args):
+ if args in self.cache:
self.cacheList.remove(args)
self.cacheList.insert(0, args)
return self.cache[args]
@@ -195,14 +202,14 @@ def hostport(scheme, host, port):
if (port, scheme) in [(80, "http"), (443, "https")]:
return host
else:
- return "%s:%s"%(host, port)
+ return "%s:%s" % (host, port)
def unparse_url(scheme, host, port, path=""):
"""
Returns a URL string, constructed from the specified compnents.
"""
- return "%s://%s%s"%(scheme, hostport(scheme, host, port), path)
+ return "%s://%s%s" % (scheme, hostport(scheme, host, port), path)
def clean_hanging_newline(t):
@@ -243,7 +250,7 @@ def parse_size(s):
try:
return int(s) * mult
except ValueError:
- raise ValueError("Invalid size specification: %s"%s)
+ raise ValueError("Invalid size specification: %s" % s)
def safe_subn(pattern, repl, target, *args, **kwargs):
diff --git a/libmproxy/version.py b/libmproxy/version.py
index 2e43a05a..6d802202 100644
--- a/libmproxy/version.py
+++ b/libmproxy/version.py
@@ -1,4 +1,4 @@
-IVERSION = (0, 12, 0)
+IVERSION = (0, 12, 1)
VERSION = ".".join(str(i) for i in IVERSION)
MINORVERSION = ".".join(str(i) for i in IVERSION[:2])
NAME = "mitmproxy"
diff --git a/libmproxy/web/__init__.py b/libmproxy/web/__init__.py
index 7016eeb8..a0af7315 100644
--- a/libmproxy/web/__init__.py
+++ b/libmproxy/web/__init__.py
@@ -79,6 +79,7 @@ class WebState(flow.State):
data=[]
)
+
class Options(object):
attributes = [
"app",
@@ -128,15 +129,14 @@ class WebMaster(flow.FlowMaster):
if options.rfile:
try:
self.load_flows_file(options.rfile)
- except flow.FlowReadError, v:
+ except flow.FlowReadError as v:
self.add_event(
- "Could not read flow file: %s"%v,
+ "Could not read flow file: %s" % v,
"error"
)
if self.options.app:
self.start_app(self.options.app_host, self.options.app_port)
-
def tick(self):
flow.FlowMaster.tick(self, self.masterq, timeout=0)
@@ -157,7 +157,8 @@ class WebMaster(flow.FlowMaster):
self.shutdown()
def _process_flow(self, f):
- if self.state.intercept and self.state.intercept(f) and not f.request.is_replay:
+ if self.state.intercept and self.state.intercept(
+ f) and not f.request.is_replay:
f.intercept(self)
else:
f.reply()
diff --git a/libmproxy/web/app.py b/libmproxy/web/app.py
index 9582d97b..69341e76 100644
--- a/libmproxy/web/app.py
+++ b/libmproxy/web/app.py
@@ -27,7 +27,8 @@ class RequestHandler(tornado.web.RequestHandler):
@property
def json(self):
- if not self.request.headers.get("Content-Type").startswith("application/json"):
+ if not self.request.headers.get(
+ "Content-Type").startswith("application/json"):
return None
return json.loads(self.request.body)
@@ -67,8 +68,10 @@ class FiltHelp(RequestHandler):
commands=filt.help
))
+
class WebSocketEventBroadcaster(tornado.websocket.WebSocketHandler):
- connections = None # raise an error if inherited class doesn't specify its own instance.
+ # raise an error if inherited class doesn't specify its own instance.
+ connections = None
def open(self):
self.connections.add(self)
@@ -264,4 +267,4 @@ class Application(tornado.web.Application):
cookie_secret=os.urandom(256),
debug=debug,
)
- super(Application, self).__init__(handlers, **settings) \ No newline at end of file
+ super(Application, self).__init__(handlers, **settings)
diff --git a/mitmdump b/mitmdump
index 8cc4c99f..16087f61 100755
--- a/mitmdump
+++ b/mitmdump
@@ -1,3 +1,3 @@
#!/usr/bin/env python
from libmproxy.main import mitmdump
-mitmdump() \ No newline at end of file
+mitmdump()
diff --git a/mitmproxy b/mitmproxy
index cd22282b..b7c5c94e 100755
--- a/mitmproxy
+++ b/mitmproxy
@@ -1,3 +1,3 @@
#!/usr/bin/env python
from libmproxy.main import mitmproxy
-mitmproxy() \ No newline at end of file
+mitmproxy()
diff --git a/release/mitmdump.spec b/release/mitmdump.spec
index 1707122c..f9b0311c 100644
--- a/release/mitmdump.spec
+++ b/release/mitmdump.spec
@@ -16,6 +16,10 @@ a.datas += Tree(
"./libmproxy/onboarding/static",
prefix="libmproxy/onboarding/static"
)
+a.datas += Tree(
+ "../venv.mitmproxy/lib/python2.7/site-packages/cryptography/hazmat/bindings/openssl/src",
+ prefix = "cryptography/hazmat/bindings/openssl/src"
+)
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
diff --git a/release/mitmproxy.spec b/release/mitmproxy.spec
index cc324aa7..9aab5ef4 100644
--- a/release/mitmproxy.spec
+++ b/release/mitmproxy.spec
@@ -16,6 +16,10 @@ a.datas += Tree(
"./libmproxy/onboarding/static",
prefix="libmproxy/onboarding/static"
)
+a.datas += Tree(
+ "../venv.mitmproxy/lib/python2.7/site-packages/cryptography/hazmat/bindings/openssl/src",
+ prefix = "cryptography/hazmat/bindings/openssl/src"
+)
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
diff --git a/release/mitmweb.spec b/release/mitmweb.spec
index b247ce51..565482e6 100644
--- a/release/mitmweb.spec
+++ b/release/mitmweb.spec
@@ -24,6 +24,10 @@ a.datas += Tree(
"./libmproxy/web/static",
prefix="libmproxy/web/static"
)
+a.datas += Tree(
+ "../venv.mitmproxy/lib/python2.7/site-packages/cryptography/hazmat/bindings/openssl/src",
+ prefix = "cryptography/hazmat/bindings/openssl/src"
+)
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
diff --git a/release/release-checklist b/release/release-checklist
index 154103e9..873c5fcf 100644
--- a/release/release-checklist
+++ b/release/release-checklist
@@ -5,6 +5,9 @@
netlib/netlib/version.py
pathod/libpathod/version.py
+- Ensure that the website style assets have been compiled for production, and
+synced to the docs.
+
- Render the docs:
cshape doc-src doc
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 00000000..bc980d56
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,9 @@
+[flake8]
+max-line-length = 80
+max-complexity = 15
+
+[pep8]
+max-line-length = 80
+max-complexity = 15
+exclude = */contrib/*
+ignore = E251,E309
diff --git a/setup.py b/setup.py
index bffce805..4fa64628 100644
--- a/setup.py
+++ b/setup.py
@@ -67,13 +67,11 @@ setup(
"Topic :: Internet",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: Proxy Servers",
- "Topic :: Software Development :: Testing"
- ],
+ "Topic :: Software Development :: Testing"],
packages=find_packages(),
include_package_data=True,
entry_points={
- 'console_scripts': console_scripts
- },
+ 'console_scripts': console_scripts},
install_requires=list(deps),
extras_require={
'dev': [
@@ -81,19 +79,15 @@ setup(
"nose>=1.3.0",
"nose-cov>=1.6",
"coveralls>=0.4.1",
- "pathod>=%s, <%s" % (
- version.MINORVERSION, version.NEXT_MINORVERSION
- )
- ],
+ "pathod>=%s, <%s" %
+ (version.MINORVERSION,
+ version.NEXT_MINORVERSION),
+ "countershape"],
'contentviews': [
"pyamf>=0.6.1",
"protobuf>=2.5.0",
- "cssutils>=1.0"
- ],
+ "cssutils>=1.0"],
'examples': [
"pytz",
"harparser",
- "beautifulsoup4"
- ]
- }
-)
+ "beautifulsoup4"]})
diff --git a/test/mock_urwid.py b/test/mock_urwid.py
index f132e0bd..191210bf 100644
--- a/test/mock_urwid.py
+++ b/test/mock_urwid.py
@@ -1,8 +1,10 @@
-import os, sys, mock
+import os
+import sys
+import mock
if os.name == "nt":
m = mock.Mock()
m.__version__ = "1.1.1"
m.Widget = mock.Mock
m.WidgetWrap = mock.Mock
sys.modules['urwid'] = m
- sys.modules['urwid.util'] = mock.Mock() \ No newline at end of file
+ sys.modules['urwid.util'] = mock.Mock()
diff --git a/test/scripts/a.py b/test/scripts/a.py
index 1d5717b0..210fea78 100644
--- a/test/scripts/a.py
+++ b/test/scripts/a.py
@@ -4,14 +4,18 @@ parser = argparse.ArgumentParser()
parser.add_argument('--var', type=int)
var = 0
+
+
def start(ctx, argv):
global var
var = parser.parse_args(argv[1:]).var
+
def here(ctx):
global var
var += 1
return var
+
def errargs():
pass
diff --git a/test/scripts/all.py b/test/scripts/all.py
index 3acaf694..dad2aade 100644
--- a/test/scripts/all.py
+++ b/test/scripts/all.py
@@ -1,28 +1,36 @@
log = []
+
+
def clientconnect(ctx, cc):
ctx.log("XCLIENTCONNECT")
log.append("clientconnect")
+
def serverconnect(ctx, cc):
ctx.log("XSERVERCONNECT")
log.append("serverconnect")
+
def request(ctx, f):
ctx.log("XREQUEST")
log.append("request")
+
def response(ctx, f):
ctx.log("XRESPONSE")
log.append("response")
+
def responseheaders(ctx, f):
ctx.log("XRESPONSEHEADERS")
log.append("responseheaders")
+
def clientdisconnect(ctx, cc):
ctx.log("XCLIENTDISCONNECT")
log.append("clientdisconnect")
+
def error(ctx, cc):
ctx.log("XERROR")
log.append("error")
diff --git a/test/scripts/concurrent_decorator.py b/test/scripts/concurrent_decorator.py
index 8e132006..f6feda1d 100644
--- a/test/scripts/concurrent_decorator.py
+++ b/test/scripts/concurrent_decorator.py
@@ -29,4 +29,4 @@ def error(context, err):
@concurrent
def clientdisconnect(context, dc):
- context.log("clientdisconnect") \ No newline at end of file
+ context.log("clientdisconnect")
diff --git a/test/scripts/concurrent_decorator_err.py b/test/scripts/concurrent_decorator_err.py
index 78191315..00fd8dad 100644
--- a/test/scripts/concurrent_decorator_err.py
+++ b/test/scripts/concurrent_decorator_err.py
@@ -1,5 +1,6 @@
from libmproxy.script import concurrent
+
@concurrent
def start(context, argv):
- pass \ No newline at end of file
+ pass
diff --git a/test/scripts/duplicate_flow.py b/test/scripts/duplicate_flow.py
index f1b92309..e13af786 100644
--- a/test/scripts/duplicate_flow.py
+++ b/test/scripts/duplicate_flow.py
@@ -2,4 +2,3 @@
def request(ctx, f):
f = ctx.duplicate_flow(f)
ctx.replay_request(f)
-
diff --git a/test/scripts/stream_modify.py b/test/scripts/stream_modify.py
index 9a98a7ee..e5c323be 100644
--- a/test/scripts/stream_modify.py
+++ b/test/scripts/stream_modify.py
@@ -4,4 +4,4 @@ def modify(chunks):
def responseheaders(context, flow):
- flow.response.stream = modify \ No newline at end of file
+ flow.response.stream = modify
diff --git a/test/test_app.py b/test/test_app.py
index 0b6ed14c..5fb49563 100644
--- a/test/test_app.py
+++ b/test/test_app.py
@@ -1,8 +1,13 @@
-import mock, socket, os, time
+import mock
+import socket
+import os
+import time
from libmproxy import dump
from netlib import certutils, tcp
from libpathod.pathoc import Pathoc
-import tutils, tservers
+import tutils
+import tservers
+
class TestApp(tservers.HTTPProxTest):
def test_basic(self):
diff --git a/test/test_cmdline.py b/test/test_cmdline.py
index f7bf4612..eafcbde4 100644
--- a/test/test_cmdline.py
+++ b/test/test_cmdline.py
@@ -37,13 +37,24 @@ def test_parse_replace_hook():
def test_parse_server_spec():
tutils.raises("Invalid server specification", cmdline.parse_server_spec, "")
- assert cmdline.parse_server_spec("http://foo.com:88") == [False, False, "foo.com", 88]
- assert cmdline.parse_server_spec("http://foo.com") == [False, False, "foo.com", 80]
- assert cmdline.parse_server_spec("https://foo.com") == [True, True, "foo.com", 443]
- assert cmdline.parse_server_spec_special("https2http://foo.com") == [True, False, "foo.com", 80]
- assert cmdline.parse_server_spec_special("http2https://foo.com") == [False, True, "foo.com", 443]
- tutils.raises("Invalid server specification", cmdline.parse_server_spec, "foo.com")
- tutils.raises("Invalid server specification", cmdline.parse_server_spec, "http://")
+ assert cmdline.parse_server_spec(
+ "http://foo.com:88") == [False, False, "foo.com", 88]
+ assert cmdline.parse_server_spec(
+ "http://foo.com") == [False, False, "foo.com", 80]
+ assert cmdline.parse_server_spec(
+ "https://foo.com") == [True, True, "foo.com", 443]
+ assert cmdline.parse_server_spec_special(
+ "https2http://foo.com") == [True, False, "foo.com", 80]
+ assert cmdline.parse_server_spec_special(
+ "http2https://foo.com") == [False, True, "foo.com", 443]
+ tutils.raises(
+ "Invalid server specification",
+ cmdline.parse_server_spec,
+ "foo.com")
+ tutils.raises(
+ "Invalid server specification",
+ cmdline.parse_server_spec,
+ "http://")
def test_parse_setheaders():
@@ -103,7 +114,7 @@ def test_common():
)
p = tutils.test_data.path("data/replace")
- opts.replace_file = [("/foo/bar/%s"%p)]
+ opts.replace_file = [("/foo/bar/%s" % p)]
v = cmdline.get_common_options(opts)["replacements"]
assert len(v) == 1
assert v[0][2].strip() == "replacecontents"
@@ -122,5 +133,3 @@ def test_mitmdump():
def test_mitmweb():
ap = cmdline.mitmweb()
assert ap
-
-
diff --git a/test/test_console.py b/test/test_console.py
index 419b94a7..ed8408a5 100644
--- a/test/test_console.py
+++ b/test/test_console.py
@@ -1,4 +1,7 @@
-import os, sys, mock, gc
+import os
+import sys
+import mock
+import gc
from os.path import normpath
import mock_urwid
from libmproxy import console
@@ -6,6 +9,7 @@ from libmproxy.console import common
import tutils
+
class TestConsoleState:
def test_flow(self):
"""
diff --git a/test/test_console_contentview.py b/test/test_console_contentview.py
index 83dbbb8f..a296376e 100644
--- a/test/test_console_contentview.py
+++ b/test/test_console_contentview.py
@@ -31,40 +31,39 @@ class TestContentView:
def test_view_auto(self):
v = cv.ViewAuto()
f = v(
- odict.ODictCaseless(),
- "foo",
- 1000
- )
+ odict.ODictCaseless(),
+ "foo",
+ 1000
+ )
assert f[0] == "Raw"
f = v(
- odict.ODictCaseless(
- [["content-type", "text/html"]],
- ),
- "<html></html>",
- 1000
- )
+ odict.ODictCaseless(
+ [["content-type", "text/html"]],
+ ),
+ "<html></html>",
+ 1000
+ )
assert f[0] == "HTML"
f = v(
- odict.ODictCaseless(
- [["content-type", "text/flibble"]],
- ),
- "foo",
- 1000
- )
+ odict.ODictCaseless(
+ [["content-type", "text/flibble"]],
+ ),
+ "foo",
+ 1000
+ )
assert f[0] == "Raw"
f = v(
- odict.ODictCaseless(
- [["content-type", "text/flibble"]],
- ),
- "<xml></xml>",
- 1000
- )
+ odict.ODictCaseless(
+ [["content-type", "text/flibble"]],
+ ),
+ "<xml></xml>",
+ 1000
+ )
assert f[0].startswith("XML")
-
def test_view_urlencoded(self):
d = utils.urlencode([("one", "two"), ("three", "four")])
v = cv.ViewURLEncoded()
@@ -91,7 +90,7 @@ class TestContentView:
v = cv.ViewJSON()
assert v([], "{}", 1000)
assert not v([], "{", 1000)
- assert v([], "[" + ",".join(["0"]*cv.VIEW_CUTOFF) + "]", 1000)
+ assert v([], "[" + ",".join(["0"] * cv.VIEW_CUTOFF) + "]", 1000)
assert v([], "[1, 2, 3, 4, 5]", 5)
def test_view_xml(self):
@@ -145,18 +144,18 @@ class TestContentView:
def test_view_image(self):
v = cv.ViewImage()
p = tutils.test_data.path("data/image.png")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
p = tutils.test_data.path("data/image.gif")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
p = tutils.test_data.path("data/image-err1.jpg")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
p = tutils.test_data.path("data/image.ico")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
- assert not v([], "flibble", sys.maxint)
+ assert not v([], "flibble", sys.maxsize)
def test_view_multipart(self):
view = cv.ViewMultipart()
@@ -187,71 +186,70 @@ Larry
def test_get_content_view(self):
r = cv.get_content_view(
- cv.get("Raw"),
- [["content-type", "application/json"]],
- "[1, 2, 3]",
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("Raw"),
+ [["content-type", "application/json"]],
+ "[1, 2, 3]",
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert "Raw" in r[0]
r = cv.get_content_view(
- cv.get("Auto"),
- [["content-type", "application/json"]],
- "[1, 2, 3]",
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("Auto"),
+ [["content-type", "application/json"]],
+ "[1, 2, 3]",
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert r[0] == "JSON"
r = cv.get_content_view(
- cv.get("Auto"),
- [["content-type", "application/json"]],
- "[1, 2",
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("Auto"),
+ [["content-type", "application/json"]],
+ "[1, 2",
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert "Raw" in r[0]
r = cv.get_content_view(
- cv.get("AMF"),
- [],
- "[1, 2",
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("AMF"),
+ [],
+ "[1, 2",
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert "Raw" in r[0]
-
r = cv.get_content_view(
- cv.get("Auto"),
- [
- ["content-type", "application/json"],
- ["content-encoding", "gzip"]
- ],
- encoding.encode('gzip', "[1, 2, 3]"),
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("Auto"),
+ [
+ ["content-type", "application/json"],
+ ["content-encoding", "gzip"]
+ ],
+ encoding.encode('gzip', "[1, 2, 3]"),
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert "decoded gzip" in r[0]
assert "JSON" in r[0]
r = cv.get_content_view(
- cv.get("XML"),
- [
- ["content-type", "application/json"],
- ["content-encoding", "gzip"]
- ],
- encoding.encode('gzip', "[1, 2, 3]"),
- 1000,
- lambda x, l: None,
- False
- )
+ cv.get("XML"),
+ [
+ ["content-type", "application/json"],
+ ["content-encoding", "gzip"]
+ ],
+ encoding.encode('gzip', "[1, 2, 3]"),
+ 1000,
+ lambda x, l: None,
+ False
+ )
assert "decoded gzip" in r[0]
assert "Raw" in r[0]
@@ -261,24 +259,25 @@ if pyamf:
v = cv.ViewAMF()
p = tutils.test_data.path("data/amf01")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
p = tutils.test_data.path("data/amf02")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
def test_view_amf_response():
v = cv.ViewAMF()
p = tutils.test_data.path("data/amf03")
- assert v([], file(p,"rb").read(), sys.maxint)
+ assert v([], file(p, "rb").read(), sys.maxsize)
if cv.ViewProtobuf.is_available():
def test_view_protobuf_request():
v = cv.ViewProtobuf()
p = tutils.test_data.path("data/protobuf01")
- content_type, output = v([], file(p,"rb").read(), sys.maxint)
+ content_type, output = v([], file(p, "rb").read(), sys.maxsize)
assert content_type == "Protobuf"
assert output[0].text == '1: "3bbc333c-e61c-433b-819a-0b9a8cc103b8"'
+
def test_get_by_shortcut():
assert cv.get_by_shortcut("h")
diff --git a/test/test_console_help.py b/test/test_console_help.py
index 24517439..a7a8b745 100644
--- a/test/test_console_help.py
+++ b/test/test_console_help.py
@@ -5,10 +5,12 @@ if os.name == "nt":
import libmproxy.console.help as help
+
class DummyLoop:
def __init__(self):
self.widget = None
+
class DummyMaster:
def __init__(self):
self.loop = DummyLoop()
diff --git a/test/test_controller.py b/test/test_controller.py
index e71a148e..d287f18d 100644
--- a/test/test_controller.py
+++ b/test/test_controller.py
@@ -8,5 +8,3 @@ class TestMaster:
msg = mock.MagicMock()
m.handle("type", msg)
assert msg.reply.call_count == 1
-
-
diff --git a/test/test_dump.py b/test/test_dump.py
index 48eeb244..e3743ac6 100644
--- a/test/test_dump.py
+++ b/test/test_dump.py
@@ -116,7 +116,6 @@ class TestDumpMaster:
0, None, "", verbosity=1, rfile="test_dump.py"
)
-
def test_options(self):
o = dump.Options(verbosity = 2)
assert o.verbosity == 2
@@ -147,21 +146,25 @@ class TestDumpMaster:
def test_basic(self):
for i in (1, 2, 3):
assert "GET" in self._dummy_cycle(1, "~s", "", flow_detail=i)
- assert "GET" in self._dummy_cycle(1, "~s", "\x00\x00\x00", flow_detail=i)
+ assert "GET" in self._dummy_cycle(
+ 1,
+ "~s",
+ "\x00\x00\x00",
+ flow_detail=i)
assert "GET" in self._dummy_cycle(1, "~s", "ascii", flow_detail=i)
def test_write(self):
with tutils.tmpdir() as d:
p = os.path.join(d, "a")
- self._dummy_cycle(1, None, "", outfile=(p,"wb"), verbosity=0)
- assert len(list(flow.FlowReader(open(p,"rb")).stream())) == 1
+ self._dummy_cycle(1, None, "", outfile=(p, "wb"), verbosity=0)
+ assert len(list(flow.FlowReader(open(p, "rb")).stream())) == 1
def test_write_append(self):
with tutils.tmpdir() as d:
p = os.path.join(d, "a.append")
- self._dummy_cycle(1, None, "", outfile=(p,"wb"), verbosity=0)
- self._dummy_cycle(1, None, "", outfile=(p,"ab"), verbosity=0)
- assert len(list(flow.FlowReader(open(p,"rb")).stream())) == 2
+ self._dummy_cycle(1, None, "", outfile=(p, "wb"), verbosity=0)
+ self._dummy_cycle(1, None, "", outfile=(p, "ab"), verbosity=0)
+ assert len(list(flow.FlowReader(open(p, "rb")).stream())) == 2
def test_write_err(self):
tutils.raises(
diff --git a/test/test_encoding.py b/test/test_encoding.py
index 732447e2..e13f5dce 100644
--- a/test/test_encoding.py
+++ b/test/test_encoding.py
@@ -1,5 +1,6 @@
from libmproxy import encoding
+
def test_identity():
assert "string" == encoding.decode("identity", "string")
assert "string" == encoding.encode("identity", "string")
@@ -8,12 +9,25 @@ def test_identity():
def test_gzip():
- assert "string" == encoding.decode("gzip", encoding.encode("gzip", "string"))
+ assert "string" == encoding.decode(
+ "gzip",
+ encoding.encode(
+ "gzip",
+ "string"))
assert None == encoding.decode("gzip", "bogus")
def test_deflate():
- assert "string" == encoding.decode("deflate", encoding.encode("deflate", "string"))
- assert "string" == encoding.decode("deflate", encoding.encode("deflate", "string")[2:-4])
+ assert "string" == encoding.decode(
+ "deflate",
+ encoding.encode(
+ "deflate",
+ "string"))
+ assert "string" == encoding.decode(
+ "deflate",
+ encoding.encode(
+ "deflate",
+ "string")[
+ 2:-
+ 4])
assert None == encoding.decode("deflate", "bogus")
-
diff --git a/test/test_examples.py b/test/test_examples.py
index fd901b5d..e9bccd2e 100644
--- a/test/test_examples.py
+++ b/test/test_examples.py
@@ -21,7 +21,7 @@ def test_load_scripts():
f += " foo bar" # two arguments required
try:
s = script.Script(f, tmaster) # Loads the script file.
- except Exception, v:
+ except Exception as v:
if not "ImportError" in str(v):
raise
else:
diff --git a/test/test_filt.py b/test/test_filt.py
index 97b8e73c..3ad17dfe 100644
--- a/test/test_filt.py
+++ b/test/test_filt.py
@@ -5,6 +5,7 @@ from libmproxy.protocol import http
from libmproxy.protocol.primitives import Error
import tutils
+
class TestParsing:
def _dump(self, x):
c = cStringIO.StringIO()
@@ -99,7 +100,15 @@ class TestMatching:
headers = odict.ODictCaseless()
headers["header_response"] = ["svalue"]
- f.response = http.HTTPResponse((1, 1), 200, "OK", headers, "content_response", None, None)
+ f.response = http.HTTPResponse(
+ (1,
+ 1),
+ 200,
+ "OK",
+ headers,
+ "content_response",
+ None,
+ None)
return f
diff --git a/test/test_flow.py b/test/test_flow.py
index f5d06906..2609b7cb 100644
--- a/test/test_flow.py
+++ b/test/test_flow.py
@@ -1,4 +1,6 @@
-import Queue, time, os.path
+import Queue
+import time
+import os.path
from cStringIO import StringIO
import email.utils
import mock
@@ -33,7 +35,6 @@ def test_app_registry():
assert ar.get(r)
-
class TestStickyCookieState:
def _response(self, cookie, host):
s = flow.StickyCookieState(filt.parse(".*"))
@@ -115,7 +116,15 @@ class TestClientPlaybackState:
class TestServerPlaybackState:
def test_hash(self):
- s = flow.ServerPlaybackState(None, [], False, False, None, False, None, False)
+ s = flow.ServerPlaybackState(
+ None,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
r = tutils.tflow()
r2 = tutils.tflow()
@@ -131,7 +140,15 @@ class TestServerPlaybackState:
assert s._hash(r) != s._hash(r2)
def test_headers(self):
- s = flow.ServerPlaybackState(["foo"], [], False, False, None, False, None, False)
+ s = flow.ServerPlaybackState(
+ ["foo"],
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
r = tutils.tflow(resp=True)
r.request.headers["foo"] = ["bar"]
r2 = tutils.tflow(resp=True)
@@ -152,7 +169,9 @@ class TestServerPlaybackState:
r2 = tutils.tflow(resp=True)
r2.request.headers["key"] = ["two"]
- s = flow.ServerPlaybackState(None, [r, r2], False, False, None, False, None, False)
+ s = flow.ServerPlaybackState(
+ None, [
+ r, r2], False, False, None, False, None, False)
assert s.count() == 2
assert len(s.fmap.keys()) == 1
@@ -173,34 +192,41 @@ class TestServerPlaybackState:
r2 = tutils.tflow(resp=True)
r2.request.headers["key"] = ["two"]
- s = flow.ServerPlaybackState(None, [r, r2], False, True, None, False, None, False)
+ s = flow.ServerPlaybackState(
+ None, [
+ r, r2], False, True, None, False, None, False)
assert s.count() == 2
s.next_flow(r)
assert s.count() == 2
-
def test_ignore_params(self):
- s = flow.ServerPlaybackState(None, [], False, False, ["param1", "param2"], False, None, False)
+ s = flow.ServerPlaybackState(
+ None, [], False, False, [
+ "param1", "param2"], False, None, False)
r = tutils.tflow(resp=True)
- r.request.path="/test?param1=1"
+ r.request.path = "/test?param1=1"
r2 = tutils.tflow(resp=True)
- r2.request.path="/test"
+ r2.request.path = "/test"
assert s._hash(r) == s._hash(r2)
- r2.request.path="/test?param1=2"
+ r2.request.path = "/test?param1=2"
assert s._hash(r) == s._hash(r2)
- r2.request.path="/test?param2=1"
+ r2.request.path = "/test?param2=1"
assert s._hash(r) == s._hash(r2)
- r2.request.path="/test?param3=2"
+ r2.request.path = "/test?param3=2"
assert not s._hash(r) == s._hash(r2)
def test_ignore_payload_params(self):
- s = flow.ServerPlaybackState(None, [], False, False, None, False, ["param1", "param2"], False)
+ s = flow.ServerPlaybackState(
+ None, [], False, False, None, False, [
+ "param1", "param2"], False)
r = tutils.tflow(resp=True)
- r.request.headers["Content-Type"] = ["application/x-www-form-urlencoded"]
+ r.request.headers[
+ "Content-Type"] = ["application/x-www-form-urlencoded"]
r.request.content = "paramx=x&param1=1"
r2 = tutils.tflow(resp=True)
- r2.request.headers["Content-Type"] = ["application/x-www-form-urlencoded"]
+ r2.request.headers[
+ "Content-Type"] = ["application/x-www-form-urlencoded"]
r2.request.content = "paramx=x&param1=1"
# same parameters
assert s._hash(r) == s._hash(r2)
@@ -208,20 +234,22 @@ class TestServerPlaybackState:
r2.request.content = "paramx=x&param1=2"
assert s._hash(r) == s._hash(r2)
# missing parameter
- r2.request.content="paramx=x"
+ r2.request.content = "paramx=x"
assert s._hash(r) == s._hash(r2)
# ignorable parameter added
- r2.request.content="paramx=x&param1=2"
+ r2.request.content = "paramx=x&param1=2"
assert s._hash(r) == s._hash(r2)
# not ignorable parameter changed
- r2.request.content="paramx=y&param1=1"
+ r2.request.content = "paramx=y&param1=1"
assert not s._hash(r) == s._hash(r2)
# not ignorable parameter missing
- r2.request.content="param1=1"
+ r2.request.content = "param1=1"
assert not s._hash(r) == s._hash(r2)
def test_ignore_payload_params_other_content_type(self):
- s = flow.ServerPlaybackState(None, [], False, False, None, False, ["param1", "param2"], False)
+ s = flow.ServerPlaybackState(
+ None, [], False, False, None, False, [
+ "param1", "param2"], False)
r = tutils.tflow(resp=True)
r.request.headers["Content-Type"] = ["application/json"]
r.request.content = '{"param1":"1"}'
@@ -235,19 +263,31 @@ class TestServerPlaybackState:
assert not s._hash(r) == s._hash(r2)
def test_ignore_payload_wins_over_params(self):
- #NOTE: parameters are mutually exclusive in options
- s = flow.ServerPlaybackState(None, [], False, False, None, True, ["param1", "param2"], False)
+ # NOTE: parameters are mutually exclusive in options
+ s = flow.ServerPlaybackState(
+ None, [], False, False, None, True, [
+ "param1", "param2"], False)
r = tutils.tflow(resp=True)
- r.request.headers["Content-Type"] = ["application/x-www-form-urlencoded"]
+ r.request.headers[
+ "Content-Type"] = ["application/x-www-form-urlencoded"]
r.request.content = "paramx=y"
r2 = tutils.tflow(resp=True)
- r2.request.headers["Content-Type"] = ["application/x-www-form-urlencoded"]
+ r2.request.headers[
+ "Content-Type"] = ["application/x-www-form-urlencoded"]
r2.request.content = "paramx=x"
# same parameters
assert s._hash(r) == s._hash(r2)
def test_ignore_content(self):
- s = flow.ServerPlaybackState(None, [], False, False, None, False, None, False)
+ s = flow.ServerPlaybackState(
+ None,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
r = tutils.tflow(resp=True)
r2 = tutils.tflow(resp=True)
@@ -257,8 +297,16 @@ class TestServerPlaybackState:
r2.request.content = "bar"
assert not s._hash(r) == s._hash(r2)
- #now ignoring content
- s = flow.ServerPlaybackState(None, [], False, False, None, True, None, False)
+ # now ignoring content
+ s = flow.ServerPlaybackState(
+ None,
+ [],
+ False,
+ False,
+ None,
+ True,
+ None,
+ False)
r = tutils.tflow(resp=True)
r2 = tutils.tflow(resp=True)
r.request.content = "foo"
@@ -272,14 +320,22 @@ class TestServerPlaybackState:
assert s._hash(r) == s._hash(r2)
def test_ignore_host(self):
- s = flow.ServerPlaybackState(None, [], False, False, None, False, None, True)
+ s = flow.ServerPlaybackState(
+ None,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ True)
r = tutils.tflow(resp=True)
r2 = tutils.tflow(resp=True)
- r.request.host="address"
- r2.request.host="address"
+ r.request.host = "address"
+ r2.request.host = "address"
assert s._hash(r) == s._hash(r2)
- r2.request.host="wrong_address"
+ r2.request.host = "wrong_address"
assert s._hash(r) == s._hash(r2)
@@ -343,12 +399,14 @@ class TestFlow:
def test_getset_state(self):
f = tutils.tflow(resp=True)
state = f.get_state()
- assert f.get_state() == protocol.http.HTTPFlow.from_state(state).get_state()
+ assert f.get_state() == protocol.http.HTTPFlow.from_state(
+ state).get_state()
f.response = None
f.error = Error("error")
state = f.get_state()
- assert f.get_state() == protocol.http.HTTPFlow.from_state(state).get_state()
+ assert f.get_state() == protocol.http.HTTPFlow.from_state(
+ state).get_state()
f2 = f.copy()
f2.id = f.id # copy creates a different uuid
@@ -430,7 +488,6 @@ class TestFlow:
assert f.response.content == "abarb"
-
class TestState:
def test_backup(self):
c = flow.State()
@@ -519,7 +576,7 @@ class TestState:
assert c.intercept_txt == "~q"
assert "Invalid" in c.set_intercept("~")
assert not c.set_intercept(None)
- assert c.intercept_txt == None
+ assert c.intercept_txt is None
def _add_request(self, state):
f = tutils.tflow()
@@ -608,7 +665,13 @@ class TestSerialize:
def test_load_flows_reverse(self):
r = self._treader()
s = flow.State()
- conf = ProxyConfig(mode="reverse", upstream_server=[True,True,"use-this-domain",80])
+ conf = ProxyConfig(
+ mode="reverse",
+ upstream_server=[
+ True,
+ True,
+ "use-this-domain",
+ 80])
fm = flow.FlowMaster(DummyServer(conf), s)
fm.load_flows(r)
assert s.flows[0].request.host == "use-this-domain"
@@ -630,7 +693,6 @@ class TestSerialize:
r = flow.FlowReader(sio)
assert len(list(r.stream()))
-
def test_error(self):
sio = StringIO()
sio.write("bogus")
@@ -661,7 +723,8 @@ class TestFlowMaster:
assert not fm.load_script(tutils.test_data.path("scripts/a.py"))
assert not fm.unload_scripts()
assert fm.load_script("nonexistent")
- assert "ValueError" in fm.load_script(tutils.test_data.path("scripts/starterr.py"))
+ assert "ValueError" in fm.load_script(
+ tutils.test_data.path("scripts/starterr.py"))
assert len(fm.scripts) == 0
def test_getset_ignore(self):
@@ -707,14 +770,14 @@ class TestFlowMaster:
assert fm.scripts[0].ns["log"][-1] == "request"
fm.handle_response(f)
assert fm.scripts[0].ns["log"][-1] == "response"
- #load second script
+ # load second script
assert not fm.load_script(tutils.test_data.path("scripts/all.py"))
assert len(fm.scripts) == 2
fm.handle_clientdisconnect(f.server_conn)
assert fm.scripts[0].ns["log"][-1] == "clientdisconnect"
assert fm.scripts[1].ns["log"][-1] == "clientdisconnect"
- #unload first script
+ # unload first script
fm.unload_scripts()
assert len(fm.scripts) == 0
assert not fm.load_script(tutils.test_data.path("scripts/all.py"))
@@ -765,7 +828,16 @@ class TestFlowMaster:
f = tutils.tflow(resp=True)
pb = [tutils.tflow(resp=True), f]
fm = flow.FlowMaster(DummyServer(ProxyConfig()), s)
- assert not fm.start_server_playback(pb, False, [], False, False, None, False, None, False)
+ assert not fm.start_server_playback(
+ pb,
+ False,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
assert not fm.start_client_playback(pb, False)
fm.client_playback.testing = True
@@ -788,16 +860,43 @@ class TestFlowMaster:
fm.refresh_server_playback = True
assert not fm.do_server_playback(tutils.tflow())
- fm.start_server_playback(pb, False, [], False, False, None, False, None, False)
+ fm.start_server_playback(
+ pb,
+ False,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
assert fm.do_server_playback(tutils.tflow())
- fm.start_server_playback(pb, False, [], True, False, None, False, None, False)
+ fm.start_server_playback(
+ pb,
+ False,
+ [],
+ True,
+ False,
+ None,
+ False,
+ None,
+ False)
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, None, False, None, False)
+ fm.start_server_playback(
+ pb,
+ False,
+ [],
+ True,
+ False,
+ None,
+ False,
+ None,
+ False)
q = Queue.Queue()
fm.tick(q, 0)
assert fm.should_exit.is_set()
@@ -812,7 +911,16 @@ class TestFlowMaster:
pb = [f]
fm = flow.FlowMaster(None, s)
fm.refresh_server_playback = True
- fm.start_server_playback(pb, True, [], False, False, None, False, None, False)
+ fm.start_server_playback(
+ pb,
+ True,
+ [],
+ False,
+ False,
+ None,
+ False,
+ None,
+ False)
f = tutils.tflow()
f.request.host = "nonexistent"
@@ -862,8 +970,9 @@ class TestFlowMaster:
def test_stream(self):
with tutils.tmpdir() as tdir:
p = os.path.join(tdir, "foo")
+
def r():
- r = flow.FlowReader(open(p,"rb"))
+ r = flow.FlowReader(open(p, "rb"))
return list(r.stream())
s = flow.State()
@@ -884,6 +993,7 @@ class TestFlowMaster:
assert not r()[1].response
+
class TestRequest:
def test_simple(self):
f = tutils.tflow()
@@ -919,7 +1029,7 @@ class TestRequest:
r.host = "address"
r.port = 22
- assert r.url== "https://address:22/path"
+ assert r.url == "https://address:22/path"
assert r.pretty_url(True) == "https://address:22/path"
r.headers["Host"] = ["foo.com"]
@@ -1062,6 +1172,7 @@ class TestRequest:
resp.headers = h
assert resp.headers.get_first("content-type") == "text/plain"
+
class TestResponse:
def test_simple(self):
f = tutils.tflow(resp=True)
@@ -1077,7 +1188,9 @@ class TestResponse:
assert resp.size() == len(resp.assemble())
resp.content = CONTENT_MISSING
- tutils.raises("Cannot assemble flow with CONTENT_MISSING", resp.assemble)
+ tutils.raises(
+ "Cannot assemble flow with CONTENT_MISSING",
+ resp.assemble)
def test_refresh(self):
r = tutils.tresp()
@@ -1086,14 +1199,15 @@ class TestResponse:
pre = r.headers["date"]
r.refresh(n)
assert pre == r.headers["date"]
- r.refresh(n+60)
+ r.refresh(n + 60)
d = email.utils.parsedate_tz(r.headers["date"][0])
d = email.utils.mktime_tz(d)
# Weird that this is not exact...
- assert abs(60-(d-n)) <= 1
+ assert abs(60 - (d - n)) <= 1
- r.headers["set-cookie"] = ["MOO=BAR; Expires=Tue, 08-Mar-2011 00:20:38 GMT; Path=foo.com; Secure"]
+ r.headers[
+ "set-cookie"] = ["MOO=BAR; Expires=Tue, 08-Mar-2011 00:20:38 GMT; Path=foo.com; Secure"]
r.refresh()
def test_refresh_cookie(self):
@@ -1146,7 +1260,7 @@ class TestResponse:
def test_header_size(self):
r = tutils.tresp()
result = len(r._assemble_headers())
- assert result==44
+ assert result == 44
def test_get_content_type(self):
h = odict.ODictCaseless()
@@ -1178,7 +1292,7 @@ class TestClientConnection:
c = tutils.tclient_conn()
assert ClientConnection.from_state(c.get_state()).get_state() ==\
- c.get_state()
+ c.get_state()
c2 = tutils.tclient_conn()
c2.address.address = (c2.address.host, 4242)
@@ -1295,7 +1409,6 @@ def test_setheaders():
h.run(f)
assert f.request.content == "foo"
-
h.clear()
h.add("~s", "one", "two")
h.add("~s", "one", "three")
diff --git a/test/test_fuzzing.py b/test/test_fuzzing.py
index 3e5fc100..5e5115c9 100644
--- a/test/test_fuzzing.py
+++ b/test/test_fuzzing.py
@@ -5,16 +5,17 @@ import tservers
after being fixed to check for regressions.
"""
+
class TestFuzzy(tservers.HTTPProxTest):
def test_idna_err(self):
req = r'get:"http://localhost:%s":i10,"\xc6"'
p = self.pathoc()
- assert p.request(req%self.server.port).status_code == 400
+ assert p.request(req % self.server.port).status_code == 400
def test_nullbytes(self):
req = r'get:"http://localhost:%s":i19,"\x00"'
p = self.pathoc()
- assert p.request(req%self.server.port).status_code == 400
+ assert p.request(req % self.server.port).status_code == 400
def test_invalid_ports(self):
req = 'get:"http://localhost:999999"'
@@ -24,12 +25,12 @@ class TestFuzzy(tservers.HTTPProxTest):
def test_invalid_ipv6_url(self):
req = 'get:"http://localhost:%s":i13,"["'
p = self.pathoc()
- assert p.request(req%self.server.port).status_code == 400
+ assert p.request(req % self.server.port).status_code == 400
def test_invalid_upstream(self):
req = r"get:'http://localhost:%s/p/200:i10,\x27+\x27'"
p = self.pathoc()
- assert p.request(req%self.server.port).status_code == 502
+ assert p.request(req % self.server.port).status_code == 502
def test_upstream_disconnect(self):
req = r'200:d0'
diff --git a/test/test_platform_pf.py b/test/test_platform_pf.py
index 2c4870f9..3250b035 100644
--- a/test/test_platform_pf.py
+++ b/test/test_platform_pf.py
@@ -1,4 +1,5 @@
-import tutils, sys
+import tutils
+import sys
from libmproxy.platform import pf
@@ -6,10 +7,20 @@ class TestLookup:
def test_simple(self):
if sys.platform == "freebsd10":
p = tutils.test_data.path("data/pf02")
- d = open(p,"rb").read()
+ d = open(p, "rb").read()
else:
p = tutils.test_data.path("data/pf01")
- d = open(p,"rb").read()
+ d = open(p, "rb").read()
assert pf.lookup("192.168.1.111", 40000, d) == ("5.5.5.5", 80)
- tutils.raises("Could not resolve original destination", pf.lookup, "192.168.1.112", 40000, d)
- tutils.raises("Could not resolve original destination", pf.lookup, "192.168.1.111", 40001, d)
+ tutils.raises(
+ "Could not resolve original destination",
+ pf.lookup,
+ "192.168.1.112",
+ 40000,
+ d)
+ tutils.raises(
+ "Could not resolve original destination",
+ pf.lookup,
+ "192.168.1.111",
+ 40001,
+ d)
diff --git a/test/test_protocol_http.py b/test/test_protocol_http.py
index c39f9abb..884a528e 100644
--- a/test/test_protocol_http.py
+++ b/test/test_protocol_http.py
@@ -61,7 +61,8 @@ class TestHTTPRequest:
assert "Host" in r.headers
def test_expect_header(self):
- s = StringIO("GET / HTTP/1.1\r\nContent-Length: 3\r\nExpect: 100-continue\r\n\r\nfoobar")
+ s = StringIO(
+ "GET / HTTP/1.1\r\nContent-Length: 3\r\nExpect: 100-continue\r\n\r\nfoobar")
w = StringIO()
r = HTTPRequest.from_stream(s, wfile=w)
assert w.getvalue() == "HTTP/1.1 100 Continue\r\n\r\n"
@@ -84,7 +85,8 @@ class TestHTTPRequest:
tutils.raises("Bad HTTP request line", HTTPRequest.from_stream, s)
s = StringIO("GET http://address:22/ HTTP/1.1")
r = HTTPRequest.from_stream(s)
- assert r.assemble() == "GET http://address:22/ HTTP/1.1\r\nHost: address:22\r\nContent-Length: 0\r\n\r\n"
+ assert r.assemble(
+ ) == "GET http://address:22/ HTTP/1.1\r\nHost: address:22\r\nContent-Length: 0\r\n\r\n"
def test_http_options_relative_form_in(self):
"""
@@ -105,10 +107,10 @@ class TestHTTPRequest:
r.host = 'address'
r.port = 80
r.scheme = "http"
- assert r.assemble() == ("OPTIONS http://address:80/secret/resource HTTP/1.1\r\n"
- "Host: address\r\n"
- "Content-Length: 0\r\n\r\n")
-
+ assert r.assemble() == (
+ "OPTIONS http://address:80/secret/resource HTTP/1.1\r\n"
+ "Host: address\r\n"
+ "Content-Length: 0\r\n\r\n")
def test_assemble_unknown_form(self):
r = tutils.treq()
@@ -257,7 +259,8 @@ class TestHTTPResponse:
def test_get_cookies_with_parameters(self):
h = odict.ODictCaseless()
- h["Set-Cookie"] = ["cookiename=cookievalue;domain=example.com;expires=Wed Oct 21 16:29:41 2015;path=/; HttpOnly"]
+ h["Set-Cookie"] = [
+ "cookiename=cookievalue;domain=example.com;expires=Wed Oct 21 16:29:41 2015;path=/; HttpOnly"]
resp = tutils.tresp()
resp.headers = h
result = resp.get_cookies()
diff --git a/test/test_proxy.py b/test/test_proxy.py
index 641b4f47..a618ae6c 100644
--- a/test/test_proxy.py
+++ b/test/test_proxy.py
@@ -78,7 +78,6 @@ class TestProcessProxyOptions:
def test_no_transparent(self):
self.assert_err("transparent mode not supported", "-T")
-
@mock.patch("libmproxy.platform.resolver")
def test_modes(self, _):
self.assert_noerr("-R", "http://localhost")
@@ -96,28 +95,42 @@ class TestProcessProxyOptions:
def test_client_certs(self):
with tutils.tmpdir() as cadir:
self.assert_noerr("--client-certs", cadir)
- self.assert_err("directory does not exist", "--client-certs", "nonexistent")
+ self.assert_err(
+ "directory does not exist",
+ "--client-certs",
+ "nonexistent")
def test_certs(self):
with tutils.tmpdir() as cadir:
- self.assert_noerr("--cert", tutils.test_data.path("data/testkey.pem"))
+ self.assert_noerr(
+ "--cert",
+ tutils.test_data.path("data/testkey.pem"))
self.assert_err("does not exist", "--cert", "nonexistent")
def test_auth(self):
p = self.assert_noerr("--nonanonymous")
assert p.authenticator
- p = self.assert_noerr("--htpasswd", tutils.test_data.path("data/htpasswd"))
+ p = self.assert_noerr(
+ "--htpasswd",
+ tutils.test_data.path("data/htpasswd"))
assert p.authenticator
- self.assert_err("malformed htpasswd file", "--htpasswd", tutils.test_data.path("data/htpasswd.invalid"))
+ self.assert_err(
+ "malformed htpasswd file",
+ "--htpasswd",
+ tutils.test_data.path("data/htpasswd.invalid"))
p = self.assert_noerr("--singleuser", "test:test")
assert p.authenticator
- self.assert_err("invalid single-user specification", "--singleuser", "test")
+ self.assert_err(
+ "invalid single-user specification",
+ "--singleuser",
+ "test")
class TestProxyServer:
- @tutils.SkipWindows # binding to 0.0.0.0:1 works without special permissions on Windows
+ # binding to 0.0.0.0:1 works without special permissions on Windows
+ @tutils.SkipWindows
def test_err(self):
conf = ProxyConfig(
port=1
@@ -142,6 +155,12 @@ class TestConnectionHandler:
def test_fatal_error(self):
config = mock.Mock()
config.mode.get_upstream_server.side_effect = RuntimeError
- c = ConnectionHandler(config, mock.MagicMock(), ("127.0.0.1", 8080), None, mock.MagicMock())
+ c = ConnectionHandler(
+ config,
+ mock.MagicMock(),
+ ("127.0.0.1",
+ 8080),
+ None,
+ mock.MagicMock())
with tutils.capture_stderr(c.handle) as output:
assert "mitmproxy has crashed" in output
diff --git a/test/test_script.py b/test/test_script.py
index aed7def1..0a063740 100644
--- a/test/test_script.py
+++ b/test/test_script.py
@@ -11,7 +11,7 @@ class TestScript:
s = flow.State()
fm = flow.FlowMaster(None, s)
sp = tutils.test_data.path("scripts/a.py")
- p = script.Script("%s --var 40"%sp, fm)
+ p = script.Script("%s --var 40" % sp, fm)
assert "here" in p.ns
assert p.run("here") == (True, 41)
@@ -79,7 +79,9 @@ class TestScript:
def test_concurrent2(self):
s = flow.State()
fm = flow.FlowMaster(None, s)
- s = script.Script(tutils.test_data.path("scripts/concurrent_decorator.py"), fm)
+ s = script.Script(
+ tutils.test_data.path("scripts/concurrent_decorator.py"),
+ fm)
s.load()
m = mock.Mock()
@@ -110,8 +112,9 @@ class TestScript:
fm = flow.FlowMaster(None, s)
tutils.raises(
"decorator not supported for this method",
- script.Script, tutils.test_data.path("scripts/concurrent_decorator_err.py"), fm
- )
+ script.Script,
+ tutils.test_data.path("scripts/concurrent_decorator_err.py"),
+ fm)
def test_command_parsing():
@@ -120,5 +123,3 @@ def test_command_parsing():
absfilepath = os.path.normcase(tutils.test_data.path("scripts/a.py"))
s = script.Script(absfilepath, fm)
assert os.path.isfile(s.argv[0])
-
-
diff --git a/test/test_server.py b/test/test_server.py
index 7f93c729..2ab48422 100644
--- a/test/test_server.py
+++ b/test/test_server.py
@@ -1,10 +1,12 @@
-import socket, time
+import socket
+import time
from libmproxy.proxy.config import HostMatcher
import libpathod
from netlib import tcp, http_auth, http
from libpathod import pathoc, pathod
from netlib.certutils import SSLCert
-import tutils, tservers
+import tutils
+import tservers
from libmproxy.protocol import KILL, Error
from libmproxy.protocol.http import CONTENT_MISSING
@@ -16,9 +18,10 @@ from libmproxy.protocol.http import CONTENT_MISSING
for a 200 response.
"""
+
class CommonMixin:
def test_large(self):
- assert len(self.pathod("200:b@50k").content) == 1024*50
+ assert len(self.pathod("200:b@50k").content) == 1024 * 50
@staticmethod
def wait_until_not_live(flow):
@@ -56,7 +59,8 @@ class CommonMixin:
# Port error
l.request.port = 1
# In upstream mode, we get a 502 response from the upstream proxy server.
- # In upstream mode with ssl, the replay will fail as we cannot establish SSL with the upstream proxy.
+ # In upstream mode with ssl, the replay will fail as we cannot establish
+ # SSL with the upstream proxy.
rt = self.master.replay_request(l, block=True)
assert not rt
if isinstance(self, tservers.HTTPUpstreamProxTest) and not self.ssl:
@@ -68,7 +72,9 @@ class CommonMixin:
f = self.pathod("304")
assert f.status_code == 304
- l = self.master.state.view[-1] # In Upstream mode with SSL, we may already have a previous CONNECT request.
+ # In Upstream mode with SSL, we may already have a previous CONNECT
+ # request.
+ l = self.master.state.view[-1]
assert l.client_conn.address
assert "host" in l.request.headers
assert l.response.code == 304
@@ -90,11 +96,13 @@ class CommonMixin:
log = self.server.last_log()
assert log["request"]["sni"] == "testserver.com"
+
class TcpMixin:
def _ignore_on(self):
assert not hasattr(self, "_ignore_backup")
self._ignore_backup = self.config.check_ignore
- self.config.check_ignore = HostMatcher([".+:%s" % self.server.port] + self.config.check_ignore.patterns)
+ self.config.check_ignore = HostMatcher(
+ [".+:%s" % self.server.port] + self.config.check_ignore.patterns)
def _ignore_off(self):
assert hasattr(self, "_ignore_backup")
@@ -125,22 +133,26 @@ class TcpMixin:
# Test Non-HTTP traffic
spec = "200:i0,@100:d0" # this results in just 100 random bytes
- assert self.pathod(spec).status_code == 502 # mitmproxy responds with bad gateway
+ # mitmproxy responds with bad gateway
+ assert self.pathod(spec).status_code == 502
self._ignore_on()
- tutils.raises("invalid server response", self.pathod, spec) # pathoc tries to parse answer as HTTP
+ tutils.raises(
+ "invalid server response",
+ self.pathod,
+ spec) # pathoc tries to parse answer as HTTP
self._ignore_off()
def _tcpproxy_on(self):
assert not hasattr(self, "_tcpproxy_backup")
self._tcpproxy_backup = self.config.check_tcp
- self.config.check_tcp = HostMatcher([".+:%s" % self.server.port] + self.config.check_tcp.patterns)
+ self.config.check_tcp = HostMatcher(
+ [".+:%s" % self.server.port] + self.config.check_tcp.patterns)
def _tcpproxy_off(self):
assert hasattr(self, "_tcpproxy_backup")
self.config.check_ignore = self._tcpproxy_backup
del self._tcpproxy_backup
-
def test_tcp(self):
spec = '304:h"Alternate-Protocol"="mitmproxy-will-remove-this"'
n = self.pathod(spec)
@@ -165,6 +177,7 @@ class TcpMixin:
# Make sure that TCP messages are in the event log.
assert any("mitmproxy-will-remove-this" in m for m in self.master.log)
+
class AppMixin:
def test_app(self):
ret = self.app("/")
@@ -188,30 +201,30 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
def test_upstream_ssl_error(self):
p = self.pathoc()
- ret = p.request("get:'https://localhost:%s/'"%self.server.port)
+ ret = p.request("get:'https://localhost:%s/'" % self.server.port)
assert ret.status_code == 400
def test_connection_close(self):
# Add a body, so we have a content-length header, which combined with
# HTTP1.1 means the connection is kept alive.
- response = '%s/p/200:b@1'%self.server.urlbase
+ response = '%s/p/200:b@1' % self.server.urlbase
# Lets sanity check that the connection does indeed stay open by
# issuing two requests over the same connection
p = self.pathoc()
- assert p.request("get:'%s'"%response)
- assert p.request("get:'%s'"%response)
+ assert p.request("get:'%s'" % response)
+ assert p.request("get:'%s'" % response)
# Now check that the connection is closed as the client specifies
p = self.pathoc()
- assert p.request("get:'%s':h'Connection'='close'"%response)
+ assert p.request("get:'%s':h'Connection'='close'" % response)
# There's a race here, which means we can get any of a number of errors.
# Rather than introduce yet another sleep into the test suite, we just
# relax the Exception specification.
- tutils.raises(Exception, p.request, "get:'%s'"%response)
+ tutils.raises(Exception, p.request, "get:'%s'" % response)
def test_reconnect(self):
- req = "get:'%s/p/200:b@1:da'"%self.server.urlbase
+ req = "get:'%s/p/200:b@1:da'" % self.server.urlbase
p = self.pathoc()
assert p.request(req)
# Server has disconnected. Mitmproxy should detect this, and reconnect.
@@ -225,8 +238,8 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
return True
req = "get:'%s/p/200:b@1'"
p = self.pathoc()
- assert p.request(req%self.server.urlbase)
- assert p.request(req%self.server2.urlbase)
+ assert p.request(req % self.server.urlbase)
+ assert p.request(req % self.server2.urlbase)
assert switched(self.proxy.log)
def test_get_connection_err(self):
@@ -237,7 +250,7 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
def test_blank_leading_line(self):
p = self.pathoc()
req = "get:'%s/p/201':i0,'\r\n'"
- assert p.request(req%self.server.urlbase).status_code == 201
+ assert p.request(req % self.server.urlbase).status_code == 201
def test_invalid_headers(self):
p = self.pathoc()
@@ -251,7 +264,9 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.connect(("127.0.0.1", self.proxy.port))
spec = '301:h"Transfer-Encoding"="chunked":r:b"0\\r\\n\\r\\n"'
- connection.send("GET http://localhost:%d/p/%s HTTP/1.1\r\n"%(self.server.port, spec))
+ connection.send(
+ "GET http://localhost:%d/p/%s HTTP/1.1\r\n" %
+ (self.server.port, spec))
connection.send("\r\n")
resp = connection.recv(50000)
connection.close()
@@ -270,13 +285,20 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
self.master.set_stream_large_bodies(None)
def test_stream_modify(self):
- self.master.load_script(tutils.test_data.path("scripts/stream_modify.py"))
+ self.master.load_script(
+ tutils.test_data.path("scripts/stream_modify.py"))
d = self.pathod('200:b"foo"')
assert d.content == "bar"
self.master.unload_scripts()
+
class TestHTTPAuth(tservers.HTTPProxTest):
- authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm")
+ authenticator = http_auth.BasicProxyAuth(
+ http_auth.PassManSingleUser(
+ "test",
+ "test"),
+ "realm")
+
def test_auth(self):
assert self.pathod("202").status_code == 407
p = self.pathoc()
@@ -284,7 +306,7 @@ class TestHTTPAuth(tservers.HTTPProxTest):
get
'http://localhost:%s/p/202'
h'%s'='%s'
- """%(
+ """ % (
self.server.port,
http_auth.BasicProxyAuth.AUTH_HEADER,
http.assemble_http_basic_auth("basic", "test", "test")
@@ -294,6 +316,7 @@ class TestHTTPAuth(tservers.HTTPProxTest):
class TestHTTPConnectSSLError(tservers.HTTPProxTest):
certfile = True
+
def test_go(self):
self.config.ssl_ports.append(self.proxy.port)
p = self.pathoc_raw()
@@ -306,6 +329,7 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin):
ssl = True
ssloptions = pathod.SSLOptions(request_client_cert=True)
clientcerts = True
+
def test_clientcert(self):
f = self.pathod("304")
assert f.status_code == 304
@@ -319,6 +343,7 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin):
class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin):
ssl = True
certfile = True
+
def test_certfile(self):
assert self.pathod("304")
@@ -328,11 +353,12 @@ class TestHTTPSNoCommonName(tservers.HTTPProxTest):
Test what happens if we get a cert without common name back.
"""
ssl = True
- ssloptions=pathod.SSLOptions(
- certs = [
- ("*", tutils.test_data.path("data/no_common_name.pem"))
- ]
- )
+ ssloptions = pathod.SSLOptions(
+ certs = [
+ ("*", tutils.test_data.path("data/no_common_name.pem"))
+ ]
+ )
+
def test_http(self):
f = self.pathod("202")
assert f.sslinfo.certchain[0].get_subject().CN == "127.0.0.1"
@@ -373,7 +399,6 @@ class TestHttps2Http(tservers.ReverseProxTest):
assert p.request("get:'/p/200'").status_code == 400
-
class TestTransparent(tservers.TransparentProxTest, CommonMixin, TcpMixin):
ssl = False
@@ -413,15 +438,19 @@ class TestProxy(tservers.HTTPProxTest):
connection.connect(("127.0.0.1", self.proxy.port))
# call pathod server, wait a second to complete the request
- connection.send("GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n"%self.server.port)
+ connection.send(
+ "GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n" %
+ self.server.port)
time.sleep(1)
connection.send("\r\n")
connection.recv(50000)
connection.close()
- request, response = self.master.state.view[0].request, self.master.state.view[0].response
+ request, response = self.master.state.view[
+ 0].request, self.master.state.view[0].response
assert response.code == 304 # sanity test for our low level request
- assert 0.95 < (request.timestamp_end - request.timestamp_start) < 1.2 #time.sleep might be a little bit shorter than a second
+ # time.sleep might be a little bit shorter than a second
+ assert 0.95 < (request.timestamp_end - request.timestamp_start) < 1.2
def test_request_timestamps_not_affected_by_client_time(self):
# test that don't include user wait time in request's timestamps
@@ -441,10 +470,14 @@ class TestProxy(tservers.HTTPProxTest):
# tests that the client_conn a tcp connection has a tcp_setup_timestamp
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.connect(("localhost", self.proxy.port))
- connection.send("GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n"%self.server.port)
+ connection.send(
+ "GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n" %
+ self.server.port)
connection.send("\r\n")
connection.recv(5000)
- connection.send("GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n"%self.server.port)
+ connection.send(
+ "GET http://localhost:%d/p/304:b@1k HTTP/1.1\r\n" %
+ self.server.port)
connection.send("\r\n")
connection.recv(5000)
connection.close()
@@ -462,8 +495,10 @@ class TestProxy(tservers.HTTPProxTest):
f = self.master.state.view[0]
assert f.server_conn.address == ("127.0.0.1", self.server.port)
+
class TestProxySSL(tservers.HTTPProxTest):
- ssl=True
+ ssl = True
+
def test_request_ssl_setup_timestamp_presence(self):
# tests that the ssl timestamp is present when ssl is used
f = self.pathod("304:b@10k")
@@ -479,16 +514,24 @@ class MasterRedirectRequest(tservers.TestMaster):
request = f.request
if request.path == "/p/201":
addr = f.live.c.server_conn.address
- assert f.live.change_server(("127.0.0.1", self.redirect_port), ssl=False)
- assert not f.live.change_server(("127.0.0.1", self.redirect_port), ssl=False)
- tutils.raises("SSL handshake error", f.live.change_server, ("127.0.0.1", self.redirect_port), ssl=True)
+ assert f.live.change_server(
+ ("127.0.0.1", self.redirect_port), ssl=False)
+ assert not f.live.change_server(
+ ("127.0.0.1", self.redirect_port), ssl=False)
+ tutils.raises(
+ "SSL handshake error",
+ f.live.change_server,
+ ("127.0.0.1",
+ self.redirect_port),
+ ssl=True)
assert f.live.change_server(addr, ssl=False)
request.url = "http://127.0.0.1:%s/p/201" % self.redirect_port
tservers.TestMaster.handle_request(self, f)
def handle_response(self, f):
f.response.content = str(f.client_conn.address.port)
- f.response.headers["server-conn-id"] = [str(f.server_conn.source_address.port)]
+ f.response.headers[
+ "server-conn-id"] = [str(f.server_conn.source_address.port)]
tservers.TestMaster.handle_response(self, f)
@@ -502,37 +545,41 @@ class TestRedirectRequest(tservers.HTTPProxTest):
self.server.clear_log()
self.server2.clear_log()
- r1 = p.request("get:'%s/p/200'"%self.server.urlbase)
+ r1 = p.request("get:'%s/p/200'" % self.server.urlbase)
assert r1.status_code == 200
assert self.server.last_log()
assert not self.server2.last_log()
self.server.clear_log()
self.server2.clear_log()
- r2 = p.request("get:'%s/p/201'"%self.server.urlbase)
+ r2 = p.request("get:'%s/p/201'" % self.server.urlbase)
assert r2.status_code == 201
assert not self.server.last_log()
assert self.server2.last_log()
self.server.clear_log()
self.server2.clear_log()
- r3 = p.request("get:'%s/p/202'"%self.server.urlbase)
+ r3 = p.request("get:'%s/p/202'" % self.server.urlbase)
assert r3.status_code == 202
assert self.server.last_log()
assert not self.server2.last_log()
assert r1.content == r2.content == r3.content
- assert r1.headers.get_first("server-conn-id") == r3.headers.get_first("server-conn-id")
+ assert r1.headers.get_first(
+ "server-conn-id") == r3.headers.get_first("server-conn-id")
# Make sure that we actually use the same connection in this test case
+
class MasterStreamRequest(tservers.TestMaster):
"""
Enables the stream flag on the flow for all requests
"""
+
def handle_responseheaders(self, f):
f.response.stream = True
f.reply()
+
class TestStreamRequest(tservers.HTTPProxTest):
masterclass = MasterStreamRequest
@@ -541,7 +588,7 @@ class TestStreamRequest(tservers.HTTPProxTest):
# a request with 100k of data but without content-length
self.server.clear_log()
- r1 = p.request("get:'%s/p/200:r:b@100k:d102400'"%self.server.urlbase)
+ r1 = p.request("get:'%s/p/200:r:b@100k:d102400'" % self.server.urlbase)
assert r1.status_code == 200
assert len(r1.content) > 100000
assert self.server.last_log()
@@ -551,13 +598,13 @@ class TestStreamRequest(tservers.HTTPProxTest):
# simple request with streaming turned on
self.server.clear_log()
- r1 = p.request("get:'%s/p/200'"%self.server.urlbase)
+ r1 = p.request("get:'%s/p/200'" % self.server.urlbase)
assert r1.status_code == 200
assert self.server.last_log()
# now send back 100k of data, streamed but not chunked
self.server.clear_log()
- r1 = p.request("get:'%s/p/200:b@100k'"%self.server.urlbase)
+ r1 = p.request("get:'%s/p/200:b@100k'" % self.server.urlbase)
assert r1.status_code == 200
assert self.server.last_log()
@@ -567,15 +614,27 @@ class TestStreamRequest(tservers.HTTPProxTest):
connection.connect(("127.0.0.1", self.proxy.port))
fconn = connection.makefile()
spec = '200:h"Transfer-Encoding"="chunked":r:b"4\\r\\nthis\\r\\n7\\r\\nisatest\\r\\n0\\r\\n\\r\\n"'
- connection.send("GET %s/p/%s HTTP/1.1\r\n"%(self.server.urlbase, spec))
+ connection.send(
+ "GET %s/p/%s HTTP/1.1\r\n" %
+ (self.server.urlbase, spec))
connection.send("\r\n")
- httpversion, code, msg, headers, content = http.read_response(fconn, "GET", None, include_body=False)
+ httpversion, code, msg, headers, content = http.read_response(
+ fconn, "GET", None, include_body=False)
assert headers["Transfer-Encoding"][0] == 'chunked'
assert code == 200
- chunks = list(content for _, content, _ in http.read_http_body_chunked(fconn, headers, None, "GET", 200, False))
+ chunks = list(
+ content for _,
+ content,
+ _ in http.read_http_body_chunked(
+ fconn,
+ headers,
+ None,
+ "GET",
+ 200,
+ False))
assert chunks == ["this", "isatest", ""]
connection.close()
@@ -589,6 +648,7 @@ class MasterFakeResponse(tservers.TestMaster):
class TestFakeResponse(tservers.HTTPProxTest):
masterclass = MasterFakeResponse
+
def test_fake(self):
f = self.pathod("200")
assert "header_response" in f.headers.keys()
@@ -601,6 +661,7 @@ class MasterKillRequest(tservers.TestMaster):
class TestKillRequest(tservers.HTTPProxTest):
masterclass = MasterKillRequest
+
def test_kill(self):
tutils.raises("server disconnect", self.pathod, "200")
# Nothing should have hit the server
@@ -614,6 +675,7 @@ class MasterKillResponse(tservers.TestMaster):
class TestKillResponse(tservers.HTTPProxTest):
masterclass = MasterKillResponse
+
def test_kill(self):
tutils.raises("server disconnect", self.pathod, "200")
# The server should have seen a request
@@ -627,6 +689,7 @@ class EResolver(tservers.TResolver):
class TestTransparentResolveError(tservers.TransparentProxTest):
resolver = EResolver
+
def test_resolve_error(self):
assert self.pathod("304").status_code == 502
@@ -640,6 +703,7 @@ class MasterIncomplete(tservers.TestMaster):
class TestIncompleteResponse(tservers.HTTPProxTest):
masterclass = MasterIncomplete
+
def test_incomplete(self):
assert self.pathod("200").status_code == 502
@@ -656,10 +720,16 @@ class TestUpstreamProxy(tservers.HTTPUpstreamProxTest, CommonMixin, AppMixin):
ssl = False
def test_order(self):
- self.proxy.tmaster.replacehooks.add("~q", "foo", "bar") # replace in request
+ self.proxy.tmaster.replacehooks.add(
+ "~q",
+ "foo",
+ "bar") # replace in request
self.chain[0].tmaster.replacehooks.add("~q", "bar", "baz")
self.chain[1].tmaster.replacehooks.add("~q", "foo", "oh noes!")
- self.chain[0].tmaster.replacehooks.add("~s", "baz", "ORLY") # replace in response
+ self.chain[0].tmaster.replacehooks.add(
+ "~s",
+ "baz",
+ "ORLY") # replace in response
p = self.pathoc()
req = p.request("get:'%s/p/418:b\"foo\"'" % self.server.urlbase)
@@ -667,7 +737,10 @@ class TestUpstreamProxy(tservers.HTTPUpstreamProxTest, CommonMixin, AppMixin):
assert req.status_code == 418
-class TestUpstreamProxySSL(tservers.HTTPUpstreamProxTest, CommonMixin, TcpMixin):
+class TestUpstreamProxySSL(
+ tservers.HTTPUpstreamProxTest,
+ CommonMixin,
+ TcpMixin):
ssl = True
def _host_pattern_on(self, attr):
@@ -677,7 +750,10 @@ class TestUpstreamProxySSL(tservers.HTTPUpstreamProxTest, CommonMixin, TcpMixin)
assert not hasattr(self, "_ignore_%s_backup" % attr)
backup = []
for proxy in self.chain:
- old_matcher = getattr(proxy.tmaster.server.config, "check_%s" % attr)
+ old_matcher = getattr(
+ proxy.tmaster.server.config,
+ "check_%s" %
+ attr)
backup.append(old_matcher)
setattr(
proxy.tmaster.server.config,
@@ -721,11 +797,14 @@ class TestUpstreamProxySSL(tservers.HTTPUpstreamProxTest, CommonMixin, TcpMixin)
assert req.content == "content"
assert req.status_code == 418
- assert self.proxy.tmaster.state.flow_count() == 2 # CONNECT from pathoc to chain[0],
- # request from pathoc to chain[0]
- assert self.chain[0].tmaster.state.flow_count() == 2 # CONNECT from proxy to chain[1],
- # request from proxy to chain[1]
- assert self.chain[1].tmaster.state.flow_count() == 1 # request from chain[0] (regular proxy doesn't store CONNECTs)
+ # CONNECT from pathoc to chain[0],
+ assert self.proxy.tmaster.state.flow_count() == 2
+ # request from pathoc to chain[0]
+ # CONNECT from proxy to chain[1],
+ assert self.chain[0].tmaster.state.flow_count() == 2
+ # request from proxy to chain[1]
+ # request from chain[0] (regular proxy doesn't store CONNECTs)
+ assert self.chain[1].tmaster.state.flow_count() == 1
def test_closing_connect_response(self):
"""
@@ -755,6 +834,7 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest):
def kill_requests(master, attr, exclude):
k = [0] # variable scope workaround: put into array
_func = getattr(master, attr)
+
def handler(f):
k[0] += 1
if not (k[0] in exclude):
@@ -766,9 +846,9 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest):
kill_requests(self.chain[1].tmaster, "handle_request",
exclude=[
- # fail first request
+ # fail first request
2, # allow second request
- ])
+ ])
kill_requests(self.chain[0].tmaster, "handle_request",
exclude=[
@@ -776,16 +856,18 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest):
# fail first request
3, # reCONNECT
4, # request
- ])
+ ])
p = self.pathoc()
req = p.request("get:'/p/418:b\"content\"'")
assert self.proxy.tmaster.state.flow_count() == 2 # CONNECT and request
- assert self.chain[0].tmaster.state.flow_count() == 4 # CONNECT, failing request,
- # reCONNECT, request
- assert self.chain[1].tmaster.state.flow_count() == 2 # failing request, request
- # (doesn't store (repeated) CONNECTs from chain[0]
- # as it is a regular proxy)
+ # CONNECT, failing request,
+ assert self.chain[0].tmaster.state.flow_count() == 4
+ # reCONNECT, request
+ # failing request, request
+ assert self.chain[1].tmaster.state.flow_count() == 2
+ # (doesn't store (repeated) CONNECTs from chain[0]
+ # as it is a regular proxy)
assert req.content == "content"
assert req.status_code == 418
@@ -795,18 +877,26 @@ class TestProxyChainingSSLReconnect(tservers.HTTPUpstreamProxTest):
assert self.proxy.tmaster.state.flows[0].request.form_in == "authority"
assert self.proxy.tmaster.state.flows[1].request.form_in == "relative"
- assert self.chain[0].tmaster.state.flows[0].request.form_in == "authority"
- assert self.chain[0].tmaster.state.flows[1].request.form_in == "relative"
- assert self.chain[0].tmaster.state.flows[2].request.form_in == "authority"
- assert self.chain[0].tmaster.state.flows[3].request.form_in == "relative"
+ assert self.chain[0].tmaster.state.flows[
+ 0].request.form_in == "authority"
+ assert self.chain[0].tmaster.state.flows[
+ 1].request.form_in == "relative"
+ assert self.chain[0].tmaster.state.flows[
+ 2].request.form_in == "authority"
+ assert self.chain[0].tmaster.state.flows[
+ 3].request.form_in == "relative"
- assert self.chain[1].tmaster.state.flows[0].request.form_in == "relative"
- assert self.chain[1].tmaster.state.flows[1].request.form_in == "relative"
+ assert self.chain[1].tmaster.state.flows[
+ 0].request.form_in == "relative"
+ assert self.chain[1].tmaster.state.flows[
+ 1].request.form_in == "relative"
req = p.request("get:'/p/418:b\"content2\"'")
assert req.status_code == 502
assert self.proxy.tmaster.state.flow_count() == 3 # + new request
- assert self.chain[0].tmaster.state.flow_count() == 6 # + new request, repeated CONNECT from chain[1]
- # (both terminated)
- assert self.chain[1].tmaster.state.flow_count() == 2 # nothing happened here
+ # + new request, repeated CONNECT from chain[1]
+ assert self.chain[0].tmaster.state.flow_count() == 6
+ # (both terminated)
+ # nothing happened here
+ assert self.chain[1].tmaster.state.flow_count() == 2
diff --git a/test/test_utils.py b/test/test_utils.py
index 6b9262a0..0c514f5d 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -48,9 +48,11 @@ def test_urldecode():
s = "one=two&three=four"
assert len(utils.urldecode(s)) == 2
+
def test_multipartdecode():
boundary = 'somefancyboundary'
- headers = odict.ODict([('content-type', ('multipart/form-data; boundary=%s' % boundary))])
+ headers = odict.ODict(
+ [('content-type', ('multipart/form-data; boundary=%s' % boundary))])
content = "--{0}\n" \
"Content-Disposition: form-data; name=\"field1\"\n\n" \
"value1\n" \
@@ -65,6 +67,7 @@ def test_multipartdecode():
assert form[0] == ('field1', 'value1')
assert form[1] == ('field2', 'value2')
+
def test_pretty_duration():
assert utils.pretty_duration(0.00001) == "0ms"
assert utils.pretty_duration(0.0001) == "0ms"
@@ -79,10 +82,13 @@ def test_pretty_duration():
assert utils.pretty_duration(1.123) == "1.12s"
assert utils.pretty_duration(0.123) == "123ms"
+
def test_LRUCache():
cache = utils.LRUCache(2)
+
class Foo:
ran = False
+
def gen(self, x):
self.ran = True
return x
diff --git a/test/tools/bench.py b/test/tools/bench.py
index 1028f61d..8127d083 100644
--- a/test/tools/bench.py
+++ b/test/tools/bench.py
@@ -1,5 +1,6 @@
from __future__ import print_function
-import requests, time
+import requests
+import time
n = 100
url = "http://192.168.1.1/"
@@ -7,18 +8,17 @@ proxy = "http://192.168.1.115:8080/"
start = time.time()
for _ in range(n):
- requests.get(url, allow_redirects=False, proxies=dict(http=proxy))
- print(".", end="")
-t_mitmproxy = time.time()-start
+ requests.get(url, allow_redirects=False, proxies=dict(http=proxy))
+ print(".", end="")
+t_mitmproxy = time.time() - start
print("\r\nTotal time with mitmproxy: {}".format(t_mitmproxy))
-
start = time.time()
for _ in range(n):
- requests.get(url, allow_redirects=False)
- print(".", end="")
-t_without = time.time()-start
+ requests.get(url, allow_redirects=False)
+ print(".", end="")
+t_without = time.time() - start
-print("\r\nTotal time without mitmproxy: {}".format(t_without)) \ No newline at end of file
+print("\r\nTotal time without mitmproxy: {}".format(t_without))
diff --git a/test/tools/benchtool.py b/test/tools/benchtool.py
index 5cfcba30..ae4636a7 100644
--- a/test/tools/benchtool.py
+++ b/test/tools/benchtool.py
@@ -2,7 +2,7 @@
# yappi (https://code.google.com/p/yappi/)
#
# Requirements:
-# - Apache Bench "ab" binary
+# - Apache Bench "ab" binary
# - pip install click yappi
from libmproxy.main import mitmdump
@@ -13,14 +13,17 @@ import time
import yappi
import click
+
class ApacheBenchThread(Thread):
- def __init__(self, concurrency):
- self.concurrency = concurrency
- super(ApacheBenchThread, self).__init__()
+ def __init__(self, concurrency):
+ self.concurrency = concurrency
+ super(ApacheBenchThread, self).__init__()
+
+ def run(self):
+ time.sleep(2)
+ system(
+ "ab -n 1024 -c {} -X 127.0.0.1:8080 http://example.com/".format(self.concurrency))
- def run(self):
- time.sleep(2)
- system("ab -n 1024 -c {} -X 127.0.0.1:8080 http://example.com/".format(self.concurrency))
@click.command()
@click.option('--profiler', default="none", type=click.Choice(['none', 'yappi']))
@@ -28,24 +31,24 @@ class ApacheBenchThread(Thread):
@click.option('--concurrency', default=1, type=click.INT)
def main(profiler, clock_type, concurrency):
- outfile = "callgrind.mitmdump-{}-c{}".format(clock_type, concurrency)
- a = ApacheBenchThread(concurrency)
- a.start()
-
- if profiler == "yappi":
- yappi.set_clock_type(clock_type)
- yappi.start(builtins=True)
-
- print("Start mitmdump...")
- mitmdump(["-k","-q","-S", "1024example"])
- print("mitmdump stopped.")
-
- print("Save profile information...")
- if profiler == "yappi":
- yappi.stop()
- stats = yappi.get_func_stats()
- stats.save(outfile, type='callgrind')
- print("Done.")
+ outfile = "callgrind.mitmdump-{}-c{}".format(clock_type, concurrency)
+ a = ApacheBenchThread(concurrency)
+ a.start()
+
+ if profiler == "yappi":
+ yappi.set_clock_type(clock_type)
+ yappi.start(builtins=True)
+
+ print("Start mitmdump...")
+ mitmdump(["-k", "-q", "-S", "1024example"])
+ print("mitmdump stopped.")
+
+ print("Save profile information...")
+ if profiler == "yappi":
+ yappi.stop()
+ stats = yappi.get_func_stats()
+ stats.save(outfile, type='callgrind')
+ print("Done.")
if __name__ == '__main__':
- main() \ No newline at end of file
+ main()
diff --git a/test/tools/getcert b/test/tools/getcert
index 8fabefb7..3bd2bec8 100755
--- a/test/tools/getcert
+++ b/test/tools/getcert
@@ -1,7 +1,10 @@
#!/usr/bin/env python
import sys
sys.path.insert(0, "../..")
-import socket, tempfile, ssl, subprocess
+import socket
+import tempfile
+import ssl
+import subprocess
addr = socket.gethostbyname(sys.argv[1])
print ssl.get_server_certificate((addr, 443))
diff --git a/test/tools/passive_close.py b/test/tools/passive_close.py
index d0b36e7f..7199ea70 100644
--- a/test/tools/passive_close.py
+++ b/test/tools/passive_close.py
@@ -2,12 +2,14 @@ import SocketServer
from threading import Thread
from time import sleep
+
class service(SocketServer.BaseRequestHandler):
def handle(self):
data = 'dummy'
print "Client connected with ", self.client_address
while True:
- self.request.send("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 7\r\n\r\ncontent")
+ self.request.send(
+ "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 7\r\n\r\ncontent")
data = self.request.recv(1024)
if not len(data):
print "Connection closed by remote: ", self.client_address
@@ -17,5 +19,5 @@ class service(SocketServer.BaseRequestHandler):
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass
-server = ThreadedTCPServer(('',1520), service)
+server = ThreadedTCPServer(('', 1520), service)
server.serve_forever()
diff --git a/test/tservers.py b/test/tservers.py
index bcda0295..dc14fb37 100644
--- a/test/tservers.py
+++ b/test/tservers.py
@@ -1,23 +1,28 @@
import os.path
-import threading, Queue
-import shutil, tempfile
+import threading
+import Queue
+import shutil
+import tempfile
import flask
import mock
from libmproxy.proxy.config import ProxyConfig
from libmproxy.proxy.server import ProxyServer
from libmproxy.proxy.primitives import TransparentProxyMode
-import libpathod.test, libpathod.pathoc
+import libpathod.test
+import libpathod.pathoc
from libmproxy import flow, controller
from libmproxy.cmdline import APP_HOST, APP_PORT
import tutils
testapp = flask.Flask(__name__)
+
@testapp.route("/")
def hello():
return "testapp"
+
@testapp.route("/error")
def error():
raise ValueError("An exception...")
@@ -57,7 +62,8 @@ class ProxyThread(threading.Thread):
def __init__(self, tmaster):
threading.Thread.__init__(self)
self.tmaster = tmaster
- self.name = "ProxyThread (%s:%s)" % (tmaster.server.address.host, tmaster.server.address.port)
+ self.name = "ProxyThread (%s:%s)" % (
+ tmaster.server.address.host, tmaster.server.address.port)
controller.should_exit = False
@property
@@ -87,8 +93,12 @@ class ProxTestBase(object):
@classmethod
def setupAll(cls):
- cls.server = libpathod.test.Daemon(ssl=cls.ssl, ssloptions=cls.ssloptions)
- cls.server2 = libpathod.test.Daemon(ssl=cls.ssl, ssloptions=cls.ssloptions)
+ cls.server = libpathod.test.Daemon(
+ ssl=cls.ssl,
+ ssloptions=cls.ssloptions)
+ cls.server2 = libpathod.test.Daemon(
+ ssl=cls.ssl,
+ ssloptions=cls.ssloptions)
cls.config = ProxyConfig(**cls.get_proxy_config())
@@ -151,9 +161,9 @@ class HTTPProxTest(ProxTestBase):
p = self.pathoc(sni=sni)
spec = spec.encode("string_escape")
if self.ssl:
- q = "get:'/p/%s'"%spec
+ q = "get:'/p/%s'" % spec
else:
- q = "get:'%s/p/%s'"%(self.server.urlbase, spec)
+ q = "get:'%s/p/%s'" % (self.server.urlbase, spec)
return p.request(q)
def app(self, page):
@@ -162,10 +172,10 @@ class HTTPProxTest(ProxTestBase):
("127.0.0.1", self.proxy.port), True, fp=None
)
p.connect((APP_HOST, APP_PORT))
- return p.request("get:'%s'"%page)
+ return p.request("get:'%s'" % page)
else:
p = self.pathoc()
- return p.request("get:'http://%s%s'"%(APP_HOST, page))
+ return p.request("get:'http://%s%s'" % (APP_HOST, page))
class TResolver:
@@ -188,7 +198,10 @@ class TransparentProxTest(ProxTestBase):
ports = [cls.server.port, cls.server2.port]
else:
ports = []
- cls.config.mode = TransparentProxyMode(cls.resolver(cls.server.port), ports)
+ cls.config.mode = TransparentProxyMode(
+ cls.resolver(
+ cls.server.port),
+ ports)
@classmethod
def get_proxy_config(cls):
@@ -202,10 +215,10 @@ class TransparentProxTest(ProxTestBase):
"""
if self.ssl:
p = self.pathoc(sni=sni)
- q = "get:'/p/%s'"%spec
+ q = "get:'/p/%s'" % spec
else:
p = self.pathoc()
- q = "get:'/p/%s'"%spec
+ q = "get:'/p/%s'" % spec
return p.request(q)
def pathoc(self, sni=None):
@@ -221,6 +234,7 @@ class TransparentProxTest(ProxTestBase):
class ReverseProxTest(ProxTestBase):
ssl = None
+
@classmethod
def get_proxy_config(cls):
d = ProxTestBase.get_proxy_config()
@@ -249,10 +263,10 @@ class ReverseProxTest(ProxTestBase):
"""
if self.ssl:
p = self.pathoc(sni=sni)
- q = "get:'/p/%s'"%spec
+ q = "get:'/p/%s'" % spec
else:
p = self.pathoc()
- q = "get:'/p/%s'"%spec
+ q = "get:'/p/%s'" % spec
return p.request(q)
@@ -278,8 +292,8 @@ class ChainProxTest(ProxTestBase):
cls.chain.insert(0, proxy)
# Patch the orginal proxy to upstream mode
- cls.config = cls.proxy.tmaster.config = cls.proxy.tmaster.server.config = ProxyConfig(**cls.get_proxy_config())
-
+ cls.config = cls.proxy.tmaster.config = cls.proxy.tmaster.server.config = ProxyConfig(
+ **cls.get_proxy_config())
@classmethod
def teardownAll(cls):
@@ -303,5 +317,6 @@ class ChainProxTest(ProxTestBase):
)
return d
+
class HTTPUpstreamProxTest(ChainProxTest, HTTPProxTest):
pass
diff --git a/test/tutils.py b/test/tutils.py
index 499efc6e..aeaeb0de 100644
--- a/test/tutils.py
+++ b/test/tutils.py
@@ -1,5 +1,8 @@
from cStringIO import StringIO
-import os, shutil, tempfile, argparse
+import os
+import shutil
+import tempfile
+import argparse
from contextlib import contextmanager
import sys
from libmproxy import flow, utils, controller
@@ -14,8 +17,11 @@ from nose.plugins.skip import SkipTest
from mock import Mock
from time import time
+
def _SkipWindows():
raise SkipTest("Skipped on Windows.")
+
+
def SkipWindows(fn):
if os.name == "nt":
return _SkipWindows
@@ -83,10 +89,23 @@ def treq(content="content", scheme="http", host="address", port=22):
"""
headers = odict.ODictCaseless()
headers["header"] = ["qvalue"]
- req = http.HTTPRequest("relative", "GET", scheme, host, port, "/path", (1, 1), headers, content,
- None, None, None)
+ req = http.HTTPRequest(
+ "relative",
+ "GET",
+ scheme,
+ host,
+ port,
+ "/path",
+ (1,
+ 1),
+ headers,
+ content,
+ None,
+ None,
+ None)
return req
+
def treq_absolute(content="content"):
"""
@return: libmproxy.protocol.http.HTTPRequest
@@ -107,7 +126,15 @@ def tresp(content="message"):
headers = odict.ODictCaseless()
headers["header_response"] = ["svalue"]
- resp = http.HTTPResponse((1, 1), 200, "OK", headers, content, time(), time())
+ resp = http.HTTPResponse(
+ (1,
+ 1),
+ 200,
+ "OK",
+ headers,
+ content,
+ time(),
+ time())
return resp
@@ -118,10 +145,11 @@ def terr(content="error"):
err = Error(content)
return err
+
def tflowview(request_contents=None):
m = Mock()
cs = ConsoleState()
- if request_contents == None:
+ if request_contents is None:
flow = tflow()
else:
flow = tflow(req=treq(request_contents))
@@ -129,9 +157,11 @@ def tflowview(request_contents=None):
fv = FlowView(m, cs, flow)
return fv
+
def get_body_line(last_displayed_body, line_nb):
return last_displayed_body.contents()[line_nb + 2]
+
@contextmanager
def tmpdir(*args, **kwargs):
orig_workdir = os.getcwd()
@@ -149,6 +179,7 @@ class MockParser(argparse.ArgumentParser):
argparse.ArgumentParser sys.exits() by default.
Make it more testable by throwing an exception instead.
"""
+
def error(self, message):
raise Exception(message)
@@ -169,14 +200,14 @@ def raises(exc, obj, *args, **kwargs):
:kwargs Arguments to be passed to the callable.
"""
try:
- apply(obj, args, kwargs)
- except Exception, v:
+ obj(*args, **kwargs)
+ except Exception as v:
if isinstance(exc, basestring):
if exc.lower() in str(v).lower():
return
else:
raise AssertionError(
- "Expected %s, but caught %s"%(
+ "Expected %s, but caught %s" % (
repr(str(exc)), v
)
)
@@ -185,7 +216,7 @@ def raises(exc, obj, *args, **kwargs):
return
else:
raise AssertionError(
- "Expected %s, but caught %s %s"%(
+ "Expected %s, but caught %s %s" % (
exc.__name__, v.__class__.__name__, str(v)
)
)