From dedca540996f337f3965fb87531fd03d7e27e417 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 16 Feb 2016 20:34:14 +0100 Subject: rename pathod source directory --- pathod/libpathod/__init__.py | 0 pathod/libpathod/app.py | 179 ------- pathod/libpathod/language/__init__.py | 113 ---- pathod/libpathod/language/actions.py | 126 ----- pathod/libpathod/language/base.py | 576 --------------------- pathod/libpathod/language/exceptions.py | 22 - pathod/libpathod/language/generators.py | 86 --- pathod/libpathod/language/http.py | 381 -------------- pathod/libpathod/language/http2.py | 299 ----------- pathod/libpathod/language/message.py | 96 ---- pathod/libpathod/language/websockets.py | 241 --------- pathod/libpathod/language/writer.py | 67 --- pathod/libpathod/log.py | 83 --- pathod/libpathod/pathoc.py | 534 ------------------- pathod/libpathod/pathoc_cmdline.py | 226 -------- pathod/libpathod/pathod.py | 503 ------------------ pathod/libpathod/pathod_cmdline.py | 231 --------- pathod/libpathod/protocols/__init__.py | 1 - pathod/libpathod/protocols/http.py | 71 --- pathod/libpathod/protocols/http2.py | 20 - pathod/libpathod/protocols/websockets.py | 56 -- pathod/libpathod/static/bootstrap.min.css | 9 - pathod/libpathod/static/bootstrap.min.js | 6 - pathod/libpathod/static/jquery-1.7.2.min.js | 4 - pathod/libpathod/static/jquery.localscroll-min.js | 9 - pathod/libpathod/static/jquery.scrollTo-min.js | 11 - pathod/libpathod/static/pathod.css | 56 -- pathod/libpathod/static/start_quote.png | Bin 376 -> 0 bytes pathod/libpathod/static/syntax.css | 120 ----- pathod/libpathod/static/torture.png | Bin 108327 -> 0 bytes pathod/libpathod/templates/about.html | 22 - pathod/libpathod/templates/docframe.html | 26 - pathod/libpathod/templates/docs_lang.html | 196 ------- pathod/libpathod/templates/docs_lang_requests.html | 114 ---- .../libpathod/templates/docs_lang_responses.html | 88 ---- .../libpathod/templates/docs_lang_websockets.html | 115 ---- pathod/libpathod/templates/docs_libpathod.html | 23 - pathod/libpathod/templates/docs_pathoc.html | 211 -------- pathod/libpathod/templates/docs_pathod.html | 172 ------ pathod/libpathod/templates/docs_test.html | 50 -- pathod/libpathod/templates/download.html | 39 -- pathod/libpathod/templates/examples_context.html | 24 - pathod/libpathod/templates/examples_setup.html | 32 -- pathod/libpathod/templates/examples_setupall.html | 40 -- pathod/libpathod/templates/frame.html | 7 - pathod/libpathod/templates/index.html | 60 --- pathod/libpathod/templates/layout.html | 75 --- pathod/libpathod/templates/libpathod_pathoc.html | 8 - pathod/libpathod/templates/log.html | 31 -- pathod/libpathod/templates/onelog.html | 8 - pathod/libpathod/templates/request_preview.html | 44 -- .../libpathod/templates/request_previewform.html | 53 -- pathod/libpathod/templates/response_preview.html | 44 -- .../libpathod/templates/response_previewform.html | 87 ---- pathod/libpathod/test.py | 103 ---- pathod/libpathod/utils.py | 124 ----- pathod/libpathod/version.py | 3 - 57 files changed, 5925 deletions(-) delete mode 100644 pathod/libpathod/__init__.py delete mode 100644 pathod/libpathod/app.py delete mode 100644 pathod/libpathod/language/__init__.py delete mode 100644 pathod/libpathod/language/actions.py delete mode 100644 pathod/libpathod/language/base.py delete mode 100644 pathod/libpathod/language/exceptions.py delete mode 100644 pathod/libpathod/language/generators.py delete mode 100644 pathod/libpathod/language/http.py delete mode 100644 pathod/libpathod/language/http2.py delete mode 100644 pathod/libpathod/language/message.py delete mode 100644 pathod/libpathod/language/websockets.py delete mode 100644 pathod/libpathod/language/writer.py delete mode 100644 pathod/libpathod/log.py delete mode 100644 pathod/libpathod/pathoc.py delete mode 100644 pathod/libpathod/pathoc_cmdline.py delete mode 100644 pathod/libpathod/pathod.py delete mode 100644 pathod/libpathod/pathod_cmdline.py delete mode 100644 pathod/libpathod/protocols/__init__.py delete mode 100644 pathod/libpathod/protocols/http.py delete mode 100644 pathod/libpathod/protocols/http2.py delete mode 100644 pathod/libpathod/protocols/websockets.py delete mode 100644 pathod/libpathod/static/bootstrap.min.css delete mode 100644 pathod/libpathod/static/bootstrap.min.js delete mode 100644 pathod/libpathod/static/jquery-1.7.2.min.js delete mode 100644 pathod/libpathod/static/jquery.localscroll-min.js delete mode 100644 pathod/libpathod/static/jquery.scrollTo-min.js delete mode 100644 pathod/libpathod/static/pathod.css delete mode 100644 pathod/libpathod/static/start_quote.png delete mode 100644 pathod/libpathod/static/syntax.css delete mode 100644 pathod/libpathod/static/torture.png delete mode 100644 pathod/libpathod/templates/about.html delete mode 100644 pathod/libpathod/templates/docframe.html delete mode 100644 pathod/libpathod/templates/docs_lang.html delete mode 100644 pathod/libpathod/templates/docs_lang_requests.html delete mode 100644 pathod/libpathod/templates/docs_lang_responses.html delete mode 100644 pathod/libpathod/templates/docs_lang_websockets.html delete mode 100644 pathod/libpathod/templates/docs_libpathod.html delete mode 100644 pathod/libpathod/templates/docs_pathoc.html delete mode 100644 pathod/libpathod/templates/docs_pathod.html delete mode 100644 pathod/libpathod/templates/docs_test.html delete mode 100644 pathod/libpathod/templates/download.html delete mode 100644 pathod/libpathod/templates/examples_context.html delete mode 100644 pathod/libpathod/templates/examples_setup.html delete mode 100644 pathod/libpathod/templates/examples_setupall.html delete mode 100644 pathod/libpathod/templates/frame.html delete mode 100644 pathod/libpathod/templates/index.html delete mode 100644 pathod/libpathod/templates/layout.html delete mode 100644 pathod/libpathod/templates/libpathod_pathoc.html delete mode 100644 pathod/libpathod/templates/log.html delete mode 100644 pathod/libpathod/templates/onelog.html delete mode 100644 pathod/libpathod/templates/request_preview.html delete mode 100644 pathod/libpathod/templates/request_previewform.html delete mode 100644 pathod/libpathod/templates/response_preview.html delete mode 100644 pathod/libpathod/templates/response_previewform.html delete mode 100644 pathod/libpathod/test.py delete mode 100644 pathod/libpathod/utils.py delete mode 100644 pathod/libpathod/version.py (limited to 'pathod/libpathod') diff --git a/pathod/libpathod/__init__.py b/pathod/libpathod/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pathod/libpathod/app.py b/pathod/libpathod/app.py deleted file mode 100644 index debebaf2..00000000 --- a/pathod/libpathod/app.py +++ /dev/null @@ -1,179 +0,0 @@ -import logging -import pprint -import cStringIO -import copy -from flask import Flask, jsonify, render_template, request, abort, make_response -from . import version, language, utils -from netlib.http import user_agents - -logging.basicConfig(level="DEBUG") -EXAMPLE_HOST = "example.com" -EXAMPLE_WEBSOCKET_KEY = "examplekey" - -# pylint: disable=unused-variable - - -def make_app(noapi, debug): - app = Flask(__name__) - app.debug = debug - - if not noapi: - @app.route('/api/info') - def api_info(): - return jsonify( - version=version.IVERSION - ) - - @app.route('/api/log') - def api_log(): - return jsonify( - log=app.config["pathod"].get_log() - ) - - @app.route('/api/clear_log') - def api_clear_log(): - app.config["pathod"].clear_log() - return "OK" - - def render(s, cacheable, **kwargs): - kwargs["noapi"] = app.config["pathod"].noapi - kwargs["nocraft"] = app.config["pathod"].nocraft - kwargs["craftanchor"] = app.config["pathod"].craftanchor - resp = make_response(render_template(s, **kwargs), 200) - if cacheable: - resp.headers["Cache-control"] = "public, max-age=4320" - return resp - - @app.route('/') - @app.route('/index.html') - def index(): - return render( - "index.html", - True, - section="main", - version=version.VERSION - ) - - @app.route('/download') - @app.route('/download.html') - def download(): - return render( - "download.html", True, section="download", version=version.VERSION - ) - - @app.route('/about') - @app.route('/about.html') - def about(): - return render("about.html", True, section="about") - - @app.route('/docs/pathod') - def docs_pathod(): - return render( - "docs_pathod.html", True, section="docs", subsection="pathod" - ) - - @app.route('/docs/language') - def docs_language(): - return render( - "docs_lang.html", True, - section="docs", uastrings=user_agents.UASTRINGS, - subsection="lang" - ) - - @app.route('/docs/pathoc') - def docs_pathoc(): - return render( - "docs_pathoc.html", True, section="docs", subsection="pathoc" - ) - - @app.route('/docs/libpathod') - def docs_libpathod(): - return render( - "docs_libpathod.html", True, section="docs", subsection="libpathod" - ) - - @app.route('/docs/test') - def docs_test(): - return render( - "docs_test.html", True, section="docs", subsection="test" - ) - - @app.route('/log') - def log(): - if app.config["pathod"].noapi: - abort(404) - return render( - "log.html", - False, - section="log", - log=app.config["pathod"].get_log() - ) - - @app.route('/log/') - def onelog(lid): - item = app.config["pathod"].log_by_id(int(lid)) - if not item: - abort(404) - l = pprint.pformat(item) - return render("onelog.html", False, section="log", alog=l, lid=lid) - - def _preview(is_request): - if is_request: - template = "request_preview.html" - else: - template = "response_preview.html" - - spec = request.args["spec"] - - args = dict( - spec=spec, - section="main", - syntaxerror=None, - error=None, - ) - if not spec.strip(): - args["error"] = "Can't parse an empty spec." - return render(template, False, **args) - - try: - if is_request: - r = language.parse_pathoc(spec).next() - else: - r = language.parse_pathod(spec).next() - except language.ParseException as v: - args["syntaxerror"] = str(v) - args["marked"] = v.marked() - return render(template, False, **args) - - s = cStringIO.StringIO() - - settings = copy.copy(app.config["pathod"].settings) - settings.request_host = EXAMPLE_HOST - settings.websocket_key = EXAMPLE_WEBSOCKET_KEY - - safe = r.preview_safe() - err, safe = app.config["pathod"].check_policy( - safe, - settings - ) - if err: - args["error"] = err - return render(template, False, **args) - if is_request: - settings.request_host = EXAMPLE_HOST - language.serve(safe, s, settings) - else: - settings.websocket_key = EXAMPLE_WEBSOCKET_KEY - language.serve(safe, s, settings) - - args["output"] = utils.escape_unprintables(s.getvalue()) - return render(template, False, **args) - - @app.route('/response_preview') - def response_preview(): - return _preview(False) - - @app.route('/request_preview') - def request_preview(): - return _preview(True) - return app diff --git a/pathod/libpathod/language/__init__.py b/pathod/libpathod/language/__init__.py deleted file mode 100644 index 32199e08..00000000 --- a/pathod/libpathod/language/__init__.py +++ /dev/null @@ -1,113 +0,0 @@ -import itertools -import time - -import pyparsing as pp - -from . import http, http2, websockets, writer, exceptions - -from exceptions import * -from base import Settings -assert Settings # prevent pyflakes from messing with this - - -def expand(msg): - times = getattr(msg, "times", None) - if times: - for j_ in xrange(int(times.value)): - yield msg.strike_token("times") - else: - yield msg - - -def parse_pathod(s, use_http2=False): - """ - May raise ParseException - """ - try: - s = s.decode("ascii") - except UnicodeError: - raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0) - try: - if use_http2: - expressions = [ - # http2.Frame.expr(), - http2.Response.expr(), - ] - else: - expressions = [ - websockets.WebsocketFrame.expr(), - http.Response.expr(), - ] - reqs = pp.Or(expressions).parseString(s, parseAll=True) - except pp.ParseException as v: - raise exceptions.ParseException(v.msg, v.line, v.col) - return itertools.chain(*[expand(i) for i in reqs]) - - -def parse_pathoc(s, use_http2=False): - try: - s = s.decode("ascii") - except UnicodeError: - raise exceptions.ParseException("Spec must be valid ASCII.", 0, 0) - try: - if use_http2: - expressions = [ - # http2.Frame.expr(), - http2.Request.expr(), - ] - else: - expressions = [ - websockets.WebsocketClientFrame.expr(), - http.Request.expr(), - ] - reqs = pp.OneOrMore(pp.Or(expressions)).parseString(s, parseAll=True) - except pp.ParseException as v: - raise exceptions.ParseException(v.msg, v.line, v.col) - return itertools.chain(*[expand(i) for i in reqs]) - - -def parse_websocket_frame(s): - """ - May raise ParseException - """ - try: - reqs = pp.OneOrMore( - websockets.WebsocketFrame.expr() - ).parseString( - s, - parseAll=True - ) - except pp.ParseException as v: - raise exceptions.ParseException(v.msg, v.line, v.col) - return itertools.chain(*[expand(i) for i in reqs]) - - -def serve(msg, fp, settings): - """ - fp: The file pointer to write to. - - request_host: If this a request, this is the connecting host. If - None, we assume it's a response. Used to decide what standard - modifications to make if raw is not set. - - Calling this function may modify the object. - """ - msg = msg.resolve(settings) - started = time.time() - - vals = msg.values(settings) - vals.reverse() - - actions = sorted(msg.actions[:]) - actions.reverse() - actions = [i.intermediate(settings) for i in actions] - - disconnect = writer.write_values(fp, vals, actions[:]) - duration = time.time() - started - ret = dict( - disconnect=disconnect, - started=started, - duration=duration, - ) - ret.update(msg.log(settings)) - return ret diff --git a/pathod/libpathod/language/actions.py b/pathod/libpathod/language/actions.py deleted file mode 100644 index 34a9bafb..00000000 --- a/pathod/libpathod/language/actions.py +++ /dev/null @@ -1,126 +0,0 @@ -import abc -import copy -import random - -import pyparsing as pp - -from . import base - - -class _Action(base.Token): - - """ - An action that operates on the raw data stream of the message. All - actions have one thing in common: an offset that specifies where the - action should take place. - """ - - def __init__(self, offset): - self.offset = offset - - def resolve(self, settings, msg): - """ - Resolves offset specifications to a numeric offset. Returns a copy - of the action object. - """ - c = copy.copy(self) - l = msg.length(settings) - if c.offset == "r": - c.offset = random.randrange(l) - elif c.offset == "a": - c.offset = l + 1 - return c - - def __cmp__(self, other): - return cmp(self.offset, other.offset) - - def __repr__(self): - return self.spec() - - @abc.abstractmethod - def spec(self): # pragma: no cover - pass - - @abc.abstractmethod - def intermediate(self, settings): # pragma: no cover - pass - - -class PauseAt(_Action): - unique_name = None - - def __init__(self, offset, seconds): - _Action.__init__(self, offset) - self.seconds = seconds - - @classmethod - def expr(cls): - e = pp.Literal("p").suppress() - e += base.TokOffset - e += pp.Literal(",").suppress() - e += pp.MatchFirst( - [ - base.v_integer, - pp.Literal("f") - ] - ) - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - return "p%s,%s" % (self.offset, self.seconds) - - def intermediate(self, settings): - return (self.offset, "pause", self.seconds) - - def freeze(self, settings_): - return self - - -class DisconnectAt(_Action): - - def __init__(self, offset): - _Action.__init__(self, offset) - - @classmethod - def expr(cls): - e = pp.Literal("d").suppress() - e += base.TokOffset - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - return "d%s" % self.offset - - def intermediate(self, settings): - return (self.offset, "disconnect") - - def freeze(self, settings_): - return self - - -class InjectAt(_Action): - unique_name = None - - def __init__(self, offset, value): - _Action.__init__(self, offset) - self.value = value - - @classmethod - def expr(cls): - e = pp.Literal("i").suppress() - e += base.TokOffset - e += pp.Literal(",").suppress() - e += base.TokValue - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - return "i%s,%s" % (self.offset, self.value.spec()) - - def intermediate(self, settings): - return ( - self.offset, - "inject", - self.value.get_generator(settings) - ) - - def freeze(self, settings): - return InjectAt(self.offset, self.value.freeze(settings)) diff --git a/pathod/libpathod/language/base.py b/pathod/libpathod/language/base.py deleted file mode 100644 index a4302998..00000000 --- a/pathod/libpathod/language/base.py +++ /dev/null @@ -1,576 +0,0 @@ -import operator -import os -import abc -import pyparsing as pp - -from .. import utils -from . import generators, exceptions - -class Settings(object): - - def __init__( - self, - is_client=False, - staticdir=None, - unconstrained_file_access=False, - request_host=None, - websocket_key=None, - protocol=None, - ): - self.is_client = is_client - self.staticdir = staticdir - self.unconstrained_file_access = unconstrained_file_access - self.request_host = request_host - self.websocket_key = websocket_key # TODO: refactor this into the protocol - self.protocol = protocol - - -Sep = pp.Optional(pp.Literal(":")).suppress() - - -v_integer = pp.Word(pp.nums)\ - .setName("integer")\ - .setParseAction(lambda toks: int(toks[0])) - - -v_literal = pp.MatchFirst( - [ - pp.QuotedString( - "\"", - unquoteResults=True, - multiline=True - ), - pp.QuotedString( - "'", - unquoteResults=True, - multiline=True - ), - ] -) - -v_naked_literal = pp.MatchFirst( - [ - v_literal, - pp.Word("".join(i for i in pp.printables if i not in ",:\n@\'\"")) - ] -) - - -class Token(object): - - """ - A token in the specification language. Tokens are immutable. The token - classes have no meaning in and of themselves, and are combined into - Components and Actions to build the language. - """ - __metaclass__ = abc.ABCMeta - - @classmethod - def expr(cls): # pragma: no cover - """ - A parse expression. - """ - return None - - @abc.abstractmethod - def spec(self): # pragma: no cover - """ - A parseable specification for this token. - """ - return None - - @property - def unique_name(self): - """ - Controls uniqueness constraints for tokens. No two tokens with the - same name will be allowed. If no uniquness should be applied, this - should be None. - """ - return self.__class__.__name__.lower() - - def resolve(self, settings_, msg_): - """ - Resolves this token to ready it for transmission. This means that - the calculated offsets of actions are fixed. - - settings: a language.Settings instance - msg: The containing message - """ - return self - - def __repr__(self): - return self.spec() - - -class _TokValueLiteral(Token): - - def __init__(self, val): - self.val = val.decode("string_escape") - - def get_generator(self, settings_): - return self.val - - def freeze(self, settings_): - return self - - -class TokValueLiteral(_TokValueLiteral): - - """ - A literal with Python-style string escaping - """ - @classmethod - def expr(cls): - e = v_literal.copy() - return e.setParseAction(cls.parseAction) - - @classmethod - def parseAction(cls, x): - v = cls(*x) - return v - - def spec(self): - inner = self.val.encode("string_escape") - inner = inner.replace(r"\'", r"\x27") - return "'" + inner + "'" - - -class TokValueNakedLiteral(_TokValueLiteral): - - @classmethod - def expr(cls): - e = v_naked_literal.copy() - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - return self.val.encode("string_escape") - - -class TokValueGenerate(Token): - - def __init__(self, usize, unit, datatype): - if not unit: - unit = "b" - self.usize, self.unit, self.datatype = usize, unit, datatype - - def bytes(self): - return self.usize * utils.SIZE_UNITS[self.unit] - - def get_generator(self, settings_): - return generators.RandomGenerator(self.datatype, self.bytes()) - - def freeze(self, settings): - g = self.get_generator(settings) - return TokValueLiteral(g[:].encode("string_escape")) - - @classmethod - def expr(cls): - e = pp.Literal("@").suppress() + v_integer - - u = reduce( - operator.or_, - [pp.Literal(i) for i in utils.SIZE_UNITS.keys()] - ).leaveWhitespace() - e = e + pp.Optional(u, default=None) - - s = pp.Literal(",").suppress() - s += reduce( - operator.or_, - [pp.Literal(i) for i in generators.DATATYPES.keys()] - ) - e += pp.Optional(s, default="bytes") - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - s = "@%s" % self.usize - if self.unit != "b": - s += self.unit - if self.datatype != "bytes": - s += ",%s" % self.datatype - return s - - -class TokValueFile(Token): - - def __init__(self, path): - self.path = str(path) - - @classmethod - def expr(cls): - e = pp.Literal("<").suppress() - e = e + v_naked_literal - return e.setParseAction(lambda x: cls(*x)) - - def freeze(self, settings_): - return self - - def get_generator(self, settings): - if not settings.staticdir: - raise exceptions.FileAccessDenied("File access disabled.") - s = os.path.expanduser(self.path) - s = os.path.normpath( - os.path.abspath(os.path.join(settings.staticdir, s)) - ) - uf = settings.unconstrained_file_access - if not uf and not s.startswith(settings.staticdir): - raise exceptions.FileAccessDenied( - "File access outside of configured directory" - ) - if not os.path.isfile(s): - raise exceptions.FileAccessDenied("File not readable") - return generators.FileGenerator(s) - - def spec(self): - return "<'%s'" % self.path.encode("string_escape") - - -TokValue = pp.MatchFirst( - [ - TokValueGenerate.expr(), - TokValueFile.expr(), - TokValueLiteral.expr() - ] -) - - -TokNakedValue = pp.MatchFirst( - [ - TokValueGenerate.expr(), - TokValueFile.expr(), - TokValueLiteral.expr(), - TokValueNakedLiteral.expr(), - ] -) - - -TokOffset = pp.MatchFirst( - [ - v_integer, - pp.Literal("r"), - pp.Literal("a") - ] -) - - -class _Component(Token): - - """ - A value component of the primary specification of an message. - Components produce byte values desribe the bytes of the message. - """ - - def values(self, settings): # pragma: no cover - """ - A sequence of values, which can either be strings or generators. - """ - pass - - def string(self, settings=None): - """ - A string representation of the object. - """ - return "".join(i[:] for i in self.values(settings or {})) - - -class KeyValue(_Component): - - """ - A key/value pair. - cls.preamble: leader - """ - - def __init__(self, key, value): - self.key, self.value = key, value - - @classmethod - def expr(cls): - e = pp.Literal(cls.preamble).suppress() - e += TokValue - e += pp.Literal("=").suppress() - e += TokValue - return e.setParseAction(lambda x: cls(*x)) - - def spec(self): - return "%s%s=%s" % (self.preamble, self.key.spec(), self.value.spec()) - - def freeze(self, settings): - return self.__class__( - self.key.freeze(settings), self.value.freeze(settings) - ) - - -class CaselessLiteral(_Component): - - """ - A caseless token that can take only one value. - """ - - def __init__(self, value): - self.value = value - - @classmethod - def expr(cls): - spec = pp.CaselessLiteral(cls.TOK) - spec = spec.setParseAction(lambda x: cls(*x)) - return spec - - def values(self, settings): - return self.TOK - - def spec(self): - return self.TOK - - def freeze(self, settings_): - return self - - -class OptionsOrValue(_Component): - - """ - Can be any of a specified set of options, or a value specifier. - """ - preamble = "" - options = [] - - def __init__(self, value): - # If it's a string, we were passed one of the options, so we lower-case - # it to be canonical. The user can specify a different case by using a - # string value literal. - self.option_used = False - if isinstance(value, basestring): - for i in self.options: - # Find the exact option value in a case-insensitive way - if i.lower() == value.lower(): - self.option_used = True - value = TokValueLiteral(i) - break - self.value = value - - @classmethod - def expr(cls): - parts = [pp.CaselessLiteral(i) for i in cls.options] - m = pp.MatchFirst(parts) - spec = m | TokValue.copy() - spec = spec.setParseAction(lambda x: cls(*x)) - if cls.preamble: - spec = pp.Literal(cls.preamble).suppress() + spec - return spec - - def values(self, settings): - return [ - self.value.get_generator(settings) - ] - - def spec(self): - s = self.value.spec() - if s[1:-1].lower() in self.options: - s = s[1:-1].lower() - return "%s%s" % (self.preamble, s) - - def freeze(self, settings): - return self.__class__(self.value.freeze(settings)) - - -class Integer(_Component): - bounds = (None, None) - preamble = "" - - def __init__(self, value): - v = int(value) - outofbounds = any([ - self.bounds[0] is not None and v < self.bounds[0], - self.bounds[1] is not None and v > self.bounds[1] - ]) - if outofbounds: - raise exceptions.ParseException( - "Integer value must be between %s and %s." % self.bounds, - 0, 0 - ) - self.value = str(value) - - @classmethod - def expr(cls): - e = v_integer.copy() - if cls.preamble: - e = pp.Literal(cls.preamble).suppress() + e - return e.setParseAction(lambda x: cls(*x)) - - def values(self, settings): - return self.value - - def spec(self): - return "%s%s" % (self.preamble, self.value) - - def freeze(self, settings_): - return self - - -class Value(_Component): - - """ - A value component lead by an optional preamble. - """ - preamble = "" - - def __init__(self, value): - self.value = value - - @classmethod - def expr(cls): - e = (TokValue | TokNakedValue) - if cls.preamble: - e = pp.Literal(cls.preamble).suppress() + e - return e.setParseAction(lambda x: cls(*x)) - - def values(self, settings): - return [self.value.get_generator(settings)] - - def spec(self): - return "%s%s" % (self.preamble, self.value.spec()) - - def freeze(self, settings): - return self.__class__(self.value.freeze(settings)) - - -class FixedLengthValue(Value): - - """ - A value component lead by an optional preamble. - """ - preamble = "" - length = None - - def __init__(self, value): - Value.__init__(self, value) - lenguess = None - try: - lenguess = len(value.get_generator(Settings())) - except exceptions.RenderError: - pass - # This check will fail if we know the length upfront - if lenguess is not None and lenguess != self.length: - raise exceptions.RenderError( - "Invalid value length: '%s' is %s bytes, should be %s." % ( - self.spec(), - lenguess, - self.length - ) - ) - - def values(self, settings): - ret = Value.values(self, settings) - l = sum(len(i) for i in ret) - # This check will fail if we don't know the length upfront - i.e. for - # file inputs - if l != self.length: - raise exceptions.RenderError( - "Invalid value length: '%s' is %s bytes, should be %s." % ( - self.spec(), - l, - self.length - ) - ) - return ret - - -class Boolean(_Component): - - """ - A boolean flag. - name = true - -name = false - """ - name = "" - - def __init__(self, value): - self.value = value - - @classmethod - def expr(cls): - e = pp.Optional(pp.Literal("-"), default=True) - e += pp.Literal(cls.name).suppress() - - def parse(s_, loc_, toks): - val = True - if toks[0] == "-": - val = False - return cls(val) - - return e.setParseAction(parse) - - def spec(self): - return "%s%s" % ("-" if not self.value else "", self.name) - - -class IntField(_Component): - - """ - An integer field, where values can optionally specified by name. - """ - names = {} - max = 16 - preamble = "" - - def __init__(self, value): - self.origvalue = value - self.value = self.names.get(value, value) - if self.value > self.max: - raise exceptions.ParseException( - "Value can't exceed %s" % self.max, 0, 0 - ) - - @classmethod - def expr(cls): - parts = [pp.CaselessLiteral(i) for i in cls.names.keys()] - m = pp.MatchFirst(parts) - spec = m | v_integer.copy() - spec = spec.setParseAction(lambda x: cls(*x)) - if cls.preamble: - spec = pp.Literal(cls.preamble).suppress() + spec - return spec - - def values(self, settings): - return [str(self.value)] - - def spec(self): - return "%s%s" % (self.preamble, self.origvalue) - - -class NestedMessage(Token): - - """ - A nested message, as an escaped string with a preamble. - """ - preamble = "" - nest_type = None - - def __init__(self, value): - Token.__init__(self) - self.value = value - try: - self.parsed = self.nest_type( - self.nest_type.expr().parseString( - value.val, - parseAll=True - ) - ) - except pp.ParseException as v: - raise exceptions.ParseException(v.msg, v.line, v.col) - - @classmethod - def expr(cls): - e = pp.Literal(cls.preamble).suppress() - e = e + TokValueLiteral.expr() - return e.setParseAction(lambda x: cls(*x)) - - def values(self, settings): - return [ - self.value.get_generator(settings), - ] - - def spec(self): - return "%s%s" % (self.preamble, self.value.spec()) - - def freeze(self, settings): - f = self.parsed.freeze(settings).spec() - return self.__class__(TokValueLiteral(f.encode("string_escape"))) diff --git a/pathod/libpathod/language/exceptions.py b/pathod/libpathod/language/exceptions.py deleted file mode 100644 index 84ad3c02..00000000 --- a/pathod/libpathod/language/exceptions.py +++ /dev/null @@ -1,22 +0,0 @@ - -class RenderError(Exception): - pass - - -class FileAccessDenied(RenderError): - pass - - -class ParseException(Exception): - - def __init__(self, msg, s, col): - Exception.__init__(self) - self.msg = msg - self.s = s - self.col = col - - def marked(self): - return "%s\n%s" % (self.s, " " * (self.col - 1) + "^") - - def __str__(self): - return "%s at char %s" % (self.msg, self.col) diff --git a/pathod/libpathod/language/generators.py b/pathod/libpathod/language/generators.py deleted file mode 100644 index a17e7052..00000000 --- a/pathod/libpathod/language/generators.py +++ /dev/null @@ -1,86 +0,0 @@ -import string -import random -import mmap - -DATATYPES = dict( - ascii_letters=string.ascii_letters, - ascii_lowercase=string.ascii_lowercase, - ascii_uppercase=string.ascii_uppercase, - digits=string.digits, - hexdigits=string.hexdigits, - octdigits=string.octdigits, - punctuation=string.punctuation, - whitespace=string.whitespace, - ascii=string.printable, - bytes="".join(chr(i) for i in range(256)) -) - - -class TransformGenerator(object): - - """ - Perform a byte-by-byte transform another generator - that is, for each - input byte, the transformation must produce one output byte. - - gen: A generator to wrap - transform: A function (offset, data) -> transformed - """ - - def __init__(self, gen, transform): - self.gen = gen - self.transform = transform - - def __len__(self): - return len(self.gen) - - def __getitem__(self, x): - d = self.gen.__getitem__(x) - return self.transform(x, d) - - def __getslice__(self, a, b): - d = self.gen.__getslice__(a, b) - return self.transform(a, d) - - def __repr__(self): - return "'transform(%s)'" % self.gen - - -class RandomGenerator(object): - - def __init__(self, dtype, length): - self.dtype = dtype - self.length = length - - def __len__(self): - return self.length - - def __getitem__(self, x): - return random.choice(DATATYPES[self.dtype]) - - def __getslice__(self, a, b): - b = min(b, self.length) - chars = DATATYPES[self.dtype] - return "".join(random.choice(chars) for x in range(a, b)) - - def __repr__(self): - return "%s random from %s" % (self.length, self.dtype) - - -class FileGenerator(object): - - def __init__(self, path): - self.path = path - self.fp = file(path, "rb") - self.map = mmap.mmap(self.fp.fileno(), 0, access=mmap.ACCESS_READ) - - def __len__(self): - return len(self.map) - - def __getitem__(self, x): - return self.map.__getitem__(x) - - def __getslice__(self, a, b): - return self.map.__getslice__(a, b) - - def __repr__(self): - return "<%s" % self.path diff --git a/pathod/libpathod/language/http.py b/pathod/libpathod/language/http.py deleted file mode 100644 index a82f12fe..00000000 --- a/pathod/libpathod/language/http.py +++ /dev/null @@ -1,381 +0,0 @@ - -import abc - -import pyparsing as pp - -import netlib.websockets -from netlib.http import status_codes, user_agents -from . import base, exceptions, actions, message - -# TODO: use netlib.semantics.protocol assemble method, -# instead of duplicating the HTTP on-the-wire representation here. -# see http2 language for an example - -class WS(base.CaselessLiteral): - TOK = "ws" - - -class Raw(base.CaselessLiteral): - TOK = "r" - - -class Path(base.Value): - pass - - -class StatusCode(base.Integer): - pass - - -class Reason(base.Value): - preamble = "m" - - -class Body(base.Value): - preamble = "b" - - -class Times(base.Integer): - preamble = "x" - - -class Method(base.OptionsOrValue): - options = [ - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - "OPTIONS", - "TRACE", - "CONNECT", - ] - - -class _HeaderMixin(object): - unique_name = None - - def format_header(self, key, value): - return [key, ": ", value, "\r\n"] - - def values(self, settings): - return self.format_header( - self.key.get_generator(settings), - self.value.get_generator(settings), - ) - - -class Header(_HeaderMixin, base.KeyValue): - preamble = "h" - - -class ShortcutContentType(_HeaderMixin, base.Value): - preamble = "c" - key = base.TokValueLiteral("Content-Type") - - -class ShortcutLocation(_HeaderMixin, base.Value): - preamble = "l" - key = base.TokValueLiteral("Location") - - -class ShortcutUserAgent(_HeaderMixin, base.OptionsOrValue): - preamble = "u" - options = [i[1] for i in user_agents.UASTRINGS] - key = base.TokValueLiteral("User-Agent") - - def values(self, settings): - value = self.value.val - if self.option_used: - value = user_agents.get_by_shortcut(value.lower())[2] - - return self.format_header( - self.key.get_generator(settings), - value - ) - - -def get_header(val, headers): - """ - Header keys may be Values, so we have to "generate" them as we try the - match. - """ - for h in headers: - k = h.key.get_generator({}) - if len(k) == len(val) and k[:].lower() == val.lower(): - return h - return None - - -class _HTTPMessage(message.Message): - version = "HTTP/1.1" - - @property - def actions(self): - return self.toks(actions._Action) - - @property - def raw(self): - return bool(self.tok(Raw)) - - @property - def body(self): - return self.tok(Body) - - @abc.abstractmethod - def preamble(self, settings): # pragma: no cover - pass - - @property - def headers(self): - return self.toks(_HeaderMixin) - - def values(self, settings): - vals = self.preamble(settings) - vals.append("\r\n") - for h in self.headers: - vals.extend(h.values(settings)) - vals.append("\r\n") - if self.body: - vals.extend(self.body.values(settings)) - return vals - - -class Response(_HTTPMessage): - unique_name = None - comps = ( - Header, - ShortcutContentType, - ShortcutLocation, - Raw, - Reason, - Body, - - actions.PauseAt, - actions.DisconnectAt, - actions.InjectAt, - ) - logattrs = ["status_code", "reason", "version", "body"] - - @property - def ws(self): - return self.tok(WS) - - @property - def status_code(self): - return self.tok(StatusCode) - - @property - def reason(self): - return self.tok(Reason) - - def preamble(self, settings): - l = [self.version, " "] - l.extend(self.status_code.values(settings)) - status_code = int(self.status_code.value) - l.append(" ") - if self.reason: - l.extend(self.reason.values(settings)) - else: - l.append( - status_codes.RESPONSES.get( - status_code, - "Unknown code" - ) - ) - return l - - def resolve(self, settings, msg=None): - tokens = self.tokens[:] - if self.ws: - if not settings.websocket_key: - raise exceptions.RenderError( - "No websocket key - have we seen a client handshake?" - ) - if not self.status_code: - tokens.insert( - 1, - StatusCode(101) - ) - headers = netlib.websockets.WebsocketsProtocol.server_handshake_headers( - settings.websocket_key - ) - for i in headers.fields: - if not get_header(i[0], self.headers): - tokens.append( - Header( - base.TokValueLiteral(i[0]), - base.TokValueLiteral(i[1])) - ) - if not self.raw: - if not get_header("Content-Length", self.headers): - if not self.body: - length = 0 - else: - length = sum( - len(i) for i in self.body.values(settings) - ) - tokens.append( - Header( - base.TokValueLiteral("Content-Length"), - base.TokValueLiteral(str(length)), - ) - ) - intermediate = self.__class__(tokens) - return self.__class__( - [i.resolve(settings, intermediate) for i in tokens] - ) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.comps] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - pp.MatchFirst( - [ - WS.expr() + pp.Optional( - base.Sep + StatusCode.expr() - ), - StatusCode.expr(), - ] - ), - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - - -class NestedResponse(base.NestedMessage): - preamble = "s" - nest_type = Response - - -class Request(_HTTPMessage): - comps = ( - Header, - ShortcutContentType, - ShortcutUserAgent, - Raw, - NestedResponse, - Body, - Times, - - actions.PauseAt, - actions.DisconnectAt, - actions.InjectAt, - ) - logattrs = ["method", "path", "body"] - - @property - def ws(self): - return self.tok(WS) - - @property - def method(self): - return self.tok(Method) - - @property - def path(self): - return self.tok(Path) - - @property - def times(self): - return self.tok(Times) - - @property - def nested_response(self): - return self.tok(NestedResponse) - - def preamble(self, settings): - v = self.method.values(settings) - v.append(" ") - v.extend(self.path.values(settings)) - if self.nested_response: - v.append(self.nested_response.parsed.spec()) - v.append(" ") - v.append(self.version) - return v - - def resolve(self, settings, msg=None): - tokens = self.tokens[:] - if self.ws: - if not self.method: - tokens.insert( - 1, - Method("get") - ) - for i in netlib.websockets.WebsocketsProtocol.client_handshake_headers().fields: - if not get_header(i[0], self.headers): - tokens.append( - Header( - base.TokValueLiteral(i[0]), - base.TokValueLiteral(i[1]) - ) - ) - if not self.raw: - if not get_header("Content-Length", self.headers): - if self.body: - length = sum( - len(i) for i in self.body.values(settings) - ) - tokens.append( - Header( - base.TokValueLiteral("Content-Length"), - base.TokValueLiteral(str(length)), - ) - ) - if settings.request_host: - if not get_header("Host", self.headers): - tokens.append( - Header( - base.TokValueLiteral("Host"), - base.TokValueLiteral(settings.request_host) - ) - ) - intermediate = self.__class__(tokens) - return self.__class__( - [i.resolve(settings, intermediate) for i in tokens] - ) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.comps] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - pp.MatchFirst( - [ - WS.expr() + pp.Optional( - base.Sep + Method.expr() - ), - Method.expr(), - ] - ), - base.Sep, - Path.expr(), - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - - -def make_error_response(reason, body=None): - tokens = [ - StatusCode("800"), - Header( - base.TokValueLiteral("Content-Type"), - base.TokValueLiteral("text/plain") - ), - Reason(base.TokValueLiteral(reason)), - Body(base.TokValueLiteral("pathod error: " + (body or reason))), - ] - return Response(tokens) diff --git a/pathod/libpathod/language/http2.py b/pathod/libpathod/language/http2.py deleted file mode 100644 index d5e3ca31..00000000 --- a/pathod/libpathod/language/http2.py +++ /dev/null @@ -1,299 +0,0 @@ -import pyparsing as pp - -from netlib import http -from netlib.http import user_agents, Headers -from . import base, message - -""" - Normal HTTP requests: - ::
: - e.g.: - GET:/ - GET:/:h"foo"="bar" - POST:/:h"foo"="bar":b'content body payload' - - Normal HTTP responses: - :
: - e.g.: - 200 - 302:h"foo"="bar" - 404:h"foo"="bar":b'content body payload' - - Individual HTTP/2 frames: - h2f::::: - e.g.: - h2f:0:PING - h2f:42:HEADERS:END_HEADERS:0x1234567:foo=bar,host=example.com - h2f:42:DATA:END_STREAM,PADDED:0x1234567:'content body payload' -""" - -def get_header(val, headers): - """ - Header keys may be Values, so we have to "generate" them as we try the - match. - """ - for h in headers: - k = h.key.get_generator({}) - if len(k) == len(val) and k[:].lower() == val.lower(): - return h - return None - - -class _HeaderMixin(object): - unique_name = None - - def values(self, settings): - return ( - self.key.get_generator(settings), - self.value.get_generator(settings), - ) - -class _HTTP2Message(message.Message): - @property - def actions(self): - return [] # self.toks(actions._Action) - - @property - def headers(self): - headers = self.toks(_HeaderMixin) - - if not self.raw: - if not get_header("content-length", headers): - if not self.body: - length = 0 - else: - length = len(self.body.string()) - headers.append( - Header( - base.TokValueLiteral("content-length"), - base.TokValueLiteral(str(length)), - ) - ) - return headers - - @property - def raw(self): - return bool(self.tok(Raw)) - - @property - def body(self): - return self.tok(Body) - - def resolve(self, settings): - return self - - -class StatusCode(base.Integer): - pass - - -class Method(base.OptionsOrValue): - options = [ - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - ] - - -class Path(base.Value): - pass - - -class Header(_HeaderMixin, base.KeyValue): - preamble = "h" - - -class ShortcutContentType(_HeaderMixin, base.Value): - preamble = "c" - key = base.TokValueLiteral("content-type") - - -class ShortcutLocation(_HeaderMixin, base.Value): - preamble = "l" - key = base.TokValueLiteral("location") - - -class ShortcutUserAgent(_HeaderMixin, base.OptionsOrValue): - preamble = "u" - options = [i[1] for i in user_agents.UASTRINGS] - key = base.TokValueLiteral("user-agent") - - def values(self, settings): - value = self.value.val - if self.option_used: - value = user_agents.get_by_shortcut(value.lower())[2] - - return ( - self.key.get_generator(settings), - value - ) - - -class Raw(base.CaselessLiteral): - TOK = "r" - - -class Body(base.Value): - preamble = "b" - - -class Times(base.Integer): - preamble = "x" - - -class Response(_HTTP2Message): - unique_name = None - comps = ( - Header, - Body, - ShortcutContentType, - ShortcutLocation, - Raw, - ) - - def __init__(self, tokens): - super(Response, self).__init__(tokens) - self.rendered_values = None - self.stream_id = 2 - - @property - def status_code(self): - return self.tok(StatusCode) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.comps] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - StatusCode.expr(), - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - def values(self, settings): - if self.rendered_values: - return self.rendered_values - else: - headers = Headers([header.values(settings) for header in self.headers]) - - body = self.body - if body: - body = body.string() - - resp = http.Response( - (2, 0), - self.status_code.string(), - '', - headers, - body, - ) - resp.stream_id = self.stream_id - - self.rendered_values = settings.protocol.assemble(resp) - return self.rendered_values - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - - -class NestedResponse(base.NestedMessage): - preamble = "s" - nest_type = Response - - -class Request(_HTTP2Message): - comps = ( - Header, - ShortcutContentType, - ShortcutUserAgent, - Raw, - NestedResponse, - Body, - Times, - ) - logattrs = ["method", "path"] - - def __init__(self, tokens): - super(Request, self).__init__(tokens) - self.rendered_values = None - self.stream_id = 1 - - @property - def method(self): - return self.tok(Method) - - @property - def path(self): - return self.tok(Path) - - @property - def nested_response(self): - return self.tok(NestedResponse) - - @property - def times(self): - return self.tok(Times) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.comps] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - Method.expr(), - base.Sep, - Path.expr(), - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - def values(self, settings): - if self.rendered_values: - return self.rendered_values - else: - path = self.path.string() - if self.nested_response: - path += self.nested_response.parsed.spec() - - headers = Headers([header.values(settings) for header in self.headers]) - - body = self.body - if body: - body = body.string() - - req = http.Request( - '', - self.method.string(), - '', - '', - '', - path, - (2, 0), - headers, - body, - ) - req.stream_id = self.stream_id - - self.rendered_values = settings.protocol.assemble(req) - return self.rendered_values - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - -def make_error_response(reason, body=None): - tokens = [ - StatusCode("800"), - Body(base.TokValueLiteral("pathod error: " + (body or reason))), - ] - return Response(tokens) - - -# class Frame(message.Message): -# pass diff --git a/pathod/libpathod/language/message.py b/pathod/libpathod/language/message.py deleted file mode 100644 index 33124856..00000000 --- a/pathod/libpathod/language/message.py +++ /dev/null @@ -1,96 +0,0 @@ -import abc -from . import actions, exceptions - -LOG_TRUNCATE = 1024 - - -class Message(object): - __metaclass__ = abc.ABCMeta - logattrs = [] - - def __init__(self, tokens): - track = set([]) - for i in tokens: - if i.unique_name: - if i.unique_name in track: - raise exceptions.ParseException( - "Message has multiple %s clauses, " - "but should only have one." % i.unique_name, - 0, 0 - ) - else: - track.add(i.unique_name) - self.tokens = tokens - - def strike_token(self, name): - toks = [i for i in self.tokens if i.unique_name != name] - return self.__class__(toks) - - def toks(self, klass): - """ - Fetch all tokens that are instances of klass - """ - return [i for i in self.tokens if isinstance(i, klass)] - - def tok(self, klass): - """ - Fetch first token that is an instance of klass - """ - l = self.toks(klass) - if l: - return l[0] - - def length(self, settings): - """ - Calculate the length of the base message without any applied - actions. - """ - return sum(len(x) for x in self.values(settings)) - - def preview_safe(self): - """ - Return a copy of this message that issafe for previews. - """ - tokens = [i for i in self.tokens if not isinstance(i, actions.PauseAt)] - return self.__class__(tokens) - - def maximum_length(self, settings): - """ - Calculate the maximum length of the base message with all applied - actions. - """ - l = self.length(settings) - for i in self.actions: - if isinstance(i, actions.InjectAt): - l += len(i.value.get_generator(settings)) - return l - - @classmethod - def expr(cls): # pragma: no cover - pass - - def log(self, settings): - """ - A dictionary that should be logged if this message is served. - """ - ret = {} - for i in self.logattrs: - v = getattr(self, i) - # Careful not to log any VALUE specs without sanitizing them first. - # We truncate at 1k. - if hasattr(v, "values"): - v = [x[:LOG_TRUNCATE] for x in v.values(settings)] - v = "".join(v).encode("string_escape") - elif hasattr(v, "__len__"): - v = v[:LOG_TRUNCATE] - v = v.encode("string_escape") - ret[i] = v - ret["spec"] = self.spec() - return ret - - def freeze(self, settings): - r = self.resolve(settings) - return self.__class__([i.freeze(settings) for i in r.tokens]) - - def __repr__(self): - return self.spec() diff --git a/pathod/libpathod/language/websockets.py b/pathod/libpathod/language/websockets.py deleted file mode 100644 index ea7c870e..00000000 --- a/pathod/libpathod/language/websockets.py +++ /dev/null @@ -1,241 +0,0 @@ -import os -import netlib.websockets -import pyparsing as pp -from . import base, generators, actions, message - -NESTED_LEADER = "pathod!" - - -class WF(base.CaselessLiteral): - TOK = "wf" - - -class OpCode(base.IntField): - names = { - "continue": netlib.websockets.OPCODE.CONTINUE, - "text": netlib.websockets.OPCODE.TEXT, - "binary": netlib.websockets.OPCODE.BINARY, - "close": netlib.websockets.OPCODE.CLOSE, - "ping": netlib.websockets.OPCODE.PING, - "pong": netlib.websockets.OPCODE.PONG, - } - max = 15 - preamble = "c" - - -class Body(base.Value): - preamble = "b" - - -class RawBody(base.Value): - unique_name = "body" - preamble = "r" - - -class Fin(base.Boolean): - name = "fin" - - -class RSV1(base.Boolean): - name = "rsv1" - - -class RSV2(base.Boolean): - name = "rsv2" - - -class RSV3(base.Boolean): - name = "rsv3" - - -class Mask(base.Boolean): - name = "mask" - - -class Key(base.FixedLengthValue): - preamble = "k" - length = 4 - - -class KeyNone(base.CaselessLiteral): - unique_name = "key" - TOK = "knone" - - -class Length(base.Integer): - bounds = (0, 1 << 64) - preamble = "l" - - -class Times(base.Integer): - preamble = "x" - - -COMPONENTS = ( - OpCode, - Length, - # Bit flags - Fin, - RSV1, - RSV2, - RSV3, - Mask, - actions.PauseAt, - actions.DisconnectAt, - actions.InjectAt, - KeyNone, - Key, - Times, - - Body, - RawBody, -) - - -class WebsocketFrame(message.Message): - components = COMPONENTS - logattrs = ["body"] - # Used for nested frames - unique_name = "body" - - @property - def actions(self): - return self.toks(actions._Action) - - @property - def body(self): - return self.tok(Body) - - @property - def rawbody(self): - return self.tok(RawBody) - - @property - def opcode(self): - return self.tok(OpCode) - - @property - def fin(self): - return self.tok(Fin) - - @property - def rsv1(self): - return self.tok(RSV1) - - @property - def rsv2(self): - return self.tok(RSV2) - - @property - def rsv3(self): - return self.tok(RSV3) - - @property - def mask(self): - return self.tok(Mask) - - @property - def key(self): - return self.tok(Key) - - @property - def knone(self): - return self.tok(KeyNone) - - @property - def times(self): - return self.tok(Times) - - @property - def toklength(self): - return self.tok(Length) - - @classmethod - def expr(cls): - parts = [i.expr() for i in cls.components] - atom = pp.MatchFirst(parts) - resp = pp.And( - [ - WF.expr(), - base.Sep, - pp.ZeroOrMore(base.Sep + atom) - ] - ) - resp = resp.setParseAction(cls) - return resp - - @property - def nested_frame(self): - return self.tok(NestedFrame) - - def resolve(self, settings, msg=None): - tokens = self.tokens[:] - if not self.mask and settings.is_client: - tokens.append( - Mask(True) - ) - if not self.knone and self.mask and self.mask.value and not self.key: - tokens.append( - Key(base.TokValueLiteral(os.urandom(4))) - ) - return self.__class__( - [i.resolve(settings, self) for i in tokens] - ) - - def values(self, settings): - if self.body: - bodygen = self.body.value.get_generator(settings) - length = len(self.body.value.get_generator(settings)) - elif self.rawbody: - bodygen = self.rawbody.value.get_generator(settings) - length = len(self.rawbody.value.get_generator(settings)) - elif self.nested_frame: - bodygen = NESTED_LEADER + self.nested_frame.parsed.spec() - length = len(bodygen) - else: - bodygen = None - length = 0 - if self.toklength: - length = int(self.toklength.value) - frameparts = dict( - payload_length=length - ) - if self.mask and self.mask.value: - frameparts["mask"] = True - if self.knone: - frameparts["masking_key"] = None - elif self.key: - key = self.key.values(settings)[0][:] - frameparts["masking_key"] = key - for i in ["opcode", "fin", "rsv1", "rsv2", "rsv3", "mask"]: - v = getattr(self, i, None) - if v is not None: - frameparts[i] = v.value - frame = netlib.websockets.FrameHeader(**frameparts) - vals = [bytes(frame)] - if bodygen: - if frame.masking_key and not self.rawbody: - masker = netlib.websockets.Masker(frame.masking_key) - vals.append( - generators.TransformGenerator( - bodygen, - masker.mask - ) - ) - else: - vals.append(bodygen) - return vals - - def spec(self): - return ":".join([i.spec() for i in self.tokens]) - - -class NestedFrame(base.NestedMessage): - preamble = "f" - nest_type = WebsocketFrame - - -class WebsocketClientFrame(WebsocketFrame): - components = COMPONENTS + ( - NestedFrame, - ) diff --git a/pathod/libpathod/language/writer.py b/pathod/libpathod/language/writer.py deleted file mode 100644 index 1a27e1ef..00000000 --- a/pathod/libpathod/language/writer.py +++ /dev/null @@ -1,67 +0,0 @@ -import time -from netlib.exceptions import TcpDisconnect -import netlib.tcp - -BLOCKSIZE = 1024 -# It's not clear what the upper limit for time.sleep is. It's lower than the -# maximum int or float. 1 year should do. -FOREVER = 60 * 60 * 24 * 365 - - -def send_chunk(fp, val, blocksize, start, end): - """ - (start, end): Inclusive lower bound, exclusive upper bound. - """ - for i in range(start, end, blocksize): - fp.write( - val[i:min(i + blocksize, end)] - ) - return end - start - - -def write_values(fp, vals, actions, sofar=0, blocksize=BLOCKSIZE): - """ - vals: A list of values, which may be strings or Value objects. - - actions: A list of (offset, action, arg) tuples. Action may be "pause" - or "disconnect". - - Both vals and actions are in reverse order, with the first items last. - - Return True if connection should disconnect. - """ - sofar = 0 - try: - while vals: - v = vals.pop() - offset = 0 - while actions and actions[-1][0] < (sofar + len(v)): - a = actions.pop() - offset += send_chunk( - fp, - v, - blocksize, - offset, - a[0] - sofar - offset - ) - if a[1] == "pause": - time.sleep( - FOREVER if a[2] == "f" else a[2] - ) - elif a[1] == "disconnect": - return True - elif a[1] == "inject": - send_chunk(fp, a[2], blocksize, 0, len(a[2])) - send_chunk(fp, v, blocksize, offset, len(v)) - sofar += len(v) - # Remainders - while actions: - a = actions.pop() - if a[1] == "pause": - time.sleep(a[2]) - elif a[1] == "disconnect": - return True - elif a[1] == "inject": - send_chunk(fp, a[2], blocksize, 0, len(a[2])) - except TcpDisconnect: # pragma: no cover - return True diff --git a/pathod/libpathod/log.py b/pathod/libpathod/log.py deleted file mode 100644 index f203542f..00000000 --- a/pathod/libpathod/log.py +++ /dev/null @@ -1,83 +0,0 @@ -import datetime - -import netlib.utils -import netlib.tcp -import netlib.http - -TIMEFMT = '%d-%m-%y %H:%M:%S' - - -def write_raw(fp, lines): - if fp: - fp.write( - "%s: " % datetime.datetime.now().strftime(TIMEFMT) - ) - for i in lines: - fp.write(i) - fp.write("\n") - fp.flush() - - -class LogCtx(object): - - def __init__(self, fp, hex, rfile, wfile): - self.lines = [] - self.fp = fp - self.suppressed = False - self.hex = hex - self.rfile, self.wfile = rfile, wfile - - def __enter__(self): - if self.wfile: - self.wfile.start_log() - if self.rfile: - self.rfile.start_log() - return self - - def __exit__(self, exc_type, exc_value, traceback): - wlog = self.wfile.get_log() if self.wfile else None - rlog = self.rfile.get_log() if self.rfile else None - if self.suppressed or not self.fp: - return - if wlog: - self("Bytes written:") - self.dump(wlog, self.hex) - if rlog: - self("Bytes read:") - self.dump(rlog, self.hex) - if self.lines: - write_raw( - self.fp, - [ - "\n".join(self.lines), - ] - ) - if exc_value: - raise exc_type, exc_value, traceback - - def suppress(self): - self.suppressed = True - - def dump(self, data, hexdump): - if hexdump: - for line in netlib.utils.hexdump(data): - self("\t%s %s %s" % line) - else: - for i in netlib.utils.clean_bin(data).split("\n"): - self("\t%s" % i) - - def __call__(self, line): - self.lines.append(line) - - -class ConnectionLogger: - def __init__(self, fp, hex, rfile, wfile): - self.fp = fp - self.hex = hex - self.rfile, self.wfile = rfile, wfile - - def ctx(self): - return LogCtx(self.fp, self.hex, self.rfile, self.wfile) - - def write(self, lines): - write_raw(self.fp, lines) diff --git a/pathod/libpathod/pathoc.py b/pathod/libpathod/pathoc.py deleted file mode 100644 index c0a33b62..00000000 --- a/pathod/libpathod/pathoc.py +++ /dev/null @@ -1,534 +0,0 @@ -import contextlib -import sys -import os -import itertools -import hashlib -import Queue -import random -import select -import time -import threading - -import OpenSSL.crypto -import six - -from netlib import tcp, http, certutils, websockets, socks -from netlib.exceptions import HttpException, TcpDisconnect, TcpTimeout, TlsException, TcpException, \ - NetlibException -from netlib.http import http1, http2 - -import language.http -import language.websockets -from . import utils, log - -import logging -from netlib.tutils import treq - -logging.getLogger("hpack").setLevel(logging.WARNING) - - -class PathocError(Exception): - pass - - -class SSLInfo(object): - - def __init__(self, certchain, cipher, alp): - self.certchain, self.cipher, self.alp = certchain, cipher, alp - - def __str__(self): - parts = [ - "Application Layer Protocol: %s" % self.alp, - "Cipher: %s, %s bit, %s" % self.cipher, - "SSL certificate chain:" - ] - for i in self.certchain: - parts.append("\tSubject: ") - for cn in i.get_subject().get_components(): - parts.append("\t\t%s=%s" % cn) - parts.append("\tIssuer: ") - for cn in i.get_issuer().get_components(): - parts.append("\t\t%s=%s" % cn) - parts.extend( - [ - "\tVersion: %s" % i.get_version(), - "\tValidity: %s - %s" % ( - i.get_notBefore(), i.get_notAfter() - ), - "\tSerial: %s" % i.get_serial_number(), - "\tAlgorithm: %s" % i.get_signature_algorithm() - ] - ) - pk = i.get_pubkey() - types = { - OpenSSL.crypto.TYPE_RSA: "RSA", - OpenSSL.crypto.TYPE_DSA: "DSA" - } - t = types.get(pk.type(), "Uknown") - parts.append("\tPubkey: %s bit %s" % (pk.bits(), t)) - s = certutils.SSLCert(i) - if s.altnames: - parts.append("\tSANs: %s" % " ".join(s.altnames)) - return "\n".join(parts) - - - -class WebsocketFrameReader(threading.Thread): - - def __init__( - self, - rfile, - logfp, - showresp, - hexdump, - ws_read_limit, - timeout - ): - threading.Thread.__init__(self) - self.timeout = timeout - self.ws_read_limit = ws_read_limit - self.logfp = logfp - self.showresp = showresp - self.hexdump = hexdump - self.rfile = rfile - self.terminate = Queue.Queue() - self.frames_queue = Queue.Queue() - self.logger = log.ConnectionLogger( - self.logfp, - self.hexdump, - rfile if showresp else None, - None - ) - - @contextlib.contextmanager - def terminator(self): - yield - self.frames_queue.put(None) - - def run(self): - starttime = time.time() - with self.terminator(): - while True: - if self.ws_read_limit == 0: - return - r, _, _ = select.select([self.rfile], [], [], 0.05) - delta = time.time() - starttime - if not r and self.timeout and delta > self.timeout: - return - try: - self.terminate.get_nowait() - return - except Queue.Empty: - pass - for rfile in r: - with self.logger.ctx() as log: - try: - frm = websockets.Frame.from_file(self.rfile) - except TcpDisconnect: - return - self.frames_queue.put(frm) - log("<< %s" % frm.header.human_readable()) - if self.ws_read_limit is not None: - self.ws_read_limit -= 1 - starttime = time.time() - - -class Pathoc(tcp.TCPClient): - - def __init__( - self, - address, - - # SSL - ssl=None, - sni=None, - ssl_version=tcp.SSL_DEFAULT_METHOD, - ssl_options=tcp.SSL_DEFAULT_OPTIONS, - clientcert=None, - ciphers=None, - - # HTTP/2 - use_http2=False, - http2_skip_connection_preface=False, - http2_framedump=False, - - # Websockets - ws_read_limit=None, - - # Network - timeout=None, - - # Output control - showreq=False, - showresp=False, - explain=False, - hexdump=False, - ignorecodes=(), - ignoretimeout=False, - showsummary=False, - fp=sys.stdout - ): - """ - spec: A request specification - showreq: Print requests - showresp: Print responses - explain: Print request explanation - showssl: Print info on SSL connection - hexdump: When printing requests or responses, use hex dump output - showsummary: Show a summary of requests - ignorecodes: Sequence of return codes to ignore - """ - tcp.TCPClient.__init__(self, address) - - self.ssl, self.sni = ssl, sni - self.clientcert = clientcert - self.ssl_version = ssl_version - self.ssl_options = ssl_options - self.ciphers = ciphers - self.sslinfo = None - - self.use_http2 = use_http2 - self.http2_skip_connection_preface = http2_skip_connection_preface - self.http2_framedump = http2_framedump - - self.ws_read_limit = ws_read_limit - - self.timeout = timeout - - self.showreq = showreq - self.showresp = showresp - self.explain = explain - self.hexdump = hexdump - self.ignorecodes = ignorecodes - self.ignoretimeout = ignoretimeout - self.showsummary = showsummary - self.fp = fp - - self.ws_framereader = None - - if self.use_http2: - if not tcp.HAS_ALPN: # pragma: nocover - log.write_raw( - self.fp, - "HTTP/2 requires ALPN support. " - "Please use OpenSSL >= 1.0.2. " - "Pathoc might not be working as expected without ALPN." - ) - self.protocol = http2.HTTP2Protocol(self, dump_frames=self.http2_framedump) - else: - self.protocol = http1 - - self.settings = language.Settings( - is_client=True, - staticdir=os.getcwd(), - unconstrained_file_access=True, - request_host=self.address.host, - protocol=self.protocol, - ) - - def http_connect(self, connect_to): - self.wfile.write( - 'CONNECT %s:%s HTTP/1.1\r\n' % tuple(connect_to) + - '\r\n' - ) - self.wfile.flush() - try: - resp = self.protocol.read_response(self.rfile, treq(method="CONNECT")) - if resp.status_code != 200: - raise HttpException("Unexpected status code: %s" % resp.status_code) - except HttpException as e: - six.reraise(PathocError, PathocError( - "Proxy CONNECT failed: %s" % repr(e) - )) - - def socks_connect(self, connect_to): - try: - client_greet = socks.ClientGreeting(socks.VERSION.SOCKS5, [socks.METHOD.NO_AUTHENTICATION_REQUIRED]) - client_greet.to_file(self.wfile) - self.wfile.flush() - - server_greet = socks.ServerGreeting.from_file(self.rfile) - server_greet.assert_socks5() - if server_greet.method != socks.METHOD.NO_AUTHENTICATION_REQUIRED: - raise socks.SocksError( - socks.METHOD.NO_ACCEPTABLE_METHODS, - "pathoc only supports SOCKS without authentication" - ) - - connect_request = socks.Message( - socks.VERSION.SOCKS5, - socks.CMD.CONNECT, - socks.ATYP.DOMAINNAME, - tcp.Address.wrap(connect_to) - ) - connect_request.to_file(self.wfile) - self.wfile.flush() - - connect_reply = socks.Message.from_file(self.rfile) - connect_reply.assert_socks5() - if connect_reply.msg != socks.REP.SUCCEEDED: - raise socks.SocksError( - connect_reply.msg, - "SOCKS server error" - ) - except (socks.SocksError, TcpDisconnect) as e: - raise PathocError(str(e)) - - def connect(self, connect_to=None, showssl=False, fp=sys.stdout): - """ - connect_to: A (host, port) tuple, which will be connected to with - an HTTP CONNECT request. - """ - if self.use_http2 and not self.ssl: - raise NotImplementedError("HTTP2 without SSL is not supported.") - - tcp.TCPClient.connect(self) - - if connect_to: - self.http_connect(connect_to) - - self.sslinfo = None - if self.ssl: - try: - alpn_protos = [b'http/1.1'] - if self.use_http2: - alpn_protos.append(b'h2') - - self.convert_to_ssl( - sni=self.sni, - cert=self.clientcert, - method=self.ssl_version, - options=self.ssl_options, - cipher_list=self.ciphers, - alpn_protos=alpn_protos - ) - except TlsException as v: - raise PathocError(str(v)) - - self.sslinfo = SSLInfo( - self.connection.get_peer_cert_chain(), - self.get_current_cipher(), - self.get_alpn_proto_negotiated() - ) - if showssl: - print >> fp, str(self.sslinfo) - - if self.use_http2: - self.protocol.check_alpn() - if not self.http2_skip_connection_preface: - self.protocol.perform_client_connection_preface() - - if self.timeout: - self.settimeout(self.timeout) - - def stop(self): - if self.ws_framereader: - self.ws_framereader.terminate.put(None) - - def wait(self, timeout=0.01, finish=True): - """ - A generator that yields frames until Pathoc terminates. - - timeout: If specified None may be yielded instead if timeout is - reached. If timeout is None, wait forever. If timeout is 0, return - immedately if nothing is on the queue. - - finish: If true, consume messages until the reader shuts down. - Otherwise, return None on timeout. - """ - if self.ws_framereader: - while True: - try: - frm = self.ws_framereader.frames_queue.get( - timeout=timeout, - block=True if timeout != 0 else False - ) - except Queue.Empty: - if finish: - continue - else: - return - if frm is None: - self.ws_framereader.join() - return - yield frm - - def websocket_send_frame(self, r): - """ - Sends a single websocket frame. - """ - logger = log.ConnectionLogger( - self.fp, - self.hexdump, - None, - self.wfile if self.showreq else None, - ) - with logger.ctx() as lg: - lg(">> %s" % r) - language.serve(r, self.wfile, self.settings) - self.wfile.flush() - - def websocket_start(self, r): - """ - Performs an HTTP request, and attempts to drop into websocket - connection. - """ - resp = self.http(r) - if resp.status_code == 101: - self.ws_framereader = WebsocketFrameReader( - self.rfile, - self.fp, - self.showresp, - self.hexdump, - self.ws_read_limit, - self.timeout - ) - self.ws_framereader.start() - return resp - - def http(self, r): - """ - Performs a single request. - - r: A language.http.Request object, or a string representing one - request. - - Returns Response if we have a non-ignored response. - - May raise a NetlibException - """ - logger = log.ConnectionLogger( - self.fp, - self.hexdump, - self.rfile if self.showresp else None, - self.wfile if self.showreq else None, - ) - with logger.ctx() as lg: - lg(">> %s" % r) - resp, req = None, None - try: - req = language.serve(r, self.wfile, self.settings) - self.wfile.flush() - - resp = self.protocol.read_response(self.rfile, treq(method=req["method"].encode())) - resp.sslinfo = self.sslinfo - except HttpException as v: - lg("Invalid server response: %s" % v) - raise - except TcpTimeout: - if self.ignoretimeout: - lg("Timeout (ignored)") - return None - lg("Timeout") - raise - finally: - if resp: - lg("<< %s %s: %s bytes" % ( - resp.status_code, utils.xrepr(resp.msg), len(resp.content) - )) - if resp.status_code in self.ignorecodes: - lg.suppress() - return resp - - def request(self, r): - """ - Performs a single request. - - r: A language.message.Messsage object, or a string representing - one. - - Returns Response if we have a non-ignored response. - - May raise a NetlibException - """ - if isinstance(r, basestring): - r = language.parse_pathoc(r, self.use_http2).next() - - if isinstance(r, language.http.Request): - if r.ws: - return self.websocket_start(r) - else: - return self.http(r) - elif isinstance(r, language.websockets.WebsocketFrame): - self.websocket_send_frame(r) - elif isinstance(r, language.http2.Request): - return self.http(r) - # elif isinstance(r, language.http2.Frame): - # TODO: do something - - -def main(args): # pragma: nocover - memo = set([]) - trycount = 0 - p = None - try: - cnt = 0 - while True: - if cnt == args.repeat and args.repeat != 0: - break - if args.wait and cnt != 0: - time.sleep(args.wait) - - cnt += 1 - playlist = itertools.chain(*args.requests) - if args.random: - playlist = random.choice(args.requests) - p = Pathoc( - (args.host, args.port), - ssl=args.ssl, - sni=args.sni, - ssl_version=args.ssl_version, - ssl_options=args.ssl_options, - clientcert=args.clientcert, - ciphers=args.ciphers, - use_http2=args.use_http2, - http2_skip_connection_preface=args.http2_skip_connection_preface, - http2_framedump=args.http2_framedump, - showreq=args.showreq, - showresp=args.showresp, - explain=args.explain, - hexdump=args.hexdump, - ignorecodes=args.ignorecodes, - timeout=args.timeout, - ignoretimeout=args.ignoretimeout, - showsummary=True - ) - trycount = 0 - try: - p.connect(args.connect_to, args.showssl) - except TcpException as v: - print >> sys.stderr, str(v) - continue - except PathocError as v: - print >> sys.stderr, str(v) - sys.exit(1) - for spec in playlist: - if args.explain or args.memo: - spec = spec.freeze(p.settings) - if args.memo: - h = hashlib.sha256(spec.spec()).digest() - if h not in memo: - trycount = 0 - memo.add(h) - else: - trycount += 1 - if trycount > args.memolimit: - print >> sys.stderr, "Memo limit exceeded..." - return - else: - continue - try: - ret = p.request(spec) - if ret and args.oneshot: - return - # We consume the queue when we can, so it doesn't build up. - for i_ in p.wait(timeout=0, finish=False): - pass - except NetlibException: - break - for i_ in p.wait(timeout=0.01, finish=True): - pass - except KeyboardInterrupt: - pass - if p: - p.stop() diff --git a/pathod/libpathod/pathoc_cmdline.py b/pathod/libpathod/pathoc_cmdline.py deleted file mode 100644 index bf827a9a..00000000 --- a/pathod/libpathod/pathoc_cmdline.py +++ /dev/null @@ -1,226 +0,0 @@ -import sys -import argparse -import os -import os.path - -from netlib import tcp -from netlib.http import user_agents -from . import pathoc, version, language - - -def args_pathoc(argv, stdout=sys.stdout, stderr=sys.stderr): - preparser = argparse.ArgumentParser(add_help=False) - preparser.add_argument( - "--show-uas", dest="showua", action="store_true", default=False, - help="Print user agent shortcuts and exit." - ) - pa = preparser.parse_known_args(argv)[0] - if pa.showua: - print >> stdout, "User agent strings:" - for i in user_agents.UASTRINGS: - print >> stdout, " ", i[1], i[0] - sys.exit(0) - - parser = argparse.ArgumentParser( - description='A perverse HTTP client.', parents=[preparser] - ) - parser.add_argument( - '--version', - action='version', - version="pathoc " + version.VERSION - ) - parser.add_argument( - "-c", dest="connect_to", type=str, default=False, - metavar="HOST:PORT", - help="Issue an HTTP CONNECT to connect to the specified host." - ) - parser.add_argument( - "--memo-limit", dest='memolimit', default=5000, type=int, metavar="N", - help='Stop if we do not find a valid request after N attempts.' - ) - parser.add_argument( - "-m", dest='memo', action="store_true", default=False, - help=""" - Remember specs, and never play the same one twice. Note that this - means requests have to be rendered in memory, which means that - large generated data can cause issues. - """ - ) - parser.add_argument( - "-n", dest='repeat', default=1, type=int, metavar="N", - help='Repeat N times. If 0 repeat for ever.' - ) - parser.add_argument( - "-w", dest='wait', default=0, type=float, metavar="N", - help='Wait N seconds between each request.' - ) - parser.add_argument( - "-r", dest="random", action="store_true", default=False, - help=""" - Select a random request from those specified. If this is not specified, - requests are all played in sequence. - """ - ) - parser.add_argument( - "-t", dest="timeout", type=int, default=None, - help="Connection timeout" - ) - parser.add_argument( - "--http2", dest="use_http2", action="store_true", default=False, - help='Perform all requests over a single HTTP/2 connection.' - ) - parser.add_argument( - "--http2-skip-connection-preface", - dest="http2_skip_connection_preface", - action="store_true", - default=False, - help='Skips the HTTP/2 connection preface before sending requests.') - - parser.add_argument( - 'host', type=str, - metavar="host[:port]", - help='Host and port to connect to' - ) - parser.add_argument( - 'requests', type=str, nargs="+", - help=""" - Request specification, or path to a file containing request - specifcations - """ - ) - - group = parser.add_argument_group( - 'SSL', - ) - group.add_argument( - "-s", dest="ssl", action="store_true", default=False, - help="Connect with SSL" - ) - group.add_argument( - "-C", dest="clientcert", type=str, default=False, - help="Path to a file containing client certificate and private key" - ) - group.add_argument( - "-i", dest="sni", type=str, default=False, - help="SSL Server Name Indication" - ) - group.add_argument( - "--ciphers", dest="ciphers", type=str, default=False, - help="SSL cipher specification" - ) - group.add_argument( - "--ssl-version", dest="ssl_version", type=str, default="secure", - choices=tcp.sslversion_choices.keys(), - help="Set supported SSL/TLS versions. " - "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." - ) - - group = parser.add_argument_group( - 'Controlling Output', - """ - Some of these options expand generated values for logging - if - you're generating large data, use them with caution. - """ - ) - group.add_argument( - "-I", dest="ignorecodes", type=str, default="", - help="Comma-separated list of response codes to ignore" - ) - group.add_argument( - "-S", dest="showssl", action="store_true", default=False, - help="Show info on SSL connection" - ) - group.add_argument( - "-e", dest="explain", action="store_true", default=False, - help="Explain requests" - ) - group.add_argument( - "-o", dest="oneshot", action="store_true", default=False, - help="Oneshot - exit after first non-ignored response" - ) - group.add_argument( - "-q", dest="showreq", action="store_true", default=False, - help="Print full request" - ) - group.add_argument( - "-p", dest="showresp", action="store_true", default=False, - help="Print full response" - ) - group.add_argument( - "-T", dest="ignoretimeout", action="store_true", default=False, - help="Ignore timeouts" - ) - group.add_argument( - "-x", dest="hexdump", action="store_true", default=False, - help="Output in hexdump format" - ) - group.add_argument( - "--http2-framedump", dest="http2_framedump", action="store_true", default=False, - help="Output all received & sent HTTP/2 frames" - ) - - args = parser.parse_args(argv[1:]) - - args.ssl_version, args.ssl_options = tcp.sslversion_choices[args.ssl_version] - - args.port = None - if ":" in args.host: - h, p = args.host.rsplit(":", 1) - try: - p = int(p) - except ValueError: - return parser.error("Invalid port in host spec: %s" % args.host) - args.host = h - args.port = p - - if args.port is None: - args.port = 443 if args.ssl else 80 - - try: - args.ignorecodes = [int(i) for i in args.ignorecodes.split(",") if i] - except ValueError: - return parser.error( - "Invalid return code specification: %s" % - args.ignorecodes) - - if args.connect_to: - parts = args.connect_to.split(":") - if len(parts) != 2: - return parser.error( - "Invalid CONNECT specification: %s" % - args.connect_to) - try: - parts[1] = int(parts[1]) - except ValueError: - return parser.error( - "Invalid CONNECT specification: %s" % - args.connect_to) - args.connect_to = parts - else: - args.connect_to = None - - if args.http2_skip_connection_preface: - args.use_http2 = True - - if args.use_http2: - args.ssl = True - - reqs = [] - for r in args.requests: - if os.path.isfile(r): - data = open(r).read() - r = data - try: - reqs.append(language.parse_pathoc(r, args.use_http2)) - except language.ParseException as v: - print >> stderr, "Error parsing request spec: %s" % v.msg - print >> stderr, v.marked() - sys.exit(1) - args.requests = reqs - - return args - - -def go_pathoc(): # pragma: nocover - args = args_pathoc(sys.argv) - pathoc.main(args) diff --git a/pathod/libpathod/pathod.py b/pathod/libpathod/pathod.py deleted file mode 100644 index 55e75074..00000000 --- a/pathod/libpathod/pathod.py +++ /dev/null @@ -1,503 +0,0 @@ -import copy -import logging -import os -import sys -import threading -import urllib - -from netlib import tcp, http, certutils, websockets -from netlib.exceptions import HttpException, HttpReadDisconnect, TcpTimeout, TcpDisconnect, \ - TlsException - -from . import version, app, language, utils, log, protocols -import language.http -import language.actions -import language.exceptions -import language.websockets - - -DEFAULT_CERT_DOMAIN = "pathod.net" -CONFDIR = "~/.mitmproxy" -CERTSTORE_BASENAME = "mitmproxy" -CA_CERT_NAME = "mitmproxy-ca.pem" -DEFAULT_CRAFT_ANCHOR = "/p/" - -logger = logging.getLogger('pathod') - - -class PathodError(Exception): - pass - - -class SSLOptions(object): - def __init__( - self, - confdir=CONFDIR, - cn=None, - sans=(), - not_after_connect=None, - request_client_cert=False, - ssl_version=tcp.SSL_DEFAULT_METHOD, - ssl_options=tcp.SSL_DEFAULT_OPTIONS, - ciphers=None, - certs=None, - alpn_select=b'h2', - ): - self.confdir = confdir - self.cn = cn - self.sans = sans - self.not_after_connect = not_after_connect - self.request_client_cert = request_client_cert - self.ssl_version = ssl_version - self.ssl_options = ssl_options - self.ciphers = ciphers - self.alpn_select = alpn_select - self.certstore = certutils.CertStore.from_store( - os.path.expanduser(confdir), - CERTSTORE_BASENAME - ) - for i in certs or []: - self.certstore.add_cert_file(*i) - - def get_cert(self, name): - if self.cn: - name = self.cn - elif not name: - name = DEFAULT_CERT_DOMAIN - return self.certstore.get_cert(name, self.sans) - - -class PathodHandler(tcp.BaseHandler): - wbufsize = 0 - sni = None - - def __init__( - self, - connection, - address, - server, - logfp, - settings, - http2_framedump=False - ): - tcp.BaseHandler.__init__(self, connection, address, server) - self.logfp = logfp - self.settings = copy.copy(settings) - self.protocol = None - self.use_http2 = False - self.http2_framedump = http2_framedump - - def handle_sni(self, connection): - self.sni = connection.get_servername() - - def http_serve_crafted(self, crafted, logctx): - error, crafted = self.server.check_policy( - crafted, self.settings - ) - if error: - err = self.make_http_error_response(error) - language.serve(err, self.wfile, self.settings) - return None, dict( - type="error", - msg=error - ) - - if self.server.explain and not hasattr(crafted, 'is_error_response'): - crafted = crafted.freeze(self.settings) - logctx(">> Spec: %s" % crafted.spec()) - - response_log = language.serve( - crafted, - self.wfile, - self.settings - ) - if response_log["disconnect"]: - return None, response_log - return self.handle_http_request, response_log - - - def handle_http_request(self, logger): - """ - Returns a (handler, log) tuple. - - handler: Handler for the next request, or None to disconnect - log: A dictionary, or None - """ - with logger.ctx() as lg: - try: - req = self.protocol.read_request(self.rfile) - except HttpReadDisconnect: - return None, None - except HttpException as s: - s = str(s) - lg(s) - return None, dict(type="error", msg=s) - - if req.method == 'CONNECT': - return self.protocol.handle_http_connect([req.host, req.port, req.http_version], lg) - - method = req.method - path = req.path - http_version = req.http_version - headers = req.headers - body = req.content - - clientcert = None - if self.clientcert: - clientcert = dict( - cn=self.clientcert.cn, - subject=self.clientcert.subject, - serial=self.clientcert.serial, - notbefore=self.clientcert.notbefore.isoformat(), - notafter=self.clientcert.notafter.isoformat(), - keyinfo=self.clientcert.keyinfo, - ) - - retlog = dict( - type="crafted", - protocol="http", - request=dict( - path=path, - method=method, - headers=headers.fields, - http_version=http_version, - sni=self.sni, - remote_address=self.address(), - clientcert=clientcert, - ), - cipher=None, - ) - if self.ssl_established: - retlog["cipher"] = self.get_current_cipher() - - m = utils.MemBool() - websocket_key = websockets.WebsocketsProtocol.check_client_handshake(headers) - self.settings.websocket_key = websocket_key - - # If this is a websocket initiation, we respond with a proper - # server response, unless over-ridden. - if websocket_key: - anchor_gen = language.parse_pathod("ws") - else: - anchor_gen = None - - for regex, spec in self.server.anchors: - if regex.match(path): - anchor_gen = language.parse_pathod(spec, self.use_http2) - break - else: - if m(path.startswith(self.server.craftanchor)): - spec = urllib.unquote(path)[len(self.server.craftanchor):] - if spec: - try: - anchor_gen = language.parse_pathod(spec, self.use_http2) - except language.ParseException as v: - lg("Parse error: %s" % v.msg) - anchor_gen = iter([self.make_http_error_response( - "Parse Error", - "Error parsing response spec: %s\n" % ( - v.msg + v.marked() - ) - )]) - else: - if self.use_http2: - anchor_gen = iter([self.make_http_error_response( - "Spec Error", - "HTTP/2 only supports request/response with the craft anchor point: %s" % - self.server.craftanchor - )]) - - if anchor_gen: - spec = anchor_gen.next() - - if self.use_http2 and isinstance(spec, language.http2.Response): - spec.stream_id = req.stream_id - - lg("crafting spec: %s" % spec) - nexthandler, retlog["response"] = self.http_serve_crafted( - spec, - lg - ) - if nexthandler and websocket_key: - self.protocol = protocols.websockets.WebsocketsProtocol(self) - return self.protocol.handle_websocket, retlog - else: - return nexthandler, retlog - else: - return self.protocol.handle_http_app(method, path, headers, body, lg) - - def make_http_error_response(self, reason, body=None): - resp = self.protocol.make_error_response(reason, body) - resp.is_error_response = True - return resp - - def handle(self): - self.settimeout(self.server.timeout) - - if self.server.ssl: - try: - cert, key, _ = self.server.ssloptions.get_cert(None) - self.convert_to_ssl( - cert, - key, - handle_sni=self.handle_sni, - request_client_cert=self.server.ssloptions.request_client_cert, - cipher_list=self.server.ssloptions.ciphers, - method=self.server.ssloptions.ssl_version, - options=self.server.ssloptions.ssl_options, - alpn_select=self.server.ssloptions.alpn_select, - ) - except TlsException as v: - s = str(v) - self.server.add_log( - dict( - type="error", - msg=s - ) - ) - log.write_raw(self.logfp, s) - return - - alp = self.get_alpn_proto_negotiated() - if alp == b'h2': - self.protocol = protocols.http2.HTTP2Protocol(self) - self.use_http2 = True - - if not self.protocol: - self.protocol = protocols.http.HTTPProtocol(self) - - lr = self.rfile if self.server.logreq else None - lw = self.wfile if self.server.logresp else None - logger = log.ConnectionLogger(self.logfp, self.server.hexdump, lr, lw) - - self.settings.protocol = self.protocol - - handler = self.handle_http_request - - while not self.finished: - handler, l = handler(logger) - if l: - self.addlog(l) - if not handler: - return - - def addlog(self, log): - # FIXME: The bytes in the log should not be escaped. We do this at the - # moment because JSON encoding can't handle binary data, and I don't - # want to base64 everything. - if self.server.logreq: - encoded_bytes = self.rfile.get_log().encode("string_escape") - log["request_bytes"] = encoded_bytes - if self.server.logresp: - encoded_bytes = self.wfile.get_log().encode("string_escape") - log["response_bytes"] = encoded_bytes - self.server.add_log(log) - - -class Pathod(tcp.TCPServer): - LOGBUF = 500 - - def __init__( - self, - addr, - ssl=False, - ssloptions=None, - craftanchor=DEFAULT_CRAFT_ANCHOR, - staticdir=None, - anchors=(), - sizelimit=None, - noweb=False, - nocraft=False, - noapi=False, - nohang=False, - timeout=None, - logreq=False, - logresp=False, - explain=False, - hexdump=False, - http2_framedump=False, - webdebug=False, - logfp=sys.stdout, - ): - """ - addr: (address, port) tuple. If port is 0, a free port will be - automatically chosen. - ssloptions: an SSLOptions object. - craftanchor: URL prefix specifying the path under which to anchor - response generation. - staticdir: path to a directory of static resources, or None. - anchors: List of (regex object, language.Request object) tuples, or - None. - sizelimit: Limit size of served data. - nocraft: Disable response crafting. - noapi: Disable the API. - nohang: Disable pauses. - """ - tcp.TCPServer.__init__(self, addr) - self.ssl = ssl - self.ssloptions = ssloptions or SSLOptions() - self.staticdir = staticdir - self.craftanchor = craftanchor - self.sizelimit = sizelimit - self.noweb, self.nocraft = noweb, nocraft - self.noapi, self.nohang = noapi, nohang - self.timeout, self.logreq = timeout, logreq - self.logresp, self.hexdump = logresp, hexdump - self.http2_framedump = http2_framedump - self.explain = explain - self.logfp = logfp - - self.app = app.make_app(noapi, webdebug) - self.app.config["pathod"] = self - self.log = [] - self.logid = 0 - self.anchors = anchors - - self.settings = language.Settings( - staticdir=self.staticdir - ) - - def check_policy(self, req, settings): - """ - A policy check that verifies the request size is within limits. - """ - if self.nocraft: - return "Crafting disabled.", None - try: - req = req.resolve(settings) - l = req.maximum_length(settings) - except language.FileAccessDenied: - return "File access denied.", None - if self.sizelimit and l > self.sizelimit: - return "Response too large.", None - pauses = [isinstance(i, language.actions.PauseAt) for i in req.actions] - if self.nohang and any(pauses): - return "Pauses have been disabled.", None - return None, req - - def handle_client_connection(self, request, client_address): - h = PathodHandler( - request, - client_address, - self, - self.logfp, - self.settings, - self.http2_framedump, - ) - try: - h.handle() - h.finish() - except TcpDisconnect: # pragma: no cover - log.write_raw(self.logfp, "Disconnect") - self.add_log( - dict( - type="error", - msg="Disconnect" - ) - ) - return - except TcpTimeout: - log.write_raw(self.logfp, "Timeout") - self.add_log( - dict( - type="timeout", - ) - ) - return - - def add_log(self, d): - if not self.noapi: - lock = threading.Lock() - with lock: - d["id"] = self.logid - self.log.insert(0, d) - if len(self.log) > self.LOGBUF: - self.log.pop() - self.logid += 1 - return d["id"] - - def clear_log(self): - lock = threading.Lock() - with lock: - self.log = [] - - def log_by_id(self, identifier): - for i in self.log: - if i["id"] == identifier: - return i - - def get_log(self): - return self.log - - -def main(args): # pragma: nocover - ssloptions = SSLOptions( - cn=args.cn, - confdir=args.confdir, - not_after_connect=args.ssl_not_after_connect, - ciphers=args.ciphers, - ssl_version=args.ssl_version, - ssl_options=args.ssl_options, - certs=args.ssl_certs, - sans=args.sans, - ) - - root = logging.getLogger() - if root.handlers: - for handler in root.handlers: - root.removeHandler(handler) - - log = logging.getLogger('pathod') - log.setLevel(logging.DEBUG) - fmt = logging.Formatter( - '%(asctime)s: %(message)s', - datefmt='%d-%m-%y %H:%M:%S', - ) - if args.logfile: - fh = logging.handlers.WatchedFileHandler(args.logfile) - fh.setFormatter(fmt) - log.addHandler(fh) - if not args.daemonize: - sh = logging.StreamHandler() - sh.setFormatter(fmt) - log.addHandler(sh) - - try: - pd = Pathod( - (args.address, args.port), - craftanchor=args.craftanchor, - ssl=args.ssl, - ssloptions=ssloptions, - staticdir=args.staticdir, - anchors=args.anchors, - sizelimit=args.sizelimit, - noweb=args.noweb, - nocraft=args.nocraft, - noapi=args.noapi, - nohang=args.nohang, - timeout=args.timeout, - logreq=args.logreq, - logresp=args.logresp, - hexdump=args.hexdump, - http2_framedump=args.http2_framedump, - explain=args.explain, - webdebug=args.webdebug - ) - except PathodError as v: - print >> sys.stderr, "Error: %s" % v - sys.exit(1) - except language.FileAccessDenied as v: - print >> sys.stderr, "Error: %s" % v - - if args.daemonize: - utils.daemonize() - - try: - print "%s listening on %s:%s" % ( - version.NAMEVERSION, - pd.address.host, - pd.address.port - ) - pd.serve_forever() - except KeyboardInterrupt: - pass diff --git a/pathod/libpathod/pathod_cmdline.py b/pathod/libpathod/pathod_cmdline.py deleted file mode 100644 index c9272249..00000000 --- a/pathod/libpathod/pathod_cmdline.py +++ /dev/null @@ -1,231 +0,0 @@ -import sys -import argparse -import os -import os.path -import re - -from netlib import tcp -from . import pathod, version, utils - - -def args_pathod(argv, stdout_=sys.stdout, stderr_=sys.stderr): - parser = argparse.ArgumentParser( - description='A pathological HTTP/S daemon.' - ) - parser.add_argument( - '--version', - action='version', - version="pathod " + version.VERSION - ) - parser.add_argument( - "-p", - dest='port', - default=9999, - type=int, - help='Port. Specify 0 to pick an arbitrary empty port. (9999)' - ) - parser.add_argument( - "-l", - dest='address', - default="127.0.0.1", - type=str, - help='Listening address. (127.0.0.1)' - ) - parser.add_argument( - "-a", - dest='anchors', - default=[], - type=str, - action="append", - metavar="ANCHOR", - help=""" - Add an anchor. Specified as a string with the form - pattern=spec or pattern=filepath, where pattern is a regular - expression. - """ - ) - parser.add_argument( - "-c", dest='craftanchor', default=pathod.DEFAULT_CRAFT_ANCHOR, type=str, - help=""" - URL path specifying prefix for URL crafting - commands. (%s) - """%pathod.DEFAULT_CRAFT_ANCHOR - ) - parser.add_argument( - "--confdir", - action="store", type = str, dest="confdir", default='~/.mitmproxy', - help = "Configuration directory. (~/.mitmproxy)" - ) - parser.add_argument( - "-d", dest='staticdir', default=None, type=str, - help='Directory for static files.' - ) - parser.add_argument( - "-D", dest='daemonize', default=False, action="store_true", - help='Daemonize.' - ) - parser.add_argument( - "-t", dest="timeout", type=int, default=None, - help="Connection timeout" - ) - parser.add_argument( - "--limit-size", - dest='sizelimit', - default=None, - type=str, - help='Size limit of served responses. Understands size suffixes, i.e. 100k.') - parser.add_argument( - "--noapi", dest='noapi', default=False, action="store_true", - help='Disable API.' - ) - parser.add_argument( - "--nohang", dest='nohang', default=False, action="store_true", - help='Disable pauses during crafted response generation.' - ) - parser.add_argument( - "--noweb", dest='noweb', default=False, action="store_true", - help='Disable both web interface and API.' - ) - parser.add_argument( - "--nocraft", - dest='nocraft', - default=False, - action="store_true", - help='Disable response crafting. If anchors are specified, they still work.') - parser.add_argument( - "--webdebug", dest='webdebug', default=False, action="store_true", - help='Debugging mode for the web app (dev only).' - ) - - group = parser.add_argument_group( - 'SSL', - ) - group.add_argument( - "-s", dest='ssl', default=False, action="store_true", - help='Run in HTTPS mode.' - ) - group.add_argument( - "--cn", - dest="cn", - type=str, - default=None, - help="CN for generated SSL certs. Default: %s" % - pathod.DEFAULT_CERT_DOMAIN) - group.add_argument( - "-C", dest='ssl_not_after_connect', default=False, action="store_true", - help="Don't expect SSL after a CONNECT request." - ) - group.add_argument( - "--cert", dest='ssl_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. Can - be passed multiple times. - """ - ) - group.add_argument( - "--ciphers", dest="ciphers", type=str, default=False, - help="SSL cipher specification" - ) - group.add_argument( - "--san", dest="sans", type=str, default=[], action="append", - metavar="SAN", - help=""" - Subject Altnernate Name to add to the server certificate. - May be passed multiple times. - """ - ) - group.add_argument( - "--ssl-version", dest="ssl_version", type=str, default="secure", - choices=tcp.sslversion_choices.keys(), - help="Set supported SSL/TLS versions. " - "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure, which is TLS1.0+." - ) - - group = parser.add_argument_group( - 'Controlling Logging', - """ - Some of these options expand generated values for logging - if - you're generating large data, use them with caution. - """ - ) - group.add_argument( - "-e", dest="explain", action="store_true", default=False, - help="Explain responses" - ) - group.add_argument( - "-f", dest='logfile', default=None, type=str, - help='Log to file.' - ) - group.add_argument( - "-q", dest="logreq", action="store_true", default=False, - help="Log full request" - ) - group.add_argument( - "-r", dest="logresp", action="store_true", default=False, - help="Log full response" - ) - group.add_argument( - "-x", dest="hexdump", action="store_true", default=False, - help="Log request/response in hexdump format" - ) - group.add_argument( - "--http2-framedump", dest="http2_framedump", action="store_true", default=False, - help="Output all received & sent HTTP/2 frames" - ) - - - args = parser.parse_args(argv[1:]) - - args.ssl_version, args.ssl_options = tcp.sslversion_choices[args.ssl_version] - - certs = [] - for i in args.ssl_certs: - parts = i.split("=", 1) - if len(parts) == 1: - parts = ["*", parts[0]] - parts[1] = os.path.expanduser(parts[1]) - if not os.path.isfile(parts[1]): - return parser.error( - "Certificate file does not exist: %s" % - parts[1]) - certs.append(parts) - args.ssl_certs = certs - - alst = [] - for i in args.anchors: - parts = utils.parse_anchor_spec(i) - if not parts: - return parser.error("Invalid anchor specification: %s" % i) - alst.append(parts) - args.anchors = alst - - sizelimit = None - if args.sizelimit: - try: - sizelimit = utils.parse_size(args.sizelimit) - except ValueError as v: - return parser.error(v) - args.sizelimit = sizelimit - - anchors = [] - for patt, spec in args.anchors: - if os.path.isfile(spec): - data = open(spec).read() - spec = data - try: - arex = re.compile(patt) - except re.error: - return parser.error("Invalid regex in anchor: %s" % patt) - anchors.append((arex, spec)) - args.anchors = anchors - - return args - - -def go_pathod(): # pragma: nocover - args = args_pathod(sys.argv) - pathod.main(args) diff --git a/pathod/libpathod/protocols/__init__.py b/pathod/libpathod/protocols/__init__.py deleted file mode 100644 index 1a8c7dab..00000000 --- a/pathod/libpathod/protocols/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import http, http2, websockets diff --git a/pathod/libpathod/protocols/http.py b/pathod/libpathod/protocols/http.py deleted file mode 100644 index 1f1765cb..00000000 --- a/pathod/libpathod/protocols/http.py +++ /dev/null @@ -1,71 +0,0 @@ -from netlib import tcp, wsgi -from netlib.exceptions import HttpReadDisconnect, TlsException -from netlib.http import http1, Request -from .. import version, language - - -class HTTPProtocol(object): - def __init__(self, pathod_handler): - self.pathod_handler = pathod_handler - - def make_error_response(self, reason, body): - return language.http.make_error_response(reason, body) - - def handle_http_app(self, method, path, headers, body, lg): - """ - Handle a request to the built-in app. - """ - if self.pathod_handler.server.noweb: - crafted = self.pathod_handler.make_http_error_response("Access Denied") - language.serve(crafted, self.pathod_handler.wfile, self.pathod_handler.settings) - return None, dict( - type="error", - msg="Access denied: web interface disabled" - ) - lg("app: %s %s" % (method, path)) - req = wsgi.Request("http", method, path, b"HTTP/1.1", headers, body) - flow = wsgi.Flow(self.pathod_handler.address, req) - sn = self.pathod_handler.connection.getsockname() - a = wsgi.WSGIAdaptor( - self.pathod_handler.server.app, - sn[0], - self.pathod_handler.server.address.port, - version.NAMEVERSION - ) - a.serve(flow, self.pathod_handler.wfile) - return self.pathod_handler.handle_http_request, None - - def handle_http_connect(self, connect, lg): - """ - Handle a CONNECT request. - """ - - self.pathod_handler.wfile.write( - 'HTTP/1.1 200 Connection established\r\n' + - ('Proxy-agent: %s\r\n' % version.NAMEVERSION) + - '\r\n' - ) - self.pathod_handler.wfile.flush() - if not self.pathod_handler.server.ssloptions.not_after_connect: - try: - cert, key, chain_file_ = self.pathod_handler.server.ssloptions.get_cert( - connect[0] - ) - self.pathod_handler.convert_to_ssl( - cert, - key, - handle_sni=self.pathod_handler.handle_sni, - request_client_cert=self.pathod_handler.server.ssloptions.request_client_cert, - cipher_list=self.pathod_handler.server.ssloptions.ciphers, - method=self.pathod_handler.server.ssloptions.ssl_version, - options=self.pathod_handler.server.ssloptions.ssl_options, - alpn_select=self.pathod_handler.server.ssloptions.alpn_select, - ) - except TlsException as v: - s = str(v) - lg(s) - return None, dict(type="error", msg=s) - return self.pathod_handler.handle_http_request, None - - def read_request(self, lg=None): - return http1.read_request(self.pathod_handler.rfile) diff --git a/pathod/libpathod/protocols/http2.py b/pathod/libpathod/protocols/http2.py deleted file mode 100644 index a098a14e..00000000 --- a/pathod/libpathod/protocols/http2.py +++ /dev/null @@ -1,20 +0,0 @@ -from netlib.http import http2 -from .. import version, app, language, utils, log - -class HTTP2Protocol: - - def __init__(self, pathod_handler): - self.pathod_handler = pathod_handler - self.wire_protocol = http2.HTTP2Protocol( - self.pathod_handler, is_server=True, dump_frames=self.pathod_handler.http2_framedump - ) - - def make_error_response(self, reason, body): - return language.http2.make_error_response(reason, body) - - def read_request(self, lg=None): - self.wire_protocol.perform_server_connection_preface() - return self.wire_protocol.read_request(self.pathod_handler.rfile) - - def assemble(self, message): - return self.wire_protocol.assemble(message) diff --git a/pathod/libpathod/protocols/websockets.py b/pathod/libpathod/protocols/websockets.py deleted file mode 100644 index 134d27bc..00000000 --- a/pathod/libpathod/protocols/websockets.py +++ /dev/null @@ -1,56 +0,0 @@ -import time - -from netlib import websockets -from .. import language -from netlib.exceptions import NetlibException - - -class WebsocketsProtocol: - - def __init__(self, pathod_handler): - self.pathod_handler = pathod_handler - - def handle_websocket(self, logger): - while True: - with logger.ctx() as lg: - started = time.time() - try: - frm = websockets.Frame.from_file(self.pathod_handler.rfile) - except NetlibException as e: - lg("Error reading websocket frame: %s" % e) - break - ended = time.time() - lg(frm.human_readable()) - retlog = dict( - type="inbound", - protocol="websockets", - started=started, - duration=ended - started, - frame=dict( - ), - cipher=None, - ) - if self.pathod_handler.ssl_established: - retlog["cipher"] = self.pathod_handler.get_current_cipher() - self.pathod_handler.addlog(retlog) - ld = language.websockets.NESTED_LEADER - if frm.payload.startswith(ld): - nest = frm.payload[len(ld):] - try: - wf_gen = language.parse_websocket_frame(nest) - except language.exceptions.ParseException as v: - logger.write( - "Parse error in reflected frame specifcation:" - " %s" % v.msg - ) - return None, None - for frm in wf_gen: - with logger.ctx() as lg: - frame_log = language.serve( - frm, - self.pathod_handler.wfile, - self.pathod_handler.settings - ) - lg("crafting websocket spec: %s" % frame_log["spec"]) - self.pathod_handler.addlog(frame_log) - return self.handle_websocket, None diff --git a/pathod/libpathod/static/bootstrap.min.css b/pathod/libpathod/static/bootstrap.min.css deleted file mode 100644 index 2e79d91a..00000000 --- a/pathod/libpathod/static/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/pathod/libpathod/static/bootstrap.min.js b/pathod/libpathod/static/bootstrap.min.js deleted file mode 100644 index 14356981..00000000 --- a/pathod/libpathod/static/bootstrap.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! -* Bootstrap.js by @fat & @mdo -* Copyright 2012 Twitter, Inc. -* http://www.apache.org/licenses/LICENSE-2.0.txt -*/ -!function(a){a(function(){"use strict",a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=c,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},to:function(b){var c=this.$element.find(".active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(a){return a||(this.paused=!0),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j=a.Event("slide");this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h]();if(e.hasClass("active"))return;if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c);e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):typeof c=="string"||(c=f.slide)?e[c]():f.interval&&e.cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning)return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning)return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){a(b).parent().removeClass("open")}"use strict";var b='[data-toggle="dropdown"]',c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),e,f,g;if(c.is(".disabled, :disabled"))return;return f=c.attr("data-target"),f||(f=c.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,"")),e=a(f),e.length||(e=c.parent()),g=e.hasClass("open"),d(),g||e.toggleClass("open"),!1}},a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a(function(){a("html").on("click.dropdown.data-api",d),a("body").on("click.dropdown",".dropdown form",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle)})}(window.jQuery),!function(a){function c(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),d.call(b)},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),d.call(b)})}function d(a){this.$element.hide().trigger("hidden"),e.call(this)}function e(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('