diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..de564e58 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,30 @@ +--- +name: Bug report +about: Report a bug for this project + +--- + +**README and remove me** +For community support and other discussion, you are welcome to visit and stay with us @ Freenode, #mailcow +Answering can take a few seconds up to many hours, please be patient. +Commercial support, including a ticket system, can be found @ https://www.servercow.de/mailcow#support - we are also available via Telegram. \o/ + +**Describe the bug, try to make it reproducible** +A clear and concise description of what the bug is. How can it be reproduced? +If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI. + +**System information and quick debugging** +General logs: +- Please take a look at the [documentation](https://mailcow.github.io/mailcow-dockerized-docs/debug-logs/). + +Further information (where applicable): + - Your OS (is Apparmor or SELinux active?) + - Your virtualization technology (KVM/QEMU, Xen, VMware, VirtualBox etc.) + - Your server/VM specifications (Memory, CPU Cores) + - Don't try to run mailcow on a Synology or QNAP NAS, do you? + - Docker and Docker Compose versions + - Output of `git diff origin/master`, any other changes to the code? + - All third-party firewalls and custom iptables rules are unsupported. Please check the Docker docs about how to use Docker with your own ruleset. Nevertheless, iptabels output can help _us_ to help _you_: `iptables -L -vn`, `ip6tables -L -vn`, `iptables -L -vn -t nat` and `ip6tables -L -vn -t nat ` + - Reverse proxy? If you think this problem is related to your reverse proxy, please post your configuration. + - Browser (if it's a Web UI issue) - please clean your browser cache and try again, problem persists? + - Check `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @172.22.1.254` (set the IP accordingly, if you changed the internal mailcow network) and `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @1.1.1.1` - output? Timeout? diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000..860ab66b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here or remove this section diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 00000000..24db8c03 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + - enhancement +# Label to use when marking an issue as stale +staleLabel: dunno +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.gitignore b/.gitignore index e535c710..5fd3c0f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,20 @@ rebuild-images.sh data/conf/sogo/sieve.creds +data/conf/phpfpm/sogo-sso/sogo-sso.pass data/conf/dovecot/dovecot-master.passwd +data/conf/dovecot/dovecot-master.userdb mailcow.conf mailcow.conf_backup data/conf/nginx/*.active data/conf/postfix/sql +data/conf/postfix/allow_mailcow_local.regexp data/conf/dovecot/sql data/conf/nextcloud-*.bak data/web/inc/vars.local.inc.php data/assets/ssl/* .vscode/* data/web/.well-known/acme-challenge -data/web/nextcloud/ +data/web/nextcloud*/ data/conf/rspamd/local.d/* data/conf/rspamd/override.d/* !data/conf/nginx/dynmaps.conf @@ -20,4 +23,14 @@ data/conf/rspamd/override.d/* data/conf/nginx/*.conf data/conf/nginx/*.custom data/conf/nginx/*.bak +data/conf/dovecot/acl_anyone +data/conf/dovecot/mail_plugins* +data/conf/dovecot/sogo-sso.conf data/conf/dovecot/extra.conf +data/conf/rspamd/custom/* +data/conf/portainer/ +data/gitea/ +data/gogs/ +data/conf/sogo/plist_ldap +.github/ +docker-compose.override.yml diff --git a/README.md b/README.md index 42b2a3f1..ec500d9c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # mailcow: dockerized - ๐Ÿฎ + ๐Ÿ‹ = ๐Ÿ’• -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JWBSYHF4SMC68) +## Want to support mailcow? -**mailcow Bitcoin donations:** 1E5rgzgA1sS3QH7r1ToWxRC3GEavfsGMrx +Donate via **PayPal** [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JWBSYHF4SMC68) or via **Liberapay** [![Liberapay.com](https://mailcow.email/img/lp.png)](https://liberapay.com/mailcow) + +Or just spread the word: moo. + +## Info and documentation Please see [the official documentation](https://mailcow.github.io/mailcow-dockerized-docs/) for instructions. diff --git a/data/Dockerfiles/acme/Dockerfile b/data/Dockerfiles/acme/Dockerfile index ce3fc171..a17064fe 100644 --- a/data/Dockerfiles/acme/Dockerfile +++ b/data/Dockerfiles/acme/Dockerfile @@ -1,10 +1,9 @@ -FROM alpine:3.6 +FROM alpine:3.9 LABEL maintainer "Andre Peters " RUN apk add --update --no-cache \ bash \ - acme-client \ curl \ openssl \ bind-tools \ @@ -12,7 +11,10 @@ RUN apk add --update --no-cache \ mariadb-client \ redis \ tini \ - tzdata + tzdata \ + py-pip \ + && pip install --upgrade pip \ + && pip install acme-tiny COPY docker-entrypoint.sh /srv/docker-entrypoint.sh COPY expand6.sh /srv/expand6.sh diff --git a/data/Dockerfiles/acme/docker-entrypoint.sh b/data/Dockerfiles/acme/docker-entrypoint.sh index c9a91dfa..e79ef977 100755 --- a/data/Dockerfiles/acme/docker-entrypoint.sh +++ b/data/Dockerfiles/acme/docker-entrypoint.sh @@ -5,6 +5,16 @@ exec 5>&1 # Thanks to https://github.com/cvmiller -> https://github.com/cvmiller/expand6 source /srv/expand6.sh +# Skipping IP check when we like to live dangerously +if [[ "${SKIP_IP_CHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + SKIP_IP_CHECK=y +fi + +# Skipping HTTP check when we like to live dangerously +if [[ "${SKIP_HTTP_VERIFICATION}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + SKIP_HTTP_VERIFICATION=y +fi + log_f() { if [[ ${2} == "no_nl" ]]; then echo -n "$(date) - ${1}" @@ -13,8 +23,12 @@ log_f() { elif [[ ${2} != "redis_only" ]]; then echo "$(date) - ${1}" fi - redis-cli -h redis LPUSH ACME_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}" | \ - tr '%&;$"_[]{}-\r\n' ' ')\"}" > /dev/null + if [[ ${3} == "b64" ]]; then + redis-cli -h redis LPUSH ACME_LOG "{\"time\":\"$(date +%s)\",\"message\":\"base64,$(printf '%s' "${1}")\"}" > /dev/null + else + redis-cli -h redis LPUSH ACME_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}" | \ + tr '%&;$"[]{}-\r\n' ' ')\"}" > /dev/null + fi } if [[ "${SKIP_LETS_ENCRYPT}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then @@ -32,12 +46,34 @@ log_f "OK" no_date ACME_BASE=/var/lib/acme SSL_EXAMPLE=/var/lib/ssl-example -mkdir -p ${ACME_BASE}/acme/private +mkdir -p ${ACME_BASE}/acme -restart_containers(){ +# Migrate +[[ -f ${ACME_BASE}/acme/private/privkey.pem ]] && mv ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/acme/key.pem +[[ -f ${ACME_BASE}/acme/private/account.key ]] && mv ${ACME_BASE}/acme/private/account.key ${ACME_BASE}/acme/account.pem + +reload_configurations(){ + # Reading container IDs + # Wrapping as array to ensure trimmed content when calling $NGINX etc. + local NGINX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("nginx-mailcow")) | .id' | tr "\n" " ")) + local DOVECOT=($(curl --silent --insecure https://dockerapi/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("dovecot-mailcow")) | .id' | tr "\n" " ")) + local POSTFIX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("postfix-mailcow")) | .id' | tr "\n" " ")) + # Reloading + echo "Reloading Nginx..." + NGINX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${NGINX}/exec -d '{"cmd":"reload", "task":"nginx"}' --silent -H 'Content-type: application/json' | jq -r .type) + [[ ${NGINX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Nginx, restarting container..."; restart_container ${NGINX} ; } + echo "Reloading Dovecot..." + DOVECOT_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${DOVECOT}/exec -d '{"cmd":"reload", "task":"dovecot"}' --silent -H 'Content-type: application/json' | jq -r .type) + [[ ${DOVECOT_RELOAD_RET} != 'success' ]] && { echo "Could not reload Dovecot, restarting container..."; restart_container ${DOVECOT} ; } + echo "Reloading Postfix..." + POSTFIX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${POSTFIX}/exec -d '{"cmd":"reload", "task":"postfix"}' --silent -H 'Content-type: application/json' | jq -r .type) + [[ ${POSTFIX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Postfix, restarting container..."; restart_container ${POSTFIX} ; } +} + +restart_container(){ for container in $*; do log_f "Restarting ${container}..." no_nl - C_REST_OUT=$(curl -X POST http://dockerapi:8080/containers/${container}/restart | jq -r '.msg') + C_REST_OUT=$(curl -X POST --insecure https://dockerapi/containers/${container}/restart | jq -r '.msg') log_f "${C_REST_OUT}" no_date done } @@ -90,28 +126,37 @@ get_ipv6(){ echo ${IPV6} } +verify_challenge_path(){ + # verify_challenge_path URL 4|6 + RAND_FILE=${RANDOM}${RANDOM}${RANDOM} + touch /var/www/acme/${RAND_FILE} + if [[ ${SKIP_HTTP_VERIFICATION} == "y" ]]; then + echo '(skipping check, returning 0)' + return 0 + elif [[ "$(curl -${2} http://${1}/.well-known/acme-challenge/${RAND_FILE} --write-out %{http_code} --silent --output /dev/null)" =~ ^(2|3) ]]; then + rm /var/www/acme/${RAND_FILE} + return 0 + else + rm /var/www/acme/${RAND_FILE} + return 1 + fi +} + [[ ! -f ${ACME_BASE}/dhparams.pem ]] && cp ${SSL_EXAMPLE}/dhparams.pem ${ACME_BASE}/dhparams.pem if [[ -f ${ACME_BASE}/cert.pem ]] && [[ -f ${ACME_BASE}/key.pem ]]; then ISSUER=$(openssl x509 -in ${ACME_BASE}/cert.pem -noout -issuer) - if [[ ${ISSUER} != *"Let's Encrypt"* && ${ISSUER} != *"mailcow"* ]]; then + if [[ ${ISSUER} != *"Let's Encrypt"* && ${ISSUER} != *"mailcow"* && ${ISSUER} != *"Fake LE Intermediate"* ]]; then log_f "Found certificate with issuer other than mailcow snake-oil CA and Let's Encrypt, skipping ACME client..." sleep 3650d exec $(readlink -f "$0") - else - declare -a SAN_ARRAY_NOW - SAN_NAMES=$(openssl x509 -noout -text -in ${ACME_BASE}/cert.pem | awk '/X509v3 Subject Alternative Name/ {getline;gsub(/ /, "", $0); print}' | tr -d "DNS:") - if [[ ! -z ${SAN_NAMES} ]]; then - IFS=',' read -a SAN_ARRAY_NOW <<< ${SAN_NAMES} - log_f "Found Let's Encrypt or mailcow snake-oil CA issued certificate with SANs: ${SAN_ARRAY_NOW[*]}" - fi fi else - if [[ -f ${ACME_BASE}/acme/fullchain.pem ]] && [[ -f ${ACME_BASE}/acme/private/privkey.pem ]]; then - if verify_hash_match ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/acme/private/privkey.pem; then + if [[ -f ${ACME_BASE}/acme/cert.pem ]] && [[ -f ${ACME_BASE}/acme/key.pem ]]; then + if verify_hash_match ${ACME_BASE}/acme/cert.pem ${ACME_BASE}/acme/key.pem; then log_f "Restoring previous acme certificate and restarting script..." - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem + cp ${ACME_BASE}/acme/cert.pem ${ACME_BASE}/cert.pem + cp ${ACME_BASE}/acme/key.pem ${ACME_BASE}/key.pem # Restarting with env var set to trigger a restart, exec env TRIGGER_RESTART=1 $(readlink -f "$0") fi @@ -123,25 +168,80 @@ else exec env TRIGGER_RESTART=1 $(readlink -f "$0") fi fi +chmod 600 ${ACME_BASE}/key.pem -log_f "Waiting for database... " -while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do +log_f "Waiting for database... " no_nl +while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do sleep 2 done +log_f "OK" no_date + +log_f "Waiting for Nginx... " no_nl +until $(curl --output /dev/null --silent --head --fail http://nginx:8081); do + sleep 2 +done +log_f "OK" no_date + +# Waiting for domain table +log_f "Waiting for domain table... " no_nl +while [[ -z ${DOMAIN_TABLE} ]]; do + curl --silent http://nginx/ >/dev/null 2>&1 + DOMAIN_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs) + [[ -z ${DOMAIN_TABLE} ]] && sleep 10 +done +log_f "OK" no_date + log_f "Initializing, please wait... " - while true; do - if [[ "${SKIP_IP_CHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then - SKIP_IP_CHECK=y + + # Re-using previous acme-mailcow account and domain keys + if [[ ! -f ${ACME_BASE}/acme/key.pem ]]; then + log_f "Generating missing domain private key..." + openssl genrsa 4096 > ${ACME_BASE}/acme/key.pem + else + log_f "Using existing domain key ${ACME_BASE}/acme/key.pem" fi + if [[ ! -f ${ACME_BASE}/acme/account.pem ]]; then + log_f "Generating missing Lets Encrypt account key..." + openssl genrsa 4096 > ${ACME_BASE}/acme/account.pem + else + log_f "Using existing Lets Encrypt account key ${ACME_BASE}/acme/account.pem" + fi + + chmod 600 ${ACME_BASE}/acme/key.pem + chmod 600 ${ACME_BASE}/acme/account.pem + + # Cleaning up and init validation arrays unset SQL_DOMAIN_ARR unset VALIDATED_CONFIG_DOMAINS unset ADDITIONAL_VALIDATED_SAN + unset ADDITIONAL_WC_ARR + unset ADDITIONAL_SAN_ARR + unset SAN_CHANGE + unset SAN_ARRAY_NOW + unset ORPHANED_SAN + unset ADDED_SAN + SAN_CHANGE=0 + declare -a SAN_ARRAY_NOW + declare -a ORPHANED_SAN + declare -a ADDED_SAN declare -a SQL_DOMAIN_ARR declare -a VALIDATED_CONFIG_DOMAINS declare -a ADDITIONAL_VALIDATED_SAN - IFS=',' read -r -a ADDITIONAL_SAN_ARR <<< "${ADDITIONAL_SAN}" + declare -a ADDITIONAL_WC_ARR + declare -a ADDITIONAL_SAN_ARR + IFS=',' read -r -a TMP_ARR <<< "${ADDITIONAL_SAN}" + for i in "${TMP_ARR[@]}" ; do + if [[ "$i" =~ \.\*$ ]]; then + ADDITIONAL_WC_ARR+=(${i::-2}) + else + ADDITIONAL_SAN_ARR+=($i) + fi + done + ADDITIONAL_WC_ARR+=('autodiscover') + + # Start IP detection log_f "Detecting IP addresses... " no_nl IPV4=$(get_ipv4) IPV6=$(get_ipv6) @@ -160,73 +260,50 @@ while true; do fi fi - # Container ids may have changed - CONTAINERS_RESTART=($(curl --silent http://dockerapi:8080/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("nginx-mailcow") or contains("postfix-mailcow") or contains("dovecot-mailcow")) | .id' | tr "\n" " ")) - - log_f "Waiting for domain table... " no_nl - while [[ -z ${DOMAIN_TABLE} ]]; do - curl --silent http://nginx/ >/dev/null 2>&1 - DOMAIN_TABLE=$(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs) - [[ -z ${DOMAIN_TABLE} ]] && sleep 10 - done - log_f "OK" no_date - + ######################################### + # IP and webroot challenge verification # while read domains; do SQL_DOMAIN_ARR+=("${domains}") - done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0 UNION SELECT alias_domain FROM alias_domain" -Bs) + done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0" -Bs) for SQL_DOMAIN in "${SQL_DOMAIN_ARR[@]}"; do - A_CONFIG=$(dig A autoconfig.${SQL_DOMAIN} +short | tail -n 1) - AAAA_CONFIG=$(dig AAAA autoconfig.${SQL_DOMAIN} +short | tail -n 1) - # Check if CNAME without v6 enabled target - if [[ ! -z ${AAAA_CONFIG} ]] && [[ -z $(echo ${AAAA_CONFIG} | grep "^\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}$") ]]; then - AAAA_CONFIG= - fi - if [[ ! -z ${AAAA_CONFIG} ]]; then - log_f "Found AAAA record for autoconfig.${SQL_DOMAIN}: ${AAAA_CONFIG} - skipping A record check" - if [[ $(expand ${IPV6:-"0000:0000:0000:0000:0000:0000:0000:0000"}) == $(expand ${AAAA_CONFIG}) ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed AAAA record autoconfig.${SQL_DOMAIN}" - VALIDATED_CONFIG_DOMAINS+=("autoconfig.${SQL_DOMAIN}") - else - log_f "Cannot match your IP ${IPV6:-NO_IPV6_LINK} against hostname autoconfig.${SQL_DOMAIN} ($(expand ${AAAA_CONFIG}))" + for SUBDOMAIN in "${ADDITIONAL_WC_ARR[@]}"; do + if [[ "${SUBDOMAIN}.${SQL_DOMAIN}" != "${MAILCOW_HOSTNAME}" ]]; then + A_SUBDOMAIN=$(dig A ${SUBDOMAIN}.${SQL_DOMAIN} +short | tail -n 1) + AAAA_SUBDOMAIN=$(dig AAAA ${SUBDOMAIN}.${SQL_DOMAIN} +short | tail -n 1) + # Check if CNAME without v6 enabled target + if [[ ! -z ${AAAA_SUBDOMAIN} ]] && [[ -z $(echo ${AAAA_SUBDOMAIN} | grep "^\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}$") ]]; then + AAAA_SUBDOMAIN= + fi + if [[ ! -z ${AAAA_SUBDOMAIN} ]]; then + log_f "Found AAAA record for ${SUBDOMAIN}.${SQL_DOMAIN}: ${AAAA_SUBDOMAIN} - skipping A record check" + if [[ $(expand ${IPV6:-"0000:0000:0000:0000:0000:0000:0000:0000"}) == $(expand ${AAAA_SUBDOMAIN}) ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then + if verify_challenge_path "${SUBDOMAIN}.${SQL_DOMAIN}" 6; then + log_f "Confirmed AAAA record ${AAAA_SUBDOMAIN}" + VALIDATED_CONFIG_DOMAINS+=("${SUBDOMAIN}.${SQL_DOMAIN}") + else + log_f "Confirmed AAAA record ${AAAA_SUBDOMAIN}, but HTTP validation failed" + fi + else + log_f "Cannot match your IP ${IPV6:-NO_IPV6_LINK} against hostname ${SUBDOMAIN}.${SQL_DOMAIN} ($(expand ${AAAA_SUBDOMAIN}))" + fi + elif [[ ! -z ${A_SUBDOMAIN} ]]; then + log_f "Found A record for ${SUBDOMAIN}.${SQL_DOMAIN}: ${A_SUBDOMAIN}" + if [[ ${IPV4:-ERR} == ${A_SUBDOMAIN} ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then + if verify_challenge_path "${SUBDOMAIN}.${SQL_DOMAIN}" 4; then + log_f "Confirmed A record ${A_SUBDOMAIN}" + VALIDATED_CONFIG_DOMAINS+=("${SUBDOMAIN}.${SQL_DOMAIN}") + else + log_f "Confirmed AAAA record ${A_SUBDOMAIN}, but HTTP validation failed" + fi + else + log_f "Cannot match your IP ${IPV4} against hostname ${SUBDOMAIN}.${SQL_DOMAIN} (${A_SUBDOMAIN})" + fi + else + log_f "No A or AAAA record found for hostname ${SUBDOMAIN}.${SQL_DOMAIN}" + fi fi - elif [[ ! -z ${A_CONFIG} ]]; then - log_f "Found A record for autoconfig.${SQL_DOMAIN}: ${A_CONFIG}" - if [[ ${IPV4:-ERR} == ${A_CONFIG} ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed A record autoconfig.${SQL_DOMAIN}" - VALIDATED_CONFIG_DOMAINS+=("autoconfig.${SQL_DOMAIN}") - else - log_f "Cannot match your IP ${IPV4} against hostname autoconfig.${SQL_DOMAIN} (${A_CONFIG})" - fi - else - log_f "No A or AAAA record found for hostname autoconfig.${SQL_DOMAIN}" - fi - - A_DISCOVER=$(dig A autodiscover.${SQL_DOMAIN} +short | tail -n 1) - AAAA_DISCOVER=$(dig AAAA autodiscover.${SQL_DOMAIN} +short | tail -n 1) - # Check if CNAME without v6 enabled target - if [[ ! -z ${AAAA_DISCOVER} ]] && [[ -z $(echo ${AAAA_DISCOVER} | grep "^\([0-9a-fA-F]\{0,4\}:\)\{1,7\}[0-9a-fA-F]\{0,4\}$") ]]; then - AAAA_DISCOVER= - fi - if [[ ! -z ${AAAA_DISCOVER} ]]; then - log_f "Found AAAA record for autodiscover.${SQL_DOMAIN}: ${AAAA_DISCOVER} - skipping A record check" - if [[ $(expand ${IPV6:-"0000:0000:0000:0000:0000:0000:0000:0000"}) == $(expand ${AAAA_DISCOVER}) ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed AAAA record autodiscover.${SQL_DOMAIN}" - VALIDATED_CONFIG_DOMAINS+=("autodiscover.${SQL_DOMAIN}") - else - log_f "Cannot match your IP ${IPV6:-NO_IPV6_LINK} against hostname autodiscover.${SQL_DOMAIN} ($(expand ${AAAA_DISCOVER}))" - fi - elif [[ ! -z ${A_DISCOVER} ]]; then - log_f "Found A record for autodiscover.${SQL_DOMAIN}: ${A_DISCOVER}" - if [[ ${IPV4:-ERR} == ${A_DISCOVER} ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed A record autodiscover.${SQL_DOMAIN}" - VALIDATED_CONFIG_DOMAINS+=("autodiscover.${SQL_DOMAIN}") - else - log_f "Cannot match your IP ${IPV4} against hostname autodiscover.${SQL_DOMAIN} (${A_DISCOVER})" - fi - else - log_f "No A or AAAA record found for hostname autodiscover.${SQL_DOMAIN}" - fi + done done A_MAILCOW_HOSTNAME=$(dig A ${MAILCOW_HOSTNAME} +short | tail -n 1) @@ -238,16 +315,24 @@ while true; do if [[ ! -z ${AAAA_MAILCOW_HOSTNAME} ]]; then log_f "Found AAAA record for ${MAILCOW_HOSTNAME}: ${AAAA_MAILCOW_HOSTNAME} - skipping A record check" if [[ $(expand ${IPV6:-"0000:0000:0000:0000:0000:0000:0000:0000"}) == $(expand ${AAAA_MAILCOW_HOSTNAME}) ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed AAAA record ${MAILCOW_HOSTNAME}" - VALIDATED_MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + if verify_challenge_path "${MAILCOW_HOSTNAME}" 6; then + log_f "Confirmed AAAA record ${AAAA_MAILCOW_HOSTNAME}" + VALIDATED_MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + else + log_f "Confirmed AAAA record ${A_MAILCOW_HOSTNAME}, but HTTP validation failed" + fi else log_f "Cannot match your IP ${IPV6:-NO_IPV6_LINK} against hostname ${MAILCOW_HOSTNAME} ($(expand ${AAAA_MAILCOW_HOSTNAME}))" fi elif [[ ! -z ${A_MAILCOW_HOSTNAME} ]]; then log_f "Found A record for ${MAILCOW_HOSTNAME}: ${A_MAILCOW_HOSTNAME}" if [[ ${IPV4:-ERR} == ${A_MAILCOW_HOSTNAME} ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed A record ${A_MAILCOW_HOSTNAME}" - VALIDATED_MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + if verify_challenge_path "${MAILCOW_HOSTNAME}" 4; then + log_f "Confirmed A record ${A_MAILCOW_HOSTNAME}" + VALIDATED_MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + else + log_f "Confirmed A record ${A_MAILCOW_HOSTNAME}, but HTTP validation failed" + fi else log_f "Cannot match your IP ${IPV4} against hostname ${MAILCOW_HOSTNAME} (${A_MAILCOW_HOSTNAME})" fi @@ -279,16 +364,24 @@ while true; do if [[ ! -z ${AAAA_SAN} ]]; then log_f "Found AAAA record for ${SAN}: ${AAAA_SAN} - skipping A record check" if [[ $(expand ${IPV6:-"0000:0000:0000:0000:0000:0000:0000:0000"}) == $(expand ${AAAA_SAN}) ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed AAAA record ${SAN}" - ADDITIONAL_VALIDATED_SAN+=("${SAN}") + if verify_challenge_path "${SAN}" 6; then + log_f "Confirmed AAAA record ${AAAA_SAN}" + ADDITIONAL_VALIDATED_SAN+=("${SAN}") + else + log_f "Confirmed AAAA record ${AAAA_SAN}, but HTTP validation failed" + fi else log_f "Cannot match your IP ${IPV6:-NO_IPV6_LINK} against hostname ${SAN} ($(expand ${AAAA_SAN}))" fi elif [[ ! -z ${A_SAN} ]]; then log_f "Found A record for ${SAN}: ${A_SAN}" if [[ ${IPV4:-ERR} == ${A_SAN} ]] || [[ ${SKIP_IP_CHECK} == "y" ]]; then - log_f "Confirmed A record ${A_SAN}" - ADDITIONAL_VALIDATED_SAN+=("${SAN}") + if verify_challenge_path "${SAN}" 4; then + log_f "Confirmed A record ${A_SAN}" + ADDITIONAL_VALIDATED_SAN+=("${SAN}") + else + log_f "Confirmed A record ${A_SAN}, but HTTP validation failed" + fi else log_f "Cannot match your IP ${IPV4} against hostname ${SAN} (${A_SAN})" fi @@ -306,113 +399,98 @@ while true; do exec $(readlink -f "$0") fi - array_diff ORPHANED_SAN SAN_ARRAY_NOW ALL_VALIDATED - if [[ ! -z ${ORPHANED_SAN[*]} ]] && [[ ${ISSUER} != *"mailcow"* ]]; then - DATE=$(date +%Y-%m-%d_%H_%M_%S) - log_f "Found orphaned SAN ${ORPHANED_SAN[*]} in certificate, moving old files to ${ACME_BASE}/acme/private/${DATE}.bak/, keeping key file..." - mkdir -p ${ACME_BASE}/acme/private/${DATE}.bak/ - [[ -f ${ACME_BASE}/acme/private/account.key ]] && mv ${ACME_BASE}/acme/private/account.key ${ACME_BASE}/acme/private/${DATE}.bak/ - [[ -f ${ACME_BASE}/acme/fullchain.pem ]] && mv ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/acme/private/${DATE}.bak/ - [[ -f ${ACME_BASE}/acme/cert.pem ]] && mv ${ACME_BASE}/acme/cert.pem ${ACME_BASE}/acme/private/${DATE}.bak/ - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/acme/private/${DATE}.bak/ # Keep key for TLSA 3 1 1 records + # Collecting SANs from active certificate + SAN_NAMES=$(openssl x509 -noout -text -in ${ACME_BASE}/cert.pem | awk '/X509v3 Subject Alternative Name/ {getline;gsub(/ /, "", $0); print}' | tr -d "DNS:") + if [[ ! -z ${SAN_NAMES} ]]; then + IFS=',' read -a SAN_ARRAY_NOW <<< ${SAN_NAMES} fi - ACME_RESPONSE=$(acme-client \ - -v -e -b -N -n \ - -a 'https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf' \ - -f ${ACME_BASE}/acme/private/account.key \ - -k ${ACME_BASE}/acme/private/privkey.pem \ - -c ${ACME_BASE}/acme \ - ${ALL_VALIDATED[*]} 2>&1 | tee /dev/fd/5) + # Finding difference in SAN array now vs. SAN array by current configuration + array_diff ORPHANED_SAN SAN_ARRAY_NOW ALL_VALIDATED + if [[ ! -z ${ORPHANED_SAN[*]} ]]; then + log_f "Found orphaned SANs ${ORPHANED_SAN[*]}" + SAN_CHANGE=1 + fi + array_diff ADDED_SAN ALL_VALIDATED SAN_ARRAY_NOW + if [[ ! -z ${ADDED_SAN[*]} ]]; then + log_f "Found new SANs ${ADDED_SAN[*]}" + SAN_CHANGE=1 + fi + + if [[ ${SAN_CHANGE} == 0 ]]; then + # Certificate did not change but could be due for renewal (4 weeks) + if ! openssl x509 -checkend 1209600 -noout -in ${ACME_BASE}/cert.pem; then + log_f "Certificate is due for renewal (< 2 weeks)" + else + log_f "Certificate validation done, neither changed nor due for renewal, sleeping for another day." + sleep 1d + continue + fi + fi + + DATE=$(date +%Y-%m-%d_%H_%M_%S) + log_f "Creating backups in ${ACME_BASE}/backups/${DATE}/ ..." + mkdir -p ${ACME_BASE}/backups/${DATE}/ + [[ -f ${ACME_BASE}/acme/acme.csr ]] && cp ${ACME_BASE}/acme/acme.csr ${ACME_BASE}/backups/${DATE}/ + [[ -f ${ACME_BASE}/acme/cert.pem ]] && cp ${ACME_BASE}/acme/cert.pem ${ACME_BASE}/backups/${DATE}/ + [[ -f ${ACME_BASE}/acme/key.pem ]] && cp ${ACME_BASE}/acme/key.pem ${ACME_BASE}/backups/${DATE}/ + [[ -f ${ACME_BASE}/acme/account.pem ]] && cp ${ACME_BASE}/acme/account.pem ${ACME_BASE}/backups/${DATE}/ + + # Generating CSR + printf "[SAN]\nsubjectAltName=" > /tmp/_SAN + printf "DNS:%s," "${ALL_VALIDATED[@]}" >> /tmp/_SAN + sed -i '$s/,$//' /tmp/_SAN + openssl req -new -sha256 -key ${ACME_BASE}/acme/key.pem -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf /tmp/_SAN) > ${ACME_BASE}/acme/acme.csr + + if [[ "${LE_STAGING}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + log_f "Using Let's Encrypt staging servers" + STAGING_PARAMETER='--directory-url https://acme-staging-v02.api.letsencrypt.org/directory' + else + STAGING_PARAMETER= + fi + + # acme-tiny writes info to stderr and ceritifcate to stdout + # The redirects will do the following: + # - redirect stdout to temp certificate file + # - redirect acme-tiny stderr to stdout (logs to variable ACME_RESPONSE) + # - tee stderr to get live output and log to dockerd + + ACME_RESPONSE=$(acme-tiny ${STAGING_PARAMETER} \ + --account-key ${ACME_BASE}/acme/account.pem \ + --disable-check \ + --csr ${ACME_BASE}/acme/acme.csr \ + --acme-dir /var/www/acme/ 2>&1 > /tmp/_cert.pem | tee /dev/fd/5) case "$?" in - 0) # new certs - log_f "${ACME_RESPONSE}" redis_only - # cp the new certificates and keys - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem - - # restart docker containers - if ! verify_hash_match ${ACME_BASE}/cert.pem ${ACME_BASE}/key.pem; then - log_f "Certificate was successfully requested, but key and certificate have non-matching hashes, restoring mailcow snake-oil and restarting containers..." - cp ${SSL_EXAMPLE}/cert.pem ${ACME_BASE}/cert.pem - cp ${SSL_EXAMPLE}/key.pem ${ACME_BASE}/key.pem - fi - restart_containers ${CONTAINERS_RESTART[*]} - ;; - 1) # failure - log_f "${ACME_RESPONSE}" redis_only - if [[ $ACME_RESPONSE =~ "No registration exists" ]]; then - log_f "Registration keys are invalid, deleting old keys and restarting..." - rm ${ACME_BASE}/acme/private/account.key + 0) # cert requested + ACME_RESPONSE_B64=$(echo "${ACME_RESPONSE}" | openssl enc -e -A -base64) + log_f "${ACME_RESPONSE_B64}" redis_only b64 + log_f "Deploying..." + # Deploy the new certificate and key + # Moving temp cert to acme/cert.pem + if verify_hash_match /tmp/_cert.pem ${ACME_BASE}/acme/key.pem; then + mv /tmp/_cert.pem ${ACME_BASE}/acme/cert.pem + cp ${ACME_BASE}/acme/cert.pem ${ACME_BASE}/cert.pem + cp ${ACME_BASE}/acme/key.pem ${ACME_BASE}/key.pem + reload_configurations + rm /var/www/acme/* + log_f "Certificate successfully deployed, removing backup, sleeping 1d" + sleep 1d + else + log_f "Certificate was successfully requested, but key and certificate have non-matching hashes, ignoring certificate" + log_f "Retrying in 30 minutes..." + sleep 30m exec $(readlink -f "$0") fi - if [[ -f ${ACME_BASE}/acme/private/${DATE}.bak/fullchain.pem ]] && [[ -f ${ACME_BASE}/acme/private/${DATE}.bak/privkey.pem ]]; then - log_f "Error requesting certificate, restoring previous certificate from backup and restarting containers...." - cp ${ACME_BASE}/acme/private/${DATE}.bak/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/${DATE}.bak/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - elif [[ -f ${ACME_BASE}/acme/fullchain.pem ]] && [[ -f ${ACME_BASE}/acme/private/privkey.pem ]]; then - log_f "Error requesting certificate, restoring from previous acme request and restarting containers..." - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - if ! verify_hash_match ${ACME_BASE}/cert.pem ${ACME_BASE}/key.pem; then - log_f "Error verifying certificates, restoring mailcow snake-oil and restarting containers..." - cp ${SSL_EXAMPLE}/cert.pem ${ACME_BASE}/cert.pem - cp ${SSL_EXAMPLE}/key.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - [[ ${TRIGGER_RESTART} == 1 ]] && restart_containers ${CONTAINERS_RESTART[*]} - log_f "Retrying in 30 minutes..." - sleep 30m - exec $(readlink -f "$0") ;; - 2) # no change - log_f "${ACME_RESPONSE}" redis_only - if ! diff ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem; then - log_f "Certificate was not changed, but active certificate does not match the verified certificate, fixing and restarting containers..." - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - if ! verify_hash_match ${ACME_BASE}/cert.pem ${ACME_BASE}/key.pem; then - log_f "Certificate was not changed, but hashes do not match, restoring from previous acme request and restarting containers..." - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - log_f "Certificate was not changed" - [[ ${TRIGGER_RESTART} == 1 ]] && restart_containers ${CONTAINERS_RESTART[*]} - ;; - *) # unspecified - log_f "${ACME_RESPONSE}" redis_only - if [[ -f ${ACME_BASE}/acme/private/${DATE}.bak/fullchain.pem ]] && [[ -f ${ACME_BASE}/acme/private/${DATE}.bak/privkey.pem ]]; then - log_f "Error requesting certificate, restoring previous certificate from backup and restarting containers...." - cp ${ACME_BASE}/acme/private/${DATE}.bak/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/${DATE}.bak/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - elif [[ -f ${ACME_BASE}/acme/fullchain.pem ]] && [[ -f ${ACME_BASE}/acme/private/privkey.pem ]]; then - log_f "Error requesting certificate, restoring from previous acme request and restarting containers..." - cp ${ACME_BASE}/acme/fullchain.pem ${ACME_BASE}/cert.pem - cp ${ACME_BASE}/acme/private/privkey.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - if ! verify_hash_match ${ACME_BASE}/cert.pem ${ACME_BASE}/key.pem; then - log_f "Error verifying certificates, restoring mailcow snake-oil..." - cp ${SSL_EXAMPLE}/cert.pem ${ACME_BASE}/cert.pem - cp ${SSL_EXAMPLE}/key.pem ${ACME_BASE}/key.pem - TRIGGER_RESTART=1 - fi - [[ ${TRIGGER_RESTART} == 1 ]] && restart_containers ${CONTAINERS_RESTART[*]} + *) # non-zero is non-fun + ACME_RESPONSE_B64=$(echo "${ACME_RESPONSE}" | openssl enc -e -A -base64) + log_f "${ACME_RESPONSE_B64}" redis_only b64 log_f "Retrying in 30 minutes..." + redis-cli -h redis SET ACME_FAIL_TIME "$(date +%s)" sleep 30m exec $(readlink -f "$0") ;; esac - log_f "ACME certificate validation done. Sleeping for another day." - sleep 1d - done diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index fc6f0a1f..f5a3903b 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,24 +1,37 @@ -FROM alpine:3.8 +FROM debian:stretch-slim LABEL maintainer "Andrรฉ Peters " -# Add scripts -COPY dl_files.sh bootstrap.sh ./ - # Installation -ENV CLAMAV 0.100.1 +ENV CLAMAV 0.101.1 -RUN apk add --no-cache --virtual build-dependencies alpine-sdk ncurses-dev zlib-dev bzip2-dev pcre-dev linux-headers fts-dev libxml2-dev libressl-dev \ - && apk add --no-cache curl bash tini libxml2 libbz2 pcre fts libressl tzdata \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + zlib1g-dev \ + libncurses5-dev \ + libzip-dev \ + libpcre2-dev \ + libxml2-dev \ + libssl-dev \ + build-essential \ + libjson-c-dev \ + curl \ + bash \ + wget \ + tzdata \ + dnsutils \ + rsync \ + dos2unix \ + netcat \ + && rm -rf /var/lib/apt/lists/* \ && wget -O - https://www.clamav.net/downloads/production/clamav-${CLAMAV}.tar.gz | tar xfvz - \ && cd clamav-${CLAMAV} \ - && LIBS=-lfts ./configure \ + && ./configure \ --prefix=/usr \ --libdir=/usr/lib \ --sysconfdir=/etc/clamav \ --mandir=/usr/share/man \ --infodir=/usr/share/info \ - --without-iconv \ --disable-llvm \ --with-user=clamav \ --with-group=clamav \ @@ -30,18 +43,19 @@ RUN apk add --no-cache --virtual build-dependencies alpine-sdk ncurses-dev zlib- && make install \ && make clean \ && cd .. && rm -rf clamav-${CLAMAV} \ - && apk del build-dependencies \ - && addgroup -S clamav \ - && adduser -S -D -h /var/lib/clamav -s /sbin/nologin -G clamav -g clamav clamav \ - && adduser clamav tty \ - && mkdir -p /run/clamav \ - && chown clamav:clamav /run/clamav \ - && chmod +x /dl_files.sh \ - && set -ex; /bin/bash /dl_files.sh \ - && chmod 750 /run/clamav + && apt-get -y --auto-remove purge build-essential \ + && apt-get -y purge zlib1g-dev \ + libncurses5-dev \ + libzip-dev \ + libpcre2-dev \ + libxml2-dev \ + libssl-dev \ + libjson-c-dev \ + && addgroup --system --gid 700 clamav \ + && adduser --system --no-create-home --home /var/lib/clamav --uid 700 --gid 700 --disabled-login clamav \ + && rm -rf /tmp/* /var/tmp/* -# Port provision -EXPOSE 3310 +COPY bootstrap.sh ./ +COPY tini /sbin/tini -# AV daemon bootstrapping CMD ["/sbin/tini", "-g", "--", "/bootstrap.sh"] diff --git a/data/Dockerfiles/clamd/bootstrap.sh b/data/Dockerfiles/clamd/bootstrap.sh index ba1cee85..1d49cd20 100755 --- a/data/Dockerfiles/clamd/bootstrap.sh +++ b/data/Dockerfiles/clamd/bootstrap.sh @@ -6,16 +6,30 @@ if [[ "${SKIP_CLAMD}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then exit 0 fi -# Create log pipes -mkdir -p /var/log/clamav -touch /var/log/clamav/clamd.log /var/log/clamav/freshclam.log -chown -R clamav:clamav /var/log/clamav/ -chown root:tty /dev/console -chmod g+rw /dev/console +# Prepare whitelist + +mkdir -p /run/clamav /var/lib/clamav + +if [[ -s /etc/clamav/whitelist.ign2 ]]; then + echo "Copying non-empty whitelist.ign2 to /var/lib/clamav/whitelist.ign2" + cp /etc/clamav/whitelist.ign2 /var/lib/clamav/whitelist.ign2 +fi +if [[ ! -f /var/lib/clamav/whitelist.ign2 ]]; then + echo "Creating /var/lib/clamav/whitelist.ign2" + echo "Example-Signature.Ignore-1" > /var/lib/clamav/whitelist.ign2 +fi + +chown clamav:clamav -R /var/lib/clamav /run/clamav + +chmod 755 /var/lib/clamav +chmod 644 -R /var/lib/clamav/* +chmod 750 /run/clamav + +echo "Stating whitelist.ign2" +stat /var/lib/clamav/whitelist.ign2 -# Prepare -[[ ! -f /var/lib/clamav/whitelist.ign2 ]] && touch /var/lib/clamav/whitelist.ign2 dos2unix /var/lib/clamav/whitelist.ign2 + sed -i '/^\s*$/d' /var/lib/clamav/whitelist.ign2 BACKGROUND_TASKS=() @@ -29,7 +43,35 @@ done ) & BACKGROUND_TASKS+=($!) -clamd & +( +while true; do + sleep 2m + SANE_MIRRORS="$(dig +ignore +short rsync.sanesecurity.net)" + for sane_mirror in ${SANE_MIRRORS}; do + rsync -avp --chown=clamav:clamav --chmod=Du=rwx,Dgo=rx,Fu=rw,Fog=r --timeout=5 rsync://${sane_mirror}/sanesecurity/ \ + --include 'blurl.ndb' \ + --include 'junk.ndb' \ + --include 'jurlbl.ndb' \ + --include 'jurbla.ndb' \ + --include 'phishtank.ndb' \ + --include 'phish.ndb' \ + --include 'spamimg.hdb' \ + --include 'scam.ndb' \ + --include 'rogue.hdb' \ + --include 'sanesecurity.ftm' \ + --include 'sigwhitelist.ign2' \ + --exclude='*' /var/lib/clamav/ + if [ $? -eq 0 ]; then + echo RELOAD | nc localhost 3310 + break + fi + done + sleep 30h +done +) & +BACKGROUND_TASKS+=($!) + +nice -n10 clamd & BACKGROUND_TASKS+=($!) while true; do diff --git a/data/Dockerfiles/clamd/dl_files.sh b/data/Dockerfiles/clamd/dl_files.sh deleted file mode 100755 index 09d61241..00000000 --- a/data/Dockerfiles/clamd/dl_files.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -declare -a DB_MIRRORS=( - "switch.clamav.net" - "clamavdb.heanet.ie" - "clamav.iol.cz" - "clamav.univ-nantes.fr" - "clamav.easynet.fr" - "clamav.begi.net" -) -declare -a DB_MIRRORS=( $(shuf -e "${DB_MIRRORS[@]}") ) - -DB_FILES=( - "bytecode.cvd" - "daily.cvd" - "main.cvd" -) - -for i in "${DB_MIRRORS[@]}"; do - for j in "${DB_FILES[@]}"; do - [[ -f "/var/lib/clamav/${j}" && -s "/var/lib/clamav/${j}" ]] && continue; - if [[ $(curl -o /dev/null --connect-timeout 1 \ - --max-time 1 \ - --silent \ - --head \ - --write-out "%{http_code}\n" "${i}/${j}") == 200 ]]; then - curl "${i}/${j}" -o "/var/lib/clamav/${j}" -# - fi - done -done - -chown clamav:clamav /var/lib/clamav/*.cvd diff --git a/data/Dockerfiles/clamd/tini b/data/Dockerfiles/clamd/tini new file mode 100755 index 00000000..03af82f0 Binary files /dev/null and b/data/Dockerfiles/clamd/tini differ diff --git a/data/Dockerfiles/dockerapi/Dockerfile b/data/Dockerfiles/dockerapi/Dockerfile index 78389c4f..67bb6b07 100644 --- a/data/Dockerfiles/dockerapi/Dockerfile +++ b/data/Dockerfiles/dockerapi/Dockerfile @@ -1,8 +1,11 @@ -FROM python:2-alpine +FROM alpine:3.9 LABEL maintainer "Andre Peters " -RUN apk add -U --no-cache iptables ip6tables tzdata -RUN pip install docker==3.0.1 flask flask-restful +RUN apk add -U --no-cache python2 python-dev py-pip gcc musl-dev tzdata openssl-dev libffi-dev \ + && pip2 install --upgrade pip \ + && pip2 install --upgrade docker==3.0.1 flask flask-restful pyOpenSSL \ + && apk del python-dev py2-pip gcc COPY server.py / + CMD ["python2", "-u", "/server.py"] diff --git a/data/Dockerfiles/dockerapi/server.py b/data/Dockerfiles/dockerapi/server.py index e66cf238..d38775db 100644 --- a/data/Dockerfiles/dockerapi/server.py +++ b/data/Dockerfiles/dockerapi/server.py @@ -1,14 +1,19 @@ from flask import Flask from flask_restful import Resource, Api from flask import jsonify +from flask import Response from flask import request from threading import Thread +from OpenSSL import crypto import docker +import uuid import signal import time import os import re import sys +import ssl +import socket docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto') app = Flask(__name__) @@ -62,65 +67,228 @@ class container_post(Resource): except Exception as e: return jsonify(type='danger', msg=str(e)) + elif post_action == 'top': + try: + for container in docker_client.containers.list(all=True, filters={"id": container_id}): + return jsonify(type='success', msg=container.top()) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif post_action == 'stats': + try: + for container in docker_client.containers.list(all=True, filters={"id": container_id}): + return jsonify(type='success', msg=container.stats(decode=True, stream=False)) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif post_action == 'exec': if not request.json or not 'cmd' in request.json: return jsonify(type='danger', msg='cmd is missing') - if request.json['cmd'] == 'df' and request.json['dir']: - try: - for container in docker_client.containers.list(filters={"id": container_id}): - # Should be changed to be able to validate a path - directory = re.sub('[^0-9a-zA-Z/]+', '', request.json['dir']) - df_return = container.exec_run(["/bin/bash", "-c", "/bin/df -H " + directory + " | /usr/bin/tail -n1 | /usr/bin/tr -s [:blank:] | /usr/bin/tr ' ' ','"], user='nobody') - if df_return.exit_code == 0: - return df_return.output.rstrip() - else: - return "0,0,0,0,0,0" - except Exception as e: - return jsonify(type='danger', msg=str(e)) - elif request.json['cmd'] == 'sieve_list' and request.json['username']: - try: - for container in docker_client.containers.list(filters={"id": container_id}): - sieve_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm sieve list -u '" + request.json['username'].replace("'", "'\\''") + "'"], user='vmail') - return sieve_return.output - except Exception as e: - return jsonify(type='danger', msg=str(e)) - elif request.json['cmd'] == 'sieve_print' and request.json['script_name'] and request.json['username']: - try: - for container in docker_client.containers.list(filters={"id": container_id}): - sieve_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm sieve get -u '" + request.json['username'].replace("'", "'\\''") + "' '" + request.json['script_name'].replace("'", "'\\''") + "'"], user='vmail') - return sieve_return.output - except Exception as e: - return jsonify(type='danger', msg=str(e)) - elif request.json['cmd'] == 'worker_password' and request.json['raw']: - try: - for container in docker_client.containers.list(filters={"id": container_id}): - hash = container.exec_run(["/bin/bash", "-c", "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null"], user='_rspamd') - if hash.exit_code == 0: - hash_stdout = str(hash.output) - for line in hash_stdout.split("\n"): - if '$2$' in line: - hash = line.strip() - f = open("/access.inc", "w") - f.write('enable_password = "' + re.sub('[^0-9a-zA-Z\$]+', '', hash.rstrip()) + '";\n') - f.close() - container.restart() - return jsonify(type='success', msg='command completed successfully') - else: - return jsonify(type='danger', msg='command did not complete, exit code was ' + int(hash.exit_code)) - except Exception as e: - return jsonify(type='danger', msg=str(e)) - elif request.json['cmd'] == 'mailman_password' and request.json['email'] and request.json['passwd']: - try: - for container in docker_client.containers.list(filters={"id": container_id}): - add_su = container.exec_run(["/bin/bash", "-c", "/opt/mm_web/add_su.py '" + request.json['passwd'].replace("'", "'\\''") + "' '" + request.json['email'].replace("'", "'\\''") + "'"], user='mailman') - if add_su.exit_code == 0: - return jsonify(type='success', msg='command completed successfully') - else: - return jsonify(type='danger', msg='command did not complete, exit code was ' + int(add_su.exit_code)) - except Exception as e: - return jsonify(type='danger', msg=str(e)) + if request.json['cmd'] == 'mailq': + if 'items' in request.json: + r = re.compile("^[0-9a-fA-F]+$") + filtered_qids = filter(r.match, request.json['items']) + if filtered_qids: + if request.json['task'] == 'delete': + flagged_qids = ['-d %s' % i for i in filtered_qids] + sanitized_string = str(' '.join(flagged_qids)); + try: + for container in docker_client.containers.list(filters={"id": container_id}): + postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string]) + return exec_run_handler('generic', postsuper_r) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if request.json['task'] == 'hold': + flagged_qids = ['-h %s' % i for i in filtered_qids] + sanitized_string = str(' '.join(flagged_qids)); + try: + for container in docker_client.containers.list(filters={"id": container_id}): + postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string]) + return exec_run_handler('generic', postsuper_r) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if request.json['task'] == 'unhold': + flagged_qids = ['-H %s' % i for i in filtered_qids] + sanitized_string = str(' '.join(flagged_qids)); + try: + for container in docker_client.containers.list(filters={"id": container_id}): + postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string]) + return exec_run_handler('generic', postsuper_r) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if request.json['task'] == 'deliver': + flagged_qids = ['-i %s' % i for i in filtered_qids] + try: + for container in docker_client.containers.list(filters={"id": container_id}): + for i in flagged_qids: + postqueue_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postqueue " + i], user='postfix') + # todo: check each exit code + return jsonify(type='success', msg=str("Scheduled immediate delivery")) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'list': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + mailq_return = container.exec_run(["/usr/sbin/postqueue", "-j"], user='postfix') + return exec_run_handler('utf8_text_only', mailq_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'flush': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + postqueue_r = container.exec_run(["/usr/sbin/postqueue", "-f"], user='postfix') + return exec_run_handler('generic', postqueue_r) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'super_delete': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + postsuper_r = container.exec_run(["/usr/sbin/postsuper", "-d", "ALL"]) + return exec_run_handler('generic', postsuper_r) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif request.json['cmd'] == 'system': + if request.json['task'] == 'fts_rescan': + if 'username' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + rescan_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm fts rescan -u '" + request.json['username'].replace("'", "'\\''") + "'"], user='vmail') + if rescan_return.exit_code == 0: + return jsonify(type='success', msg='fts_rescan: rescan triggered') + else: + return jsonify(type='warning', msg='fts_rescan error') + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if 'all' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + rescan_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm fts rescan -A"], user='vmail') + if rescan_return.exit_code == 0: + return jsonify(type='success', msg='fts_rescan: rescan triggered') + else: + return jsonify(type='warning', msg='fts_rescan error') + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'df': + if 'dir' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + df_return = container.exec_run(["/bin/bash", "-c", "/bin/df -H '" + request.json['dir'].replace("'", "'\\''") + "' | /usr/bin/tail -n1 | /usr/bin/tr -s [:blank:] | /usr/bin/tr ' ' ','"], user='nobody') + if df_return.exit_code == 0: + return df_return.output.rstrip() + else: + return "0,0,0,0,0,0" + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'mysql_upgrade': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + sql_shell = container.exec_run(["/bin/bash"], stdin=True, socket=True, user='mysql') + upgrade_cmd = "/usr/bin/mysql_upgrade -uroot -p'" + os.environ['DBROOT'].replace("'", "'\\''") + "'\n" + sql_socket = sql_shell.output; + try : + sql_socket.sendall(upgrade_cmd.encode('utf-8')) + sql_socket.shutdown(socket.SHUT_WR) + except socket.error: + return jsonify(type='danger', msg=str('socket error')) + worker_response = recv_socket_data(sql_socket) + matched = False + for line in worker_response.split("\n"): + if 'is already upgraded to' in line: + matched = True + if matched: + return jsonify(type='success', msg='mysql_upgrade: already upgraded') + else: + container.restart() + return jsonify(type='warning', msg='mysql_upgrade: upgrade was applied') + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif request.json['cmd'] == 'reload': + if request.json['task'] == 'dovecot': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + reload_return = container.exec_run(["/bin/bash", "-c", "/usr/local/sbin/dovecot reload"]) + return exec_run_handler('generic', reload_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if request.json['task'] == 'postfix': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + reload_return = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postfix reload"]) + return exec_run_handler('generic', reload_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + if request.json['task'] == 'nginx': + try: + for container in docker_client.containers.list(filters={"id": container_id}): + reload_return = container.exec_run(["/bin/sh", "-c", "/usr/sbin/nginx -s reload"]) + return exec_run_handler('generic', reload_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif request.json['cmd'] == 'sieve': + if request.json['task'] == 'list': + if 'username' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + sieve_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm sieve list -u '" + request.json['username'].replace("'", "'\\''") + "'"]) + return exec_run_handler('utf8_text_only', sieve_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + elif request.json['task'] == 'print': + if 'username' in request.json and 'script_name' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + sieve_return = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm sieve get -u '" + request.json['username'].replace("'", "'\\''") + "' '" + request.json['script_name'].replace("'", "'\\''") + "'"]) + return exec_run_handler('utf8_text_only', sieve_return) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif request.json['cmd'] == 'maildir': + if request.json['task'] == 'cleanup': + if 'maildir' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + sane_name = re.sub(r'\W+', '', request.json['maildir']) + maildir_cleanup = container.exec_run(["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"], user='vmail') + return exec_run_handler('generic', maildir_cleanup) + except Exception as e: + return jsonify(type='danger', msg=str(e)) + + elif request.json['cmd'] == 'rspamd': + if request.json['task'] == 'worker_password': + if 'raw' in request.json: + try: + for container in docker_client.containers.list(filters={"id": container_id}): + worker_shell = container.exec_run(["/bin/bash"], stdin=True, socket=True, user='_rspamd') + worker_cmd = "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null\n" + worker_socket = worker_shell.output; + try : + worker_socket.sendall(worker_cmd.encode('utf-8')) + worker_socket.shutdown(socket.SHUT_WR) + except socket.error: + return jsonify(type='danger', msg=str('socket error')) + worker_response = recv_socket_data(worker_socket) + matched = False + for line in worker_response.split("\n"): + if '$2$' in line: + matched = True + hash = line.strip() + hash_out = re.search('\$2\$.+$', hash).group(0) + f = open("/access.inc", "w") + f.write('enable_password = "' + re.sub('[^0-9a-zA-Z\$]+', '', hash_out.rstrip()) + '";\n') + f.close() + container.restart() + if matched: + return jsonify(type='success', msg='command completed successfully') + else: + return jsonify(type='danger', msg='command did not complete') + except Exception as e: + return jsonify(type='danger', msg=str(e)) else: return jsonify(type='danger', msg='Unknown command') @@ -137,11 +305,84 @@ class GracefulKiller: signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully) - def exit_gracefully(self,signum, frame): + def exit_gracefully(self, signum, frame): self.kill_now = True def startFlaskAPI(): - app.run(debug=False, host='0.0.0.0', port=8080, threaded=True) + create_self_signed_cert() + try: + ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + ctx.check_hostname = False + ctx.load_cert_chain(certfile='/cert.pem', keyfile='/key.pem') + except: + print "Cannot initialize TLS, retrying in 5s..." + time.sleep(5) + app.run(debug=False, host='0.0.0.0', port=443, threaded=True, ssl_context=ctx) + +def recv_socket_data(c_socket, timeout=10): + c_socket.setblocking(0) + total_data=[]; + data=''; + begin=time.time() + while True: + if total_data and time.time()-begin > timeout: + break + elif time.time()-begin > timeout*2: + break + try: + data = c_socket.recv(8192) + if data: + total_data.append(data) + #change the beginning time for measurement + begin=time.time() + else: + #sleep for sometime to indicate a gap + time.sleep(0.1) + break + except: + pass + return ''.join(total_data) + +def exec_run_handler(type, output): + if type == 'generic': + if output.exit_code == 0: + return jsonify(type='success', msg='command completed successfully') + else: + return jsonify(type='danger', msg='command failed: ' + output.output) + if type == 'utf8_text_only': + r = Response(response=output.output, status=200, mimetype="text/plain") + r.headers["Content-Type"] = "text/plain; charset=utf-8" + return r + +def create_self_signed_cert(): + success = False + while not success: + try: + pkey = crypto.PKey() + pkey.generate_key(crypto.TYPE_RSA, 2048) + cert = crypto.X509() + cert.get_subject().O = "mailcow" + cert.get_subject().CN = "dockerapi" + cert.set_serial_number(int(uuid.uuid4())) + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(10*365*24*60*60) + cert.set_issuer(cert.get_subject()) + cert.set_pubkey(pkey) + cert.sign(pkey, 'sha512') + cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) + pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey) + with os.fdopen(os.open('/cert.pem', os.O_WRONLY | os.O_CREAT, 0o644), 'w') as handle: + handle.write(cert) + with os.fdopen(os.open('/key.pem', os.O_WRONLY | os.O_CREAT, 0o600), 'w') as handle: + handle.write(pkey) + success = True + except: + time.sleep(1) + try: + os.remove('/cert.pem') + os.remove('/key.pem') + except OSError: + pass api.add_resource(containers_get, '/containers/json') api.add_resource(container_get, '/containers//json') diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index 03323914..c5517499 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -3,8 +3,8 @@ LABEL maintainer "Andre Peters " ARG DEBIAN_FRONTEND=noninteractive ENV LC_ALL C -ENV DOVECOT_VERSION 2.3.2.1 -ENV PIGEONHOLE_VERSION 0.5.2 +ENV DOVECOT_VERSION 2.3.5.1 +ENV PIGEONHOLE_VERSION 0.5.5 RUN apt-get update && apt-get -y --no-install-recommends install \ automake \ @@ -14,6 +14,9 @@ RUN apt-get update && apt-get -y --no-install-recommends install \ cpanminus \ curl \ default-libmysqlclient-dev \ + dnsutils \ + gettext \ + jq \ libjson-webtoken-perl \ libcgi-pm-perl \ libcrypt-openssl-rsa-perl \ @@ -38,6 +41,7 @@ RUN apt-get update && apt-get -y --no-install-recommends install \ libio-socket-ssl-perl \ libio-tee-perl \ libipc-run-perl \ + libldap2-dev \ liblockfile-simple-perl \ liblz-dev \ liblz4-dev \ @@ -60,6 +64,10 @@ RUN apt-get update && apt-get -y --no-install-recommends install \ libregexp-common-perl \ liburi-perl \ lzma-dev \ + python-html2text \ + python-jinja2 \ + python-mysql.connector \ + python-redis \ make \ mysql-client \ procps \ @@ -69,11 +77,10 @@ RUN apt-get update && apt-get -y --no-install-recommends install \ syslog-ng \ syslog-ng-core \ syslog-ng-mod-redis \ - && rm -rf /var/lib/apt/lists/* - -RUN curl https://www.dovecot.org/releases/2.3/dovecot-$DOVECOT_VERSION.tar.gz | tar xvz \ + && rm -rf /var/lib/apt/lists/* \ + && curl https://www.dovecot.org/releases/2.3/dovecot-$DOVECOT_VERSION.tar.gz | tar xvz \ && cd dovecot-$DOVECOT_VERSION \ - && ./configure --with-solr --with-mysql --with-lzma --with-lz4 --with-ssl=openssl --with-notify=inotify --with-storages=mdbox,sdbox,maildir,mbox,imapc,pop3c --with-bzlib --with-zlib \ + && ./configure --with-solr --with-mysql --with-ldap --with-lzma --with-lz4 --with-ssl=openssl --with-notify=inotify --with-storages=mdbox,sdbox,maildir,mbox,imapc,pop3c --with-bzlib --with-zlib --enable-hardening \ && make -j3 \ && make install \ && make clean \ @@ -85,12 +92,18 @@ RUN curl https://www.dovecot.org/releases/2.3/dovecot-$DOVECOT_VERSION.tar.gz | && make install \ && make clean \ && cd .. \ - && rm -rf dovecot-2.3-pigeonhole-$PIGEONHOLE_VERSION - -RUN cpanm Data::Uniqid Mail::IMAPClient String::Util -RUN echo '* * * * * root /usr/local/bin/imapsync_cron.pl' > /etc/cron.d/imapsync -RUN echo '30 3 * * * vmail /usr/local/bin/doveadm quota recalc -A' > /etc/cron.d/dovecot-sync -RUN echo '* * * * * root /usr/local/bin/trim_logs.sh >> /dev/stdout 2>&1' > /etc/cron.d/trim_logs + && rm -rf dovecot-2.3-pigeonhole-$PIGEONHOLE_VERSION \ + && cpanm Data::Uniqid Mail::IMAPClient String::Util \ + && groupadd -g 5000 vmail \ + && groupadd -g 401 dovecot \ + && groupadd -g 402 dovenull \ + && useradd -g vmail -u 5000 vmail -d /var/vmail \ + && useradd -c "Dovecot unprivileged user" -d /dev/null -u 401 -g dovecot -s /bin/false dovecot \ + && useradd -c "Dovecot login user" -d /dev/null -u 402 -g dovenull -s /bin/false dovenull \ + && touch /etc/default/locale \ + && apt-get purge -y build-essential automake autotools-dev default-libmysqlclient-dev libbz2-dev libcurl4-openssl-dev libexpat1-dev liblz-dev liblz4-dev liblzma-dev libpam-dev libssl-dev lzma-dev \ + && apt-get autoremove --purge -y \ + && rm -rf /tmp/* /var/tmp/* COPY trim_logs.sh /usr/local/bin/trim_logs.sh COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf @@ -101,31 +114,13 @@ COPY report-spam.sieve /usr/local/lib/dovecot/sieve/report-spam.sieve COPY report-ham.sieve /usr/local/lib/dovecot/sieve/report-ham.sieve COPY rspamd-pipe-ham /usr/local/lib/dovecot/sieve/rspamd-pipe-ham COPY rspamd-pipe-spam /usr/local/lib/dovecot/sieve/rspamd-pipe-spam +COPY sa-rules.sh /usr/local/bin/sa-rules.sh +COPY maildir_gc.sh /usr/local/bin/maildir_gc.sh COPY docker-entrypoint.sh / COPY supervisord.conf /etc/supervisor/supervisord.conf - -RUN chmod +x /usr/local/lib/dovecot/sieve/rspamd-pipe-ham \ - /usr/local/lib/dovecot/sieve/rspamd-pipe-spam \ - /usr/local/bin/imapsync_cron.pl \ - /usr/local/bin/postlogin.sh \ - /usr/local/bin/imapsync \ - /usr/local/bin/trim_logs.sh - -RUN groupadd -g 5000 vmail \ - && groupadd -g 401 dovecot \ - && groupadd -g 402 dovenull \ - && useradd -g vmail -u 5000 vmail -d /var/vmail \ - && useradd -c "Dovecot unprivileged user" -d /dev/null -u 401 -g dovecot -s /bin/false dovecot \ - && useradd -c "Dovecot login user" -d /dev/null -u 402 -g dovenull -s /bin/false dovenull - -RUN touch /etc/default/locale -RUN apt-get purge -y build-essential automake autotools-dev default-libmysqlclient-dev libbz2-dev libcurl4-openssl-dev libexpat1-dev liblz-dev liblz4-dev liblzma-dev libpam-dev libssl-dev lzma-dev \ - && apt-get autoremove --purge -y +COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh +COPY quarantine_notify.py /usr/local/bin/quarantine_notify.py +COPY quota_notify.py /usr/local/bin/quota_notify.py ENTRYPOINT ["/docker-entrypoint.sh"] CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf - -RUN rm -rf \ - /tmp/* \ - /var/tmp/* - diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index 50e91a12..7034fc08 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -2,28 +2,35 @@ set -e # Wait for MySQL to warm-up -while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do +while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do echo "Waiting for database to come up..." sleep 2 done -# Hard-code env vars to scripts due to cron not passing them to the perl script -sed -i "/^\$DBUSER/c\\\$DBUSER='${DBUSER}';" /usr/local/bin/imapsync_cron.pl -sed -i "/^\$DBPASS/c\\\$DBPASS='${DBPASS}';" /usr/local/bin/imapsync_cron.pl -sed -i "/^\$DBNAME/c\\\$DBNAME='${DBNAME}';" /usr/local/bin/imapsync_cron.pl -sed -i "s/LOG_LINES/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh +# Hard-code env vars to scripts due to cron not passing them to the scripts +sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/imapsync_cron.pl +sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/imapsync_cron.pl +sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/imapsync_cron.pl + +sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/quarantine_notify.py +sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/quarantine_notify.py +sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/quarantine_notify.py + +sed -i "s/__LOG_LINES__/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh # Create missing directories [[ ! -d /usr/local/etc/dovecot/sql/ ]] && mkdir -p /usr/local/etc/dovecot/sql/ +[[ ! -d /var/vmail/_garbage ]] && mkdir -p /var/vmail/_garbage [[ ! -d /var/vmail/sieve ]] && mkdir -p /var/vmail/sieve [[ ! -d /etc/sogo ]] && mkdir -p /etc/sogo +[[ ! -d /var/volatile ]] && mkdir -p /var/volatile # Set Dovecot sql config parameters, escape " in db password DBPASS=$(echo ${DBPASS} | sed 's/"/\\"/g') # Create quota dict for Dovecot cat < /usr/local/etc/dovecot/sql/dovecot-dict-sql-quota.conf -connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" +connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" map { pattern = priv/quota/storage table = quota2 @@ -40,7 +47,7 @@ EOF # Create dict used for sieve pre and postfilters cat < /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf -connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" +connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" map { pattern = priv/sieve/name/\$script_name table = sieve_before @@ -62,7 +69,7 @@ map { EOF cat < /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf -connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" +connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" map { pattern = priv/sieve/name/\$script_name table = sieve_after @@ -83,39 +90,72 @@ map { } EOF +echo -n ${ACL_ANYONE} > /usr/local/etc/dovecot/acl_anyone + +if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then +echo -n 'quota acl zlib listescape mail_crypt mail_crypt_acl mail_log notify' > /usr/local/etc/dovecot/mail_plugins +echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve listescape mail_crypt mail_crypt_acl notify mail_log' > /usr/local/etc/dovecot/mail_plugins_imap +echo -n 'quota sieve acl zlib listescape mail_crypt mail_crypt_acl' > /usr/local/etc/dovecot/mail_plugins_lmtp +else +echo -n 'quota acl zlib listescape mail_crypt mail_crypt_acl mail_log notify fts fts_solr' > /usr/local/etc/dovecot/mail_plugins +echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve listescape mail_crypt mail_crypt_acl notify mail_log fts fts_solr' > /usr/local/etc/dovecot/mail_plugins_imap +echo -n 'quota sieve acl zlib listescape mail_crypt mail_crypt_acl fts fts_solr' > /usr/local/etc/dovecot/mail_plugins_lmtp +fi +chmod 644 /usr/local/etc/dovecot/mail_plugins /usr/local/etc/dovecot/mail_plugins_imap /usr/local/etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl -# Create userdb dict for Dovecot cat < /usr/local/etc/dovecot/sql/dovecot-dict-sql-userdb.conf driver = mysql -connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" -user_query = SELECT CONCAT('maildir:/var/vmail/',maildir) AS mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1' +connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" +user_query = SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.mailbox_format')), mailbox_path_prefix, '%d/%n/${MAILDIR_SUB}:VOLATILEDIR=/var/volatile/%u') AS mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1' iterate_query = SELECT username FROM mailbox WHERE active='1'; EOF # Create pass dict for Dovecot cat < /usr/local/etc/dovecot/sql/dovecot-dict-sql-passdb.conf driver = mysql -connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" +connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}" default_pass_scheme = SSHA256 -password_query = SELECT password FROM mailbox WHERE username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_EXTRACT(attributes, '$.force_pw_update') NOT LIKE '%%1%%' +password_query = SELECT password FROM mailbox WHERE active = '1' AND username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_EXTRACT(attributes, '$.force_pw_update') NOT LIKE '%%1%%' EOF # Create global sieve_after script cat /usr/local/etc/dovecot/sieve_after > /var/vmail/sieve/global.sieve -# Check permissions of vmail directory. +# Check permissions of vmail/attachments directory. # Do not do this every start-up, it may take a very long time. So we use a stat check here. if [[ $(stat -c %U /var/vmail/) != "vmail" ]] ; then chown -R vmail:vmail /var/vmail ; fi +if [[ $(stat -c %U /var/vmail/_garbage) != "vmail" ]] ; then chown -R vmail:vmail /var/vmail/_garbage ; fi +if [[ $(stat -c %U /var/attachments) != "vmail" ]] ; then chown -R vmail:vmail /var/attachments ; fi + +# Cleanup random user maildirs +rm -rf /var/vmail/mailcow.local/* + # Create random master for SOGo sieve features RAND_USER=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 16 | head -n 1) RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 24 | head -n 1) -echo ${RAND_USER}@mailcow.local:$(doveadm pw -s SHA1 -p ${RAND_PASS}) > /usr/local/etc/dovecot/dovecot-master.passwd +echo ${RAND_USER}@mailcow.local:{SHA1}$(echo -n ${RAND_PASS} | sha1sum | awk '{print $1}') > /usr/local/etc/dovecot/dovecot-master.passwd +echo ${RAND_USER}@mailcow.local::5000:5000:::: > /usr/local/etc/dovecot/dovecot-master.userdb echo ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/sieve.creds +if [[ "${ALLOW_ADMIN_EMAIL_LOGIN}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + # Create random master Password for SOGo 'login as user' via proxy auth + RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1) + echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass + cat < /usr/local/etc/dovecot/sogo-sso.conf +passdb { + driver = static + args = allow_real_nets=${IPV4_NETWORK}.248/32 password={plain}${RAND_PASS} +} +EOF +else + rm -f /usr/local/etc/dovecot/sogo-sso.pass + rm -f /usr/local/etc/dovecot/sogo-sso.conf +fi + # 401 is user dovecot -if [[ ! -f /mail_crypt/ecprivkey.pem || ! -f /mail_crypt/ecpubkey.pem ]]; then +if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem openssl pkey -in /mail_crypt/ecprivkey.pem -pubout -out /mail_crypt/ecpubkey.pem chown 401 /mail_crypt/ecprivkey.pem /mail_crypt/ecpubkey.pem @@ -129,7 +169,32 @@ sievec /usr/local/lib/dovecot/sieve/report-spam.sieve sievec /usr/local/lib/dovecot/sieve/report-ham.sieve # Fix permissions +chown root:root /usr/local/etc/dovecot/sql/*.conf +chown root:dovecot /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve* /usr/local/etc/dovecot/sql/dovecot-dict-sql-quota* +chmod 640 /usr/local/etc/dovecot/sql/*.conf chown -R vmail:vmail /var/vmail/sieve +chown -R vmail:vmail /var/volatile +adduser vmail tty +chmod g+rw /dev/console +chmod +x /usr/local/lib/dovecot/sieve/rspamd-pipe-ham \ + /usr/local/lib/dovecot/sieve/rspamd-pipe-spam \ + /usr/local/bin/imapsync_cron.pl \ + /usr/local/bin/postlogin.sh \ + /usr/local/bin/imapsync \ + /usr/local/bin/trim_logs.sh \ + /usr/local/bin/sa-rules.sh \ + /usr/local/bin/maildir_gc.sh \ + /usr/local/sbin/stop-supervisor.sh \ + /usr/local/bin/quota_notify.py + +# Setup cronjobs +echo '* * * * * root /usr/local/bin/imapsync_cron.pl 2>&1 | /usr/bin/logger' > /etc/cron.d/imapsync +echo '30 3 * * * vmail /usr/local/bin/doveadm quota recalc -A' > /etc/cron.d/dovecot-sync +echo '* * * * * vmail /usr/local/bin/trim_logs.sh >> /dev/console 2>&1' > /etc/cron.d/trim_logs +echo '25 * * * * vmail /usr/local/bin/maildir_gc.sh >> /dev/console 2>&1' > /etc/cron.d/maildir_gc +echo '30 1 * * * root /usr/local/bin/sa-rules.sh >> /dev/console 2>&1' > /etc/cron.d/sa-rules +echo '0 2 * * * root /usr/bin/curl http://solr:8983/solr/dovecot-fts/update?optimize=true >> /dev/console 2>&1' > /etc/cron.d/solr-optimize +echo '*/20 * * * * vmail /usr/local/bin/quarantine_notify.py >> /dev/console 2>&1' > /etc/cron.d/quarantine_notify # Fix more than 1 hardlink issue touch /etc/crontab /etc/cron.*/* @@ -139,7 +204,13 @@ touch /etc/crontab /etc/cron.*/* # Clean stopped imapsync jobs rm -f /tmp/imapsync_busy.lock -IMAPSYNC_TABLE=$(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs) -[[ ! -z ${IMAPSYNC_TABLE} ]] && mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'" +IMAPSYNC_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs) +[[ ! -z ${IMAPSYNC_TABLE} ]] && mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'" + +# Envsubst maildir_gc +echo "$(envsubst < /usr/local/bin/maildir_gc.sh)" > /usr/local/bin/maildir_gc.sh + +# Collect SA rules once now +/usr/local/bin/sa-rules.sh exec "$@" diff --git a/data/Dockerfiles/dovecot/imapsync_cron.pl b/data/Dockerfiles/dovecot/imapsync_cron.pl index be5cb411..4fad97ab 100755 --- a/data/Dockerfiles/dovecot/imapsync_cron.pl +++ b/data/Dockerfiles/dovecot/imapsync_cron.pl @@ -18,18 +18,20 @@ if ($imapsync_running eq 1) exit; } -sub qqw($) { split /\s+/, $_[0] } - -$DBNAME = ''; -$DBUSER = ''; -$DBPASS = ''; +sub qqw($) { + my @values = split('(?=--)', $_[0]); + foreach my $val (@values) { + $val=trim($val); + } + return @values +} $run_dir="/tmp"; -$dsn = "DBI:mysql:database=" . $DBNAME . ";host=mysql"; +$dsn = 'DBI:mysql:database=__DBNAME__;mysql_socket=/var/run/mysqld/mysqld.sock'; $lock_file = $run_dir . "/imapsync_busy"; $lockmgr = LockFile::Simple->make(-autoclean => 1, -max => 1); $lockmgr->lock($lock_file) || die "can't lock ${lock_file}"; -$dbh = DBI->connect($dsn, $DBUSER, $DBPASS, { +$dbh = DBI->connect($dsn, '__DBUSER__', '__DBPASS__', { mysql_auto_reconnect => 1, mysql_enable_utf8mb4 => 1 }); diff --git a/data/Dockerfiles/dovecot/maildir_gc.sh b/data/Dockerfiles/dovecot/maildir_gc.sh new file mode 100755 index 00000000..24c1e461 --- /dev/null +++ b/data/Dockerfiles/dovecot/maildir_gc.sh @@ -0,0 +1,2 @@ +#/bin/bash +[ -d /var/vmail/_garbage/ ] && /usr/bin/find /var/vmail/_garbage/ -mindepth 1 -maxdepth 1 -type d -cmin +${MAILDIR_GC_TIME} -exec rm -r {} \; diff --git a/data/Dockerfiles/dovecot/postlogin.sh b/data/Dockerfiles/dovecot/postlogin.sh index 343910ff..01a45f31 100755 --- a/data/Dockerfiles/dovecot/postlogin.sh +++ b/data/Dockerfiles/dovecot/postlogin.sh @@ -1,4 +1,3 @@ #!/bin/sh - export MASTER_USER=$USER exec "$@" diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py new file mode 100755 index 00000000..28a7aabe --- /dev/null +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -0,0 +1,125 @@ +#!/usr/bin/python + +import smtplib +import os +import mysql.connector +from email.MIMEMultipart import MIMEMultipart +from email.MIMEText import MIMEText +from email.Utils import COMMASPACE, formatdate +import cgi +import jinja2 +from jinja2 import Template +import json +import redis +import time +import html2text +import socket + +while True: + try: + r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0) + r.ping() + except Exception as ex: + print '%s - trying again...' % (ex) + time.sleep(3) + else: + break + +time_now = int(time.time()) + +def query_mysql(query, headers = True, update = False): + while True: + try: + cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user='__DBUSER__', passwd='__DBPASS__', database='__DBNAME__', charset="utf8") + except Exception as ex: + print '%s - trying again...' % (ex) + time.sleep(3) + else: + break + cur = cnx.cursor() + cur.execute(query) + if not update: + result = [] + columns = tuple( [d[0].decode('utf8') for d in cur.description] ) + for row in cur: + if headers: + result.append(dict(zip(columns, row))) + else: + result.append(row) + cur.close() + cnx.close() + return result + else: + cnx.commit() + cur.close() + cnx.close() + +def notify_rcpt(rcpt, msg_count, quarantine_acl): + meta_query = query_mysql('SELECT SHA2(CONCAT(id, qid), 256) AS qhash, id, subject, score, sender, created FROM quarantine WHERE notified = 0 AND rcpt = "%s"' % (rcpt)) + if r.get('Q_HTML'): + try: + template = Template(r.get('Q_HTML')) + except: + print "Error: Cannot parse quarantine template, falling back to default template." + with open('/templates/quarantine.tpl') as file_: + template = Template(file_.read()) + else: + with open('/templates/quarantine.tpl') as file_: + template = Template(file_.read()) + html = template.render(meta=meta_query, counter=msg_count, hostname=socket.gethostname(), quarantine_acl=quarantine_acl) + text = html2text.html2text(html) + count = 0 + while count < 15: + try: + server = smtplib.SMTP('postfix', 590, 'quarantine') + server.ehlo() + msg = MIMEMultipart('alternative') + msg['From'] = r.get('Q_SENDER') or "quarantine@localhost" + msg['Subject'] = r.get('Q_SUBJ') or "Spam Quarantine Notification" + msg['Date'] = formatdate(localtime = True) + text_part = MIMEText(text, 'plain', 'utf-8') + html_part = MIMEText(html, 'html', 'utf-8') + msg.attach(text_part) + msg.attach(html_part) + msg['To'] = str(rcpt) + text = msg.as_string() + server.sendmail(msg['From'], msg['To'], text) + server.quit() + for res in meta_query: + query_mysql('UPDATE quarantine SET notified = 1 WHERE id = "%d"' % (res['id']), update = True) + r.hset('Q_LAST_NOTIFIED', record['rcpt'], time_now) + break + except Exception as ex: + print '%s' % (ex) + time.sleep(3) + +records = query_mysql('SELECT IFNULL(user_acl.quarantine, 0) AS quarantine_acl, count(id) AS counter, rcpt FROM quarantine LEFT OUTER JOIN user_acl ON user_acl.username = rcpt WHERE notified = 0 AND rcpt in (SELECT username FROM mailbox) GROUP BY rcpt') + +for record in records: + attrs = '' + attrs_json = '' + try: + last_notification = int(r.hget('Q_LAST_NOTIFIED', record['rcpt'])) + if last_notification > time_now: + print 'Last notification is > time now, assuming never' + last_notification = 0 + except Exception as ex: + print 'Could not determine last notification for %s, assuming never' % (record['rcpt']) + last_notification = 0 + attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt'])) + attrs = json.loads(str(attrs_json[0]['attributes'])) + if attrs['quarantine_notification'] not in ('hourly', 'daily', 'weekly', 'never'): + print 'Abnormal quarantine_notification value' + continue + if attrs['quarantine_notification'] == 'hourly': + if last_notification == 0 or (last_notification + 3600) < time_now: + print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) + elif attrs['quarantine_notification'] == 'daily': + if last_notification == 0 or (last_notification + 86400) < time_now: + print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) + elif attrs['quarantine_notification'] == 'weekly': + if last_notification == 0 or (last_notification + 604800) < time_now: + print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) diff --git a/data/Dockerfiles/dovecot/quota_notify.py b/data/Dockerfiles/dovecot/quota_notify.py new file mode 100755 index 00000000..f5df7639 --- /dev/null +++ b/data/Dockerfiles/dovecot/quota_notify.py @@ -0,0 +1,72 @@ +#!/usr/bin/python + +import smtplib +import os +from email.MIMEMultipart import MIMEMultipart +from email.MIMEText import MIMEText +from email.Utils import COMMASPACE, formatdate +import jinja2 +from jinja2 import Template +import redis +import time +import sys +import html2text +from subprocess import Popen, PIPE, STDOUT + +if len(sys.argv) > 2: + percent = int(sys.argv[1]) + username = str(sys.argv[2]) +else: + print "Args missing" + sys.exit(1) + +while True: + try: + r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0) + r.ping() + except Exception as ex: + print '%s - trying again...' % (ex) + time.sleep(3) + else: + break + +if r.get('QW_HTML'): + try: + template = Template(r.get('QW_HTML')) + except: + print "Error: Cannot parse quarantine template, falling back to default template." + with open('/templates/quota.tpl') as file_: + template = Template(file_.read()) +else: + with open('/templates/quota.tpl') as file_: + template = Template(file_.read()) + +html = template.render(username=username, percent=percent) +text = html2text.html2text(html) + +try: + msg = MIMEMultipart('alternative') + msg['From'] = r.get('QW_SENDER') or "quota-warning@localhost" + msg['Subject'] = r.get('QW_SUBJ') or "Quota warning" + msg['Date'] = formatdate(localtime = True) + text_part = MIMEText(text, 'plain', 'utf-8') + html_part = MIMEText(html, 'html', 'utf-8') + msg.attach(text_part) + msg.attach(html_part) + msg['To'] = username + p = Popen(['/usr/local/libexec/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) + p.communicate(input=msg.as_string()) + +except Exception as ex: + print 'Failed to send quota notification: %s' % (ex) + sys.exit(1) + +try: + sys.stdout.close() +except: + pass + +try: + sys.stderr.close() +except: + pass diff --git a/data/Dockerfiles/dovecot/rspamd-pipe-ham b/data/Dockerfiles/dovecot/rspamd-pipe-ham index 9d961be0..9b26817c 100755 --- a/data/Dockerfiles/dovecot/rspamd-pipe-ham +++ b/data/Dockerfiles/dovecot/rspamd-pipe-ham @@ -3,7 +3,7 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnham -cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham +cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd exit 0 diff --git a/data/Dockerfiles/dovecot/rspamd-pipe-spam b/data/Dockerfiles/dovecot/rspamd-pipe-spam index 3b9e3497..d06aa919 100755 --- a/data/Dockerfiles/dovecot/rspamd-pipe-spam +++ b/data/Dockerfiles/dovecot/rspamd-pipe-spam @@ -3,7 +3,7 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnspam -cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam +cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd exit 0 diff --git a/data/Dockerfiles/dovecot/sa-rules.sh b/data/Dockerfiles/dovecot/sa-rules.sh new file mode 100755 index 00000000..0cea240c --- /dev/null +++ b/data/Dockerfiles/dovecot/sa-rules.sh @@ -0,0 +1,25 @@ +#!/bin/bash +[[ ! -d /tmp/sa-rules-heinlein ]] && mkdir -p /tmp/sa-rules-heinlein +if [[ ! -f /etc/rspamd/custom/sa-rules-heinlein ]]; then + HASH_SA_RULES=0 +else + HASH_SA_RULES=$(cat /etc/rspamd/custom/sa-rules-heinlein | md5sum | cut -d' ' -f1) +fi + +curl --connect-timeout 15 --max-time 30 http://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"').tar.gz --output /tmp/sa-rules.tar.gz +if [[ -f /tmp/sa-rules.tar.gz ]]; then + tar xfvz /tmp/sa-rules.tar.gz -C /tmp/sa-rules-heinlein + # create complete list of rules in a single file + cat /tmp/sa-rules-heinlein/*cf > /etc/rspamd/custom/sa-rules-heinlein + # Only restart rspamd-mailcow when rules changed + if [[ $(cat /etc/rspamd/custom/sa-rules-heinlein | md5sum | cut -d' ' -f1) != ${HASH_SA_RULES} ]]; then + CONTAINER_NAME=rspamd-mailcow + CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | \ + jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | \ + jq -rc "select( .name | tostring | contains(\"${CONTAINER_NAME}\")) | .id") + if [[ ! -z ${CONTAINER_ID} ]]; then + curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi/containers/${CONTAINER_ID}/restart + fi + fi +fi +rm -rf /tmp/sa-rules-heinlein /tmp/sa-rules.tar.gz diff --git a/data/Dockerfiles/dovecot/stop-supervisor.sh b/data/Dockerfiles/dovecot/stop-supervisor.sh new file mode 100755 index 00000000..5394490c --- /dev/null +++ b/data/Dockerfiles/dovecot/stop-supervisor.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +printf "READY\n"; + +while read line; do + echo "Processing Event: $line" >&2; + kill -3 $(cat "/var/run/supervisord.pid") +done < /dev/stdin diff --git a/data/Dockerfiles/dovecot/supervisord.conf b/data/Dockerfiles/dovecot/supervisord.conf index f517c388..2e3026a0 100644 --- a/data/Dockerfiles/dovecot/supervisord.conf +++ b/data/Dockerfiles/dovecot/supervisord.conf @@ -1,6 +1,7 @@ [supervisord] nodaemon=true user=root +pidfile=/var/run/supervisord.pid [program:syslog-ng] command=/usr/sbin/syslog-ng --foreground --no-caps @@ -17,3 +18,7 @@ autorestart=true [program:cron] command=/usr/sbin/cron -f autorestart=true + +[eventlistener:processes] +command=/usr/local/sbin/stop-supervisor.sh +events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL diff --git a/data/Dockerfiles/dovecot/trim_logs.sh b/data/Dockerfiles/dovecot/trim_logs.sh index b8da9740..2fec55d3 100755 --- a/data/Dockerfiles/dovecot/trim_logs.sh +++ b/data/Dockerfiles/dovecot/trim_logs.sh @@ -1,8 +1,18 @@ #!/bin/bash +catch_non_zero() { + CMD=${1} + ${CMD} > /dev/null + EC=$? + if [ ${EC} -ne 0 ]; then + echo "Command ${CMD} failed to execute, exit code was ${EC}" + fi +} +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM ACME_LOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM SOGO_LOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM NETFILTER_LOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM API_LOG 0 __LOG_LINES__" +catch_non_zero "/usr/bin/redis-cli -h redis LTRIM RL_LOG 0 __LOG_LINES__" -redis-cli -h redis LTRIM ACME_LOG 0 LOG_LINES -redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 LOG_LINES -redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 LOG_LINES -redis-cli -h redis LTRIM SOGO_LOG 0 LOG_LINES -redis-cli -h redis LTRIM NETFILTER_LOG 0 LOG_LINES -redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 LOG_LINES diff --git a/data/Dockerfiles/netfilter/Dockerfile b/data/Dockerfiles/netfilter/Dockerfile index aab9b1d3..92eaa39f 100644 --- a/data/Dockerfiles/netfilter/Dockerfile +++ b/data/Dockerfiles/netfilter/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.8 +FROM alpine:3.9 LABEL maintainer "Andre Peters " ENV XTABLES_LIBDIR /usr/lib/xtables diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 9bf4a084..910679c6 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -10,7 +10,6 @@ from random import randint from threading import Thread from threading import Lock import redis -import time import json import iptc @@ -29,10 +28,11 @@ pubsub = r.pubsub() RULES = {} RULES[1] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed' RULES[2] = '-login: Disconnected \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),' -RULES[3] = '-login: Aborted login \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' -RULES[4] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' -RULES[5] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked' -RULES[6] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)' +RULES[3] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' +RULES[4] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked' +RULES[5] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)' +RULES[6] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+' +#RULES[7] = '-login: Aborted login \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' bans = {} log = {} diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 3acfd09f..de31031a 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -1,11 +1,11 @@ -FROM php:7.2-fpm-alpine3.7 +FROM php:7.3-fpm-alpine3.8 LABEL maintainer "Andre Peters " -ENV APCU_PECL 5.1.11 +ENV APCU_PECL 5.1.16 ENV IMAGICK_PECL 3.4.3 -ENV MAILPARSE_PECL 3.0.2 -ENV MEMCACHED_PECL 3.0.4 -ENV REDIS_PECL 4.0.2 +#ENV MAILPARSE_PECL 3.0.2 +ENV MEMCACHED_PECL 3.1.3 +ENV REDIS_PECL 4.2.0 RUN apk add -U --no-cache autoconf \ bash \ @@ -14,12 +14,14 @@ RUN apk add -U --no-cache autoconf \ freetype \ freetype-dev \ g++ \ + git \ gettext-dev \ icu-dev \ icu-libs \ imagemagick \ imagemagick-dev \ imap-dev \ + jq \ libjpeg-turbo \ libjpeg-turbo-dev \ libmemcached-dev \ @@ -32,6 +34,7 @@ RUN apk add -U --no-cache autoconf \ libwebp-dev \ libxml2-dev \ libxpm-dev \ + libzip-dev \ make \ mysql-client \ openldap-dev \ @@ -41,14 +44,13 @@ RUN apk add -U --no-cache autoconf \ samba-client \ zlib-dev \ tzdata \ - && pear install channel://pear.php.net/Net_IDNA2-0.2.0 \ - channel://pear.php.net/Auth_SASL-1.1.0 \ - Net_IMAP \ - Net_Sieve \ - NET_SMTP \ - Mail_mime \ - && pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} mailparse-${MAILPARSE_PECL} \ - && docker-php-ext-enable apcu imagick mailparse memcached redis \ + && git clone https://github.com/php/pecl-mail-mailparse \ + && cd pecl-mail-mailparse \ + && pecl install package.xml \ + && cd .. \ + && rm -r pecl-mail-mailparse \ + && pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} \ + && docker-php-ext-enable apcu imagick memcached mailparse redis \ && pecl clear-cache \ && docker-php-ext-configure intl \ && docker-php-ext-configure gd \ diff --git a/data/Dockerfiles/phpfpm/docker-entrypoint.sh b/data/Dockerfiles/phpfpm/docker-entrypoint.sh index 44d46f74..bf055f3a 100755 --- a/data/Dockerfiles/phpfpm/docker-entrypoint.sh +++ b/data/Dockerfiles/phpfpm/docker-entrypoint.sh @@ -1,28 +1,67 @@ #!/bin/bash -set -e function array_by_comma { local IFS=","; echo "$*"; } # Wait for containers -while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do +while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do + echo "Waiting for SQL..." sleep 2 done until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do + echo "Waiting for Redis..." sleep 2 done +# Set a default release format + +if [[ -z $(redis-cli --raw -h redis-mailcow GET Q_RELEASE_FORMAT) ]]; then + redis-cli --raw -h redis-mailcow SET Q_RELEASE_FORMAT raw +fi + +# Check of mysql_upgrade + +CONTAINER_ID= +# Todo: Better check if upgrade failed +# This can happen due to a broken sogo_view +[ -s /mysql_upgrade_loop ] && SQL_LOOP_C=$(cat /mysql_upgrade_loop) +until [[ ! -z "${CONTAINER_ID}" ]] && [[ "${CONTAINER_ID}" =~ ^[[:alnum:]]*$ ]]; do + CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"mysql-mailcow\")) | .id" 2> /dev/null) +done +echo "MySQL @ ${CONTAINER_ID}" +SQL_UPGRADE_RETURN=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_upgrade"}' --silent -H 'Content-type: application/json' | jq -r .type) +if [[ ${SQL_UPGRADE_RETURN} == 'warning' ]]; then + if [ -z ${SQL_LOOP_C} ]; then + echo 1 > /mysql_upgrade_loop + echo "MySQL applied an upgrade, restarting PHP-FPM..." + exit 1 + else + rm /mysql_upgrade_loop + echo "MySQL was not applied previously, skipping. Restart php-fpm-mailcow to retry or run mysql_upgrade manually." + while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do + echo "Waiting for SQL to return..." + sleep 2 + done + fi +else + echo "MySQL is up-to-date" +fi + +# Trigger db init +echo "Running DB init..." +php -c /usr/local/etc/php -f /web/inc/init_db.inc.php + # Migrate domain map declare -a DOMAIN_ARR redis-cli -h redis-mailcow DEL DOMAIN_MAP while read line do DOMAIN_ARR+=("$line") -done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs) +done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs) while read line do DOMAIN_ARR+=("$line") -done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs) +done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs) if [[ ! -z ${DOMAIN_ARR} ]]; then for domain in "${DOMAIN_ARR[@]}"; do @@ -48,10 +87,9 @@ if [[ ${API_ALLOW_FROM} != "invalid" ]] && \ done VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]}) if [[ ! -z ${VALIDATED_IPS} ]]; then - mysql --host mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF -INSERT INTO api (username, api_key, active, allow_from) -SELECT username, "${API_KEY}", '1', "${VALIDATED_IPS}" FROM admin WHERE superadmin='1' AND active='1' -ON DUPLICATE KEY UPDATE active = '1', allow_from = "${VALIDATED_IPS}", api_key = "${API_KEY}"; + mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF +DELETE FROM api; +INSERT INTO api (api_key, active, allow_from) VALUES ("${API_KEY}", "1", "${VALIDATED_IPS}"); EOF fi fi diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index 9ad52fb2..05f2c3c7 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -48,6 +48,13 @@ COPY postfix.sh /opt/postfix.sh COPY rspamd-pipe-ham /usr/local/bin/rspamd-pipe-ham COPY rspamd-pipe-spam /usr/local/bin/rspamd-pipe-spam COPY whitelist_forwardinghosts.sh /usr/local/bin/whitelist_forwardinghosts.sh +COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh + +RUN chmod +x /opt/postfix.sh \ + /usr/local/bin/rspamd-pipe-ham \ + /usr/local/bin/rspamd-pipe-spam \ + /usr/local/bin/whitelist_forwardinghosts.sh \ + /usr/local/sbin/stop-supervisor.sh EXPOSE 588 diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 28e51ccd..d3e9ed0c 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -14,7 +14,7 @@ newaliases; cat < /opt/postfix/conf/sql/mysql_relay_recipient_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT DISTINCT CASE WHEN '%d' IN ( @@ -29,10 +29,18 @@ query = SELECT DISTINCT END AS result; EOF +cat < /opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf +user = ${DBUSER} +password = ${DBPASS} +hosts = unix:/var/run/mysqld/mysqld.sock +dbname = ${DBNAME} +query = SELECT CONCAT(policy, ' ', parameters) AS tls_policy FROM tls_policy_override WHERE active = '1' AND dest = '%s' +EOF + cat < /opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT IF(EXISTS( SELECT 'TLS_ACTIVE' FROM alias @@ -49,7 +57,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT GROUP_CONCAT(transport SEPARATOR '') AS transport_maps FROM ( @@ -77,26 +85,49 @@ query = SELECT GROUP_CONCAT(transport SEPARATOR '') AS transport_maps AS transport_view; EOF -cat < /opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf +cat < /opt/postfix/conf/sql/mysql_transport_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock +dbname = ${DBNAME} +query = SELECT CONCAT('smtp_via_transport_maps:', nexthop) AS transport FROM transports + WHERE active = '1' + AND destination = '%s'; +EOF + +cat < /opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf +user = ${DBUSER} +password = ${DBPASS} +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM relayhosts WHERE id IN ( SELECT relayhost FROM domain WHERE CONCAT('@', domain) = '%s' - OR '%s' IN ( - SELECT CONCAT('@', alias_domain) FROM alias_domain + OR domain IN ( + SELECT target_domain FROM alias_domain WHERE CONCAT('@', alias_domain) = '%s' ) ) + AND active = '1' AND username != ''; EOF +cat < /opt/postfix/conf/sql/mysql_sasl_passwd_maps_transport_maps.cf +user = ${DBUSER} +password = ${DBPASS} +hosts = unix:/var/run/mysqld/mysqld.sock +dbname = ${DBNAME} +query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM transports + WHERE nexthop = '%s' + AND active = '1' + AND username != '' + LIMIT 1; +EOF + cat < /opt/postfix/conf/sql/mysql_virtual_alias_domain_catchall_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT goto FROM alias, alias_domain WHERE alias_domain.alias_domain = '%d' @@ -107,7 +138,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT username FROM mailbox, alias_domain WHERE alias_domain.alias_domain = '%d' @@ -119,7 +150,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_alias_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT goto FROM alias WHERE address='%s' @@ -129,7 +160,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT bcc_dest FROM bcc_maps WHERE local_dest='%s' @@ -140,7 +171,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_sender_bcc_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT bcc_dest FROM bcc_maps WHERE local_dest='%s' @@ -151,7 +182,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT new_dest FROM recipient_maps WHERE old_dest='%s' @@ -161,7 +192,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT alias_domain from alias_domain WHERE alias_domain='%s' AND active='1' UNION @@ -174,15 +205,15 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} -query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' +query = SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.mailbox_format')), mailbox_path_prefix, '%d/%u/') FROM mailbox WHERE username='%s' AND active = '1' EOF cat < /opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '1' AND active = '1' EOF @@ -190,7 +221,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_sender_acl.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} # First select queries domain and alias_domain to determine if domains are active. query = SELECT goto FROM alias @@ -231,7 +262,7 @@ EOF cat < /opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf user = ${DBUSER} password = ${DBPASS} -hosts = mysql +hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT goto FROM spamalias WHERE address='%s' @@ -244,6 +275,8 @@ chmod 700 /var/lib/zeyple/keys chown -R 600:600 /var/lib/zeyple/keys # Fix Postfix permissions +chown -R root:postfix /opt/postfix/conf/sql/ +chmod 640 /opt/postfix/conf/sql/*.cf chgrp -R postdrop /var/spool/postfix/public chgrp -R postdrop /var/spool/postfix/maildrop postfix set-permissions diff --git a/data/Dockerfiles/postfix/rspamd-pipe-ham b/data/Dockerfiles/postfix/rspamd-pipe-ham index 9d961be0..9b26817c 100755 --- a/data/Dockerfiles/postfix/rspamd-pipe-ham +++ b/data/Dockerfiles/postfix/rspamd-pipe-ham @@ -3,7 +3,7 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnham -cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham +cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd exit 0 diff --git a/data/Dockerfiles/postfix/rspamd-pipe-spam b/data/Dockerfiles/postfix/rspamd-pipe-spam index 3b9e3497..d06aa919 100755 --- a/data/Dockerfiles/postfix/rspamd-pipe-spam +++ b/data/Dockerfiles/postfix/rspamd-pipe-spam @@ -3,7 +3,7 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnspam -cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam +cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd exit 0 diff --git a/data/Dockerfiles/postfix/stop-supervisor.sh b/data/Dockerfiles/postfix/stop-supervisor.sh new file mode 100755 index 00000000..5394490c --- /dev/null +++ b/data/Dockerfiles/postfix/stop-supervisor.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +printf "READY\n"; + +while read line; do + echo "Processing Event: $line" >&2; + kill -3 $(cat "/var/run/supervisord.pid") +done < /dev/stdin diff --git a/data/Dockerfiles/postfix/supervisord.conf b/data/Dockerfiles/postfix/supervisord.conf index b5ae6b54..27494bd6 100644 --- a/data/Dockerfiles/postfix/supervisord.conf +++ b/data/Dockerfiles/postfix/supervisord.conf @@ -13,3 +13,7 @@ autostart=true [program:postfix] command=/opt/postfix.sh autorestart=true + +[eventlistener:processes] +command=/usr/local/sbin/stop-supervisor.sh +events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL diff --git a/data/Dockerfiles/rspamd/Dockerfile b/data/Dockerfiles/rspamd/Dockerfile index 67b8aa1c..87d92139 100644 --- a/data/Dockerfiles/rspamd/Dockerfile +++ b/data/Dockerfiles/rspamd/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:xenial +FROM ubuntu:bionic LABEL maintainer "Andre Peters " ARG DEBIAN_FRONTEND=noninteractive @@ -8,21 +8,21 @@ RUN apt-get update && apt-get install -y \ tzdata \ ca-certificates \ gnupg2 \ - gnupg-curl \ apt-transport-https \ && apt-key adv --fetch-keys https://rspamd.com/apt/gpg.key \ - && echo "deb https://rspamd.com/apt-stable/ xenial main" > /etc/apt/sources.list.d/rspamd.list \ + && echo "deb https://rspamd.com/apt-stable/ bionic main" > /etc/apt/sources.list.d/rspamd.list \ && apt-get update && apt-get install -y rspamd \ && rm -rf /var/lib/apt/lists/* \ - && echo '.include $LOCAL_CONFDIR/local.d/rspamd.conf.local' > /etc/rspamd/rspamd.conf.local \ && apt-get autoremove --purge \ && apt-get clean \ && mkdir -p /run/rspamd \ && chown _rspamd:_rspamd /run/rspamd -COPY settings.conf /etc/rspamd/modules.d/settings.conf +COPY settings.conf /etc/rspamd/settings.conf COPY docker-entrypoint.sh /docker-entrypoint.sh ENTRYPOINT ["/docker-entrypoint.sh"] +STOPSIGNAL SIGTERM + CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] diff --git a/data/Dockerfiles/rspamd/docker-entrypoint.sh b/data/Dockerfiles/rspamd/docker-entrypoint.sh index afb03bb6..6288550d 100755 --- a/data/Dockerfiles/rspamd/docker-entrypoint.sh +++ b/data/Dockerfiles/rspamd/docker-entrypoint.sh @@ -1,6 +1,9 @@ #!/bin/bash -chown -R _rspamd:_rspamd /var/lib/rspamd +chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/local.d /etc/rspamd/override.d /etc/rspamd/custom +chmod 755 /var/lib/rspamd [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Placeholder' > /etc/rspamd/override.d/worker-controller-password.inc +chown _rspamd:_rspamd /etc/rspamd/override.d/worker-controller-password.inc +[[ ! -f /etc/rspamd/custom/sa-rules-heinlein ]] && echo '# to be auto-filled by dovecot-mailcow' > /etc/rspamd/custom/sa-rules-heinlein exec "$@" diff --git a/data/Dockerfiles/rspamd/lua_util.lua b/data/Dockerfiles/rspamd/lua_util.lua deleted file mode 100644 index a9abd901..00000000 --- a/data/Dockerfiles/rspamd/lua_util.lua +++ /dev/null @@ -1,152 +0,0 @@ -local exports = {} -local lpeg = require 'lpeg' - -local split_grammar = {} -local function rspamd_str_split(s, sep) - local gr = split_grammar[sep] - - if not gr then - local _sep = lpeg.P(sep) - local elem = lpeg.C((1 - _sep)^0) - local p = lpeg.Ct(elem * (_sep * elem)^0) - gr = p - split_grammar[sep] = gr - end - - return gr:match(s) -end - -exports.rspamd_str_split = rspamd_str_split - -local space = lpeg.S' \t\n\v\f\r' -local nospace = 1 - space -local ptrim = space^0 * lpeg.C((space^0 * nospace^1)^0) -local match = lpeg.match -exports.rspamd_str_trim = function(s) - return match(ptrim, s) -end - --- Robert Jay Gould http://lua-users.org/wiki/SimpleRound -exports.round = function(num, numDecimalPlaces) - local mult = 10^(numDecimalPlaces or 0) - return math.floor(num * mult) / mult -end - -exports.template = function(tmpl, keys) - local var_lit = lpeg.P { lpeg.R("az") + lpeg.R("AZ") + lpeg.R("09") + "_" } - local var = lpeg.P { (lpeg.P("$") / "") * ((var_lit^1) / keys) } - local var_braced = lpeg.P { (lpeg.P("${") / "") * ((var_lit^1) / keys) * (lpeg.P("}") / "") } - - local template_grammar = lpeg.Cs((var + var_braced + 1)^0) - - return lpeg.match(template_grammar, tmpl) -end - -exports.remove_email_aliases = function(email_addr) - local function check_gmail_user(addr) - -- Remove all points - local no_dots_user = string.gsub(addr.user, '%.', '') - local cap, pluses = string.match(no_dots_user, '^([^%+][^%+]*)(%+.*)$') - if cap then - return cap, rspamd_str_split(pluses, '+'), nil - elseif no_dots_user ~= addr.user then - return no_dots_user,{},nil - end - - return nil - end - - local function check_address(addr) - if addr.user then - local cap, pluses = string.match(addr.user, '^([^%+][^%+]*)(%+.*)$') - if cap then - return cap, rspamd_str_split(pluses, '+'), nil - end - end - - return nil - end - - local function set_addr(addr, new_user, new_domain) - if new_user then - addr.user = new_user - end - if new_domain then - addr.domain = new_domain - end - - if addr.domain then - addr.addr = string.format('%s@%s', addr.user, addr.domain) - else - addr.addr = string.format('%s@', addr.user) - end - - if addr.name and #addr.name > 0 then - addr.raw = string.format('"%s" <%s>', addr.name, addr.addr) - else - addr.raw = string.format('<%s>', addr.addr) - end - end - - local function check_gmail(addr) - local nu, tags, nd = check_gmail_user(addr) - - if nu then - return nu, tags, nd - end - - return nil - end - - local function check_googlemail(addr) - local nd = 'gmail.com' - local nu, tags = check_gmail_user(addr) - - if nu then - return nu, tags, nd - end - - return nil, nil, nd - end - - local specific_domains = { - ['gmail.com'] = check_gmail, - ['googlemail.com'] = check_googlemail, - } - - if email_addr then - if email_addr.domain and specific_domains[email_addr.domain] then - local nu, tags, nd = specific_domains[email_addr.domain](email_addr) - if nu or nd then - set_addr(email_addr, nu, nd) - - return nu, tags - end - else - local nu, tags, nd = check_address(email_addr) - if nu or nd then - set_addr(email_addr, nu, nd) - - return nu, tags - end - end - - return nil - end -end - -exports.is_rspamc_or_controller = function(task) - local ua = task:get_request_header('User-Agent') or '' - local pwd = task:get_request_header('Password') - local is_rspamc = false - if tostring(ua) == 'rspamc' or pwd then is_rspamc = true end - - return is_rspamc -end - -local unpack_function = table.unpack or unpack -exports.unpack = function(t) - return unpack_function(t) -end - -return exports diff --git a/data/Dockerfiles/rspamd/metadata_exporter.lua b/data/Dockerfiles/rspamd/metadata_exporter.lua new file mode 100644 index 00000000..8420bd55 --- /dev/null +++ b/data/Dockerfiles/rspamd/metadata_exporter.lua @@ -0,0 +1,722 @@ +--[[ +Copyright (c) 2016, Andrew Lewis +Copyright (c) 2016, Vsevolod Stakhov + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +]]-- + +if confighelp then + return +end + +-- A plugin that pushes metadata (or whole messages) to external services + +local redis_params +local lua_util = require "lua_util" +local rspamd_http = require "rspamd_http" +local rspamd_tcp = require "rspamd_tcp" +local rspamd_util = require "rspamd_util" +local rspamd_logger = require "rspamd_logger" +local ucl = require "ucl" +local E = {} +local N = 'metadata_exporter' + +local settings = { + pusher_enabled = {}, + pusher_format = {}, + pusher_select = {}, + mime_type = 'text/plain', + defer = false, + mail_from = '', + mail_to = 'postmaster@localhost', + helo = 'rspamd', + email_template = [[From: "Rspamd" <$mail_from> +To: $mail_to +Subject: Spam alert +Date: $date +MIME-Version: 1.0 +Message-ID: <$our_message_id> +Content-type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +Authenticated username: $user +IP: $ip +Queue ID: $qid +SMTP FROM: $from +SMTP RCPT: $rcpt +MIME From: $header_from +MIME To: $header_to +MIME Date: $header_date +Subject: $header_subject +Message-ID: $message_id +Action: $action +Score: $score +Symbols: $symbols]], +} + +local function get_general_metadata(task, flatten, no_content) + local r = {} + local ip = task:get_from_ip() + if ip and ip:is_valid() then + r.ip = tostring(ip) + else + r.ip = 'unknown' + end + r.user = task:get_user() or 'unknown' + r.qid = task:get_queue_id() or 'unknown' + r.subject = task:get_subject() or 'unknown' + r.action = task:get_metric_action('default') + + local s = task:get_metric_score('default')[1] + r.score = flatten and string.format('%.2f', s) or s + + local rcpt = task:get_recipients('smtp') + if rcpt then + local l = {} + for _, a in ipairs(rcpt) do + table.insert(l, a['addr']) + end + if not flatten then + r.rcpt = l + else + r.rcpt = table.concat(l, ', ') + end + else + r.rcpt = 'unknown' + end + local from = task:get_from('smtp') + if ((from or E)[1] or E).addr then + r.from = from[1].addr + else + r.from = 'unknown' + end + local syminf = task:get_symbols_all() + if flatten then + local l = {} + for _, sym in ipairs(syminf) do + local txt + if sym.options then + local topt = table.concat(sym.options, ', ') + txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')' .. ' [' .. topt .. ']' + else + txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')' + end + table.insert(l, txt) + end + r.symbols = table.concat(l, '\n\t') + else + r.symbols = syminf + end + local function process_header(name) + local hdr = task:get_header_full(name) + if hdr then + local l = {} + for _, h in ipairs(hdr) do + table.insert(l, h.decoded) + end + if not flatten then + return l + else + return table.concat(l, '\n') + end + else + return 'unknown' + end + end + if not no_content then + r.header_from = process_header('from') + r.header_to = process_header('to') + r.header_subject = process_header('subject') + r.header_date = process_header('date') + r.message_id = task:get_message_id() + end + return r +end + +local formatters = { + default = function(task) + return task:get_content() + end, + email_alert = function(task, rule, extra) + local meta = get_general_metadata(task, true) + local display_emails = {} + meta.mail_from = rule.mail_from or settings.mail_from + local mail_targets = rule.mail_to or settings.mail_to + if type(mail_targets) ~= 'table' then + table.insert(display_emails, string.format('<%s>', mail_targets)) + mail_targets = {[mail_targets] = true} + else + for _, e in ipairs(mail_targets) do + table.insert(display_emails, string.format('<%s>', e)) + end + end + if rule.email_alert_sender then + local x = task:get_from('smtp') + if x and string.len(x[1].addr) > 0 then + mail_targets[x] = true + table.insert(display_emails, string.format('<%s>', x[1].addr)) + end + end + if rule.email_alert_user then + local x = task:get_user() + if x then + mail_targets[x] = true + table.insert(display_emails, string.format('<%s>', x)) + end + end + if rule.email_alert_recipients then + local x = task:get_recipients('smtp') + if x then + for _, e in ipairs(x) do + if string.len(e.addr) > 0 then + mail_targets[e.addr] = true + table.insert(display_emails, string.format('<%s>', e.addr)) + end + end + end + end + meta.mail_to = table.concat(display_emails, ', ') + meta.our_message_id = rspamd_util.random_hex(12) .. '@rspamd' + meta.date = rspamd_util.time_to_string(rspamd_util.get_time()) + return lua_util.template(rule.email_template or settings.email_template, meta), { mail_targets = mail_targets} + end, + json = function(task) + return ucl.to_format(get_general_metadata(task), 'json-compact') + end +} + +local function is_spam(action) + return (action == 'reject' or action == 'add header' or action == 'rewrite subject') +end + +local selectors = { + default = function(task) + return true + end, + is_spam = function(task) + local action = task:get_metric_action('default') + return is_spam(action) + end, + is_spam_authed = function(task) + if not task:get_user() then + return false + end + local action = task:get_metric_action('default') + return is_spam(action) + end, + is_reject = function(task) + local action = task:get_metric_action('default') + return (action == 'reject') + end, + is_reject_authed = function(task) + if not task:get_user() then + return false + end + local action = task:get_metric_action('default') + return (action == 'reject') + end, +} + +local function maybe_defer(task, rule) + if rule.defer then + rspamd_logger.warnx(task, 'deferring message') + task:set_pre_result('soft reject', 'deferred', N) + end +end + +local pushers = { + redis_pubsub = function(task, formatted, rule) + local _,ret,upstream + local function redis_pub_cb(err) + if err then + rspamd_logger.errx(task, 'got error %s when publishing on server %s', + err, upstream:get_addr()) + return maybe_defer(task, rule) + end + return true + end + ret,_,upstream = rspamd_redis_make_request(task, + redis_params, -- connect params + nil, -- hash key + true, -- is write + redis_pub_cb, --callback + 'PUBLISH', -- command + {rule.channel, formatted} -- arguments + ) + if not ret then + rspamd_logger.errx(task, 'error connecting to redis') + maybe_defer(task, rule) + end + end, + http = function(task, formatted, rule) + local function http_callback(err, code) + if err then + rspamd_logger.errx(task, 'got error %s in http callback', err) + return maybe_defer(task, rule) + end + if code ~= 200 then + rspamd_logger.errx(task, 'got unexpected http status: %s', code) + return maybe_defer(task, rule) + end + return true + end + local hdrs = {} + if rule.meta_headers then + local gm = get_general_metadata(task, false, true) + local pfx = rule.meta_header_prefix or 'X-Rspamd-' + for k, v in pairs(gm) do + if type(v) == 'table' then + hdrs[pfx .. k] = ucl.to_format(v, 'json-compact') + else + hdrs[pfx .. k] = v + end + end + end + rspamd_http.request({ + task=task, + url=rule.url, + body=formatted, + callback=http_callback, + mime_type=rule.mime_type or settings.mime_type, + headers=hdrs, + }) + end, + send_mail = function(task, formatted, rule, extra) + local function mail_cb(err, data, conn) + local function no_error(merr, mdata, wantcode) + wantcode = wantcode or '2' + if merr then + rspamd_logger.errx(task, 'got error in tcp callback: %s', merr) + if conn then + conn:close() + end + maybe_defer(task, rule) + return false + end + if mdata then + if type(mdata) ~= 'string' then + mdata = tostring(mdata) + end + if string.sub(mdata, 1, 1) ~= wantcode then + rspamd_logger.errx(task, 'got bad smtp response: %s', mdata) + if conn then + conn:close() + end + maybe_defer(task, rule) + return false + end + else + rspamd_logger.errx(task, 'no data') + if conn then + conn:close() + end + maybe_defer(task, rule) + return false + end + return true + end + local function all_done_cb(merr, mdata) + if conn then + conn:close() + end + return true + end + local function quit_done_cb(merr, mdata) + conn:add_read(all_done_cb, '\r\n') + end + local function quit_cb(merr, mdata) + if no_error(merr, mdata) then + conn:add_write(quit_done_cb, 'QUIT\r\n') + end + end + local function pre_quit_cb(merr, mdata) + if no_error(merr, '2') then + conn:add_read(quit_cb, '\r\n') + end + end + local function data_done_cb(merr, mdata) + if no_error(merr, mdata, '3') then + conn:add_write(pre_quit_cb, {formatted, '\r\n.\r\n'}) + end + end + local function data_cb(merr, mdata) + if no_error(merr, '2') then + conn:add_read(data_done_cb, '\r\n') + end + end + local from_done_cb + local function rcpt_done_cb(merr, mdata) + if no_error(merr, mdata) then + local k = next(extra.mail_targets) + if not k then + conn:add_write(data_cb, 'DATA\r\n') + else + from_done_cb('2', '2') + end + end + end + local function rcpt_cb(merr, mdata) + if no_error(merr, '2') then + conn:add_read(rcpt_done_cb, '\r\n') + end + end + from_done_cb = function(merr, mdata) + local k + if extra then + k = next(extra.mail_targets) + else + extra = {mail_targets = {}} + if type(rule.mail_to) == 'string' then + extra = {mail_targets = {}} + k = rule.mail_to + elseif type(rule.mail_to) == 'table' then + for _, r in ipairs(rule.mail_to) do + extra.mail_targets[r] = true + end + k = next(extra.mail_targets) + end + end + extra.mail_targets[k] = nil + conn:add_write(rcpt_cb, {'RCPT TO: <', k, '>\r\n'}) + end + local function from_cb(merr, mdata) + if no_error(merr, '2') then + conn:add_read(from_done_cb, '\r\n') + end + end + local function hello_done_cb(merr, mdata) + if no_error(merr, mdata) then + conn:add_write(from_cb, {'MAIL FROM: <', rule.mail_from or settings.mail_from, '>\r\n'}) + end + end + local function hello_cb(merr) + if no_error(merr, '2') then + conn:add_read(hello_done_cb, '\r\n') + end + end + if no_error(err, data) then + conn:add_write(hello_cb, {'HELO ', rule.helo or settings.helo, '\r\n'}) + end + end + rspamd_tcp.request({ + task = task, + callback = mail_cb, + stop_pattern = '\r\n', + host = rule.smtp, + port = rule.smtp_port or settings.smtp_port or 25, + }) + end, +} + +local opts = rspamd_config:get_all_opt(N) +if not opts then return end +local process_settings = { + select = function(val) + selectors.custom = assert(load(val))() + end, + format = function(val) + formatters.custom = assert(load(val))() + end, + push = function(val) + pushers.custom = assert(load(val))() + end, + custom_push = function(val) + if type(val) == 'table' then + for k, v in pairs(val) do + pushers[k] = assert(load(v))() + end + end + end, + custom_select = function(val) + if type(val) == 'table' then + for k, v in pairs(val) do + selectors[k] = assert(load(v))() + end + end + end, + custom_format = function(val) + if type(val) == 'table' then + for k, v in pairs(val) do + formatters[k] = assert(load(v))() + end + end + end, + pusher_enabled = function(val) + if type(val) == 'string' then + if pushers[val] then + settings.pusher_enabled[val] = true + else + rspamd_logger.errx(rspamd_config, 'Pusher type: %s is invalid', val) + end + elseif type(val) == 'table' then + for _, v in ipairs(val) do + if pushers[v] then + settings.pusher_enabled[v] = true + else + rspamd_logger.errx(rspamd_config, 'Pusher type: %s is invalid', val) + end + end + end + end, +} +for k, v in pairs(opts) do + local f = process_settings[k] + if f then + f(opts[k]) + else + settings[k] = v + end +end +if type(settings.rules) ~= 'table' then + -- Legacy config + settings.rules = {} + if not next(settings.pusher_enabled) then + if pushers.custom then + rspamd_logger.infox(rspamd_config, 'Custom pusher implicitly enabled') + settings.pusher_enabled.custom = true + else + -- Check legacy options + if settings.url then + rspamd_logger.warnx(rspamd_config, 'HTTP pusher implicitly enabled') + settings.pusher_enabled.http = true + end + if settings.channel then + rspamd_logger.warnx(rspamd_config, 'Redis Pubsub pusher implicitly enabled') + settings.pusher_enabled.redis_pubsub = true + end + if settings.smtp and settings.mail_to then + rspamd_logger.warnx(rspamd_config, 'SMTP pusher implicitly enabled') + settings.pusher_enabled.send_mail = true + end + end + end + if not next(settings.pusher_enabled) then + rspamd_logger.errx(rspamd_config, 'No push backend enabled') + return + end + if settings.formatter then + settings.format = formatters[settings.formatter] + if not settings.format then + rspamd_logger.errx(rspamd_config, 'No such formatter: %s', settings.formatter) + return + end + end + if settings.selector then + settings.select = selectors[settings.selector] + if not settings.select then + rspamd_logger.errx(rspamd_config, 'No such selector: %s', settings.selector) + return + end + end + for k in pairs(settings.pusher_enabled) do + local formatter = settings.pusher_format[k] + local selector = settings.pusher_select[k] + if not formatter then + settings.pusher_format[k] = settings.formatter or 'default' + rspamd_logger.infox(rspamd_config, 'Using default formatter for %s pusher', k) + else + if not formatters[formatter] then + rspamd_logger.errx(rspamd_config, 'No such formatter: %s - disabling %s', formatter, k) + settings.pusher_enabled.k = nil + end + end + if not selector then + settings.pusher_select[k] = settings.selector or 'default' + rspamd_logger.infox(rspamd_config, 'Using default selector for %s pusher', k) + else + if not selectors[selector] then + rspamd_logger.errx(rspamd_config, 'No such selector: %s - disabling %s', selector, k) + settings.pusher_enabled.k = nil + end + end + end + if settings.pusher_enabled.redis_pubsub then + redis_params = rspamd_parse_redis_server(N) + if not redis_params then + rspamd_logger.errx(rspamd_config, 'No redis servers are specified') + settings.pusher_enabled.redis_pubsub = nil + else + local r = {} + r.backend = 'redis_pubsub' + r.channel = settings.channel + r.defer = settings.defer + r.selector = settings.pusher_select.redis_pubsub + r.formatter = settings.pusher_format.redis_pubsub + settings.rules[r.backend:upper()] = r + end + end + if settings.pusher_enabled.http then + if not settings.url then + rspamd_logger.errx(rspamd_config, 'No URL is specified') + settings.pusher_enabled.http = nil + else + local r = {} + r.backend = 'http' + r.url = settings.url + r.mime_type = settings.mime_type + r.defer = settings.defer + r.selector = settings.pusher_select.http + r.formatter = settings.pusher_format.http + settings.rules[r.backend:upper()] = r + end + end + if settings.pusher_enabled.send_mail then + if not (settings.mail_to and settings.smtp) then + rspamd_logger.errx(rspamd_config, 'No mail_to and/or smtp setting is specified') + settings.pusher_enabled.send_mail = nil + else + local r = {} + r.backend = 'send_mail' + r.mail_to = settings.mail_to + r.mail_from = settings.mail_from + r.helo = settings.hello + r.smtp = settings.smtp + r.smtp_port = settings.smtp_port + r.email_template = settings.email_template + r.defer = settings.defer + r.selector = settings.pusher_select.send_mail + r.formatter = settings.pusher_format.send_mail + settings.rules[r.backend:upper()] = r + end + end + if not next(settings.pusher_enabled) then + rspamd_logger.errx(rspamd_config, 'No push backend enabled') + return + end +elseif not next(settings.rules) then + lua_util.debugm(N, rspamd_config, 'No rules enabled') + return +end +if not settings.rules or not next(settings.rules) then + rspamd_logger.errx(rspamd_config, 'No rules enabled') + return +end +local backend_required_elements = { + http = { + 'url', + }, + smtp = { + 'mail_to', + 'smtp', + }, + redis_pubsub = { + 'channel', + }, +} +local check_element = { + selector = function(k, v) + if not selectors[v] then + rspamd_logger.errx(rspamd_config, 'Rule %s has invalid selector %s', k, v) + return false + else + return true + end + end, + formatter = function(k, v) + if not formatters[v] then + rspamd_logger.errx(rspamd_config, 'Rule %s has invalid formatter %s', k, v) + return false + else + return true + end + end, +} +local backend_check = { + default = function(k, rule) + local reqset = backend_required_elements[rule.backend] + if reqset then + for _, e in ipairs(reqset) do + if not rule[e] then + rspamd_logger.errx(rspamd_config, 'Rule %s misses required setting %s', k, e) + settings.rules[k] = nil + end + end + end + for sett, v in pairs(rule) do + local f = check_element[sett] + if f then + if not f(sett, v) then + settings.rules[k] = nil + end + end + end + end, +} +backend_check.redis_pubsub = function(k, rule) + if not redis_params then + redis_params = rspamd_parse_redis_server(N) + end + if not redis_params then + rspamd_logger.errx(rspamd_config, 'No redis servers are specified') + settings.rules[k] = nil + else + backend_check.default(k, rule) + end +end +setmetatable(backend_check, { + __index = function() + return backend_check.default + end, +}) +for k, v in pairs(settings.rules) do + if type(v) == 'table' then + local backend = v.backend + if not backend then + rspamd_logger.errx(rspamd_config, 'Rule %s has no backend', k) + settings.rules[k] = nil + elseif not pushers[backend] then + rspamd_logger.errx(rspamd_config, 'Rule %s has invalid backend %s', k, backend) + settings.rules[k] = nil + else + local f = backend_check[backend] + f(k, v) + end + else + rspamd_logger.errx(rspamd_config, 'Rule %s has bad type: %s', k, type(v)) + settings.rules[k] = nil + end +end + +local function gen_exporter(rule) + return function (task) + if task:has_flag('skip') then return end + local selector = rule.selector or 'default' + local selected = selectors[selector](task) + if selected then + lua_util.debugm(N, task, 'Message selected for processing') + local formatter = rule.formatter or 'default' + local formatted, extra = formatters[formatter](task, rule) + if formatted then + pushers[rule.backend](task, formatted, rule, extra) + else + lua_util.debugm(N, task, 'Formatter [%s] returned non-truthy value [%s]', formatter, formatted) + end + else + lua_util.debugm(N, task, 'Selector [%s] returned non-truthy value [%s]', selector, selected) + end + end +end + +if not next(settings.rules) then + rspamd_logger.errx(rspamd_config, 'No rules enabled') + lua_util.disable_module(N, "config") +end +for k, r in pairs(settings.rules) do + rspamd_config:register_symbol({ + name = 'EXPORT_METADATA_' .. k, + type = 'postfilter,idempotent', + callback = gen_exporter(r), + priority = 10, + flags = 'empty', + }) +end diff --git a/data/Dockerfiles/rspamd/ratelimit.lua b/data/Dockerfiles/rspamd/ratelimit.lua deleted file mode 100644 index 839ec5c6..00000000 --- a/data/Dockerfiles/rspamd/ratelimit.lua +++ /dev/null @@ -1,674 +0,0 @@ ---[[ -Copyright (c) 2011-2017, Vsevolod Stakhov -Copyright (c) 2016-2017, Andrew Lewis - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -]]-- - -if confighelp then - return -end - --- A plugin that implements ratelimits using redis - -local E = {} -local N = 'ratelimit' -local redis_params --- Senders that are considered as bounce -local settings = { - bounce_senders = { 'postmaster', 'mailer-daemon', '', 'null', 'fetchmail-daemon', 'mdaemon' }, --- Do not check ratelimits for these recipients - whitelisted_rcpts = { 'postmaster', 'mailer-daemon' }, - prefix = 'RL', - ham_factor_rate = 1.01, - spam_factor_rate = 0.99, - ham_factor_burst = 1.02, - spam_factor_burst = 0.98, - max_rate_mult = 5, - max_bucket_mult = 10, - expire = 60 * 60 * 24 * 2, -- 2 days by default - limits = {}, - allow_local = false, -} - --- Checks bucket, updating it if needed --- KEYS[1] - prefix to update, e.g. RL__ --- KEYS[2] - current time in milliseconds --- KEYS[3] - bucket leak rate (messages per millisecond) --- KEYS[4] - bucket burst --- KEYS[5] - expire for a bucket --- return 1 if message should be ratelimited and 0 if not --- Redis keys used: --- l - last hit --- b - current burst --- dr - current dynamic rate multiplier (*10000) --- db - current dynamic burst multiplier (*10000) -local bucket_check_script = [[ - local last = redis.call('HGET', KEYS[1], 'l') - local now = tonumber(KEYS[2]) - local dynr, dynb = 0, 0 - if not last then - -- New bucket - redis.call('HSET', KEYS[1], 'l', KEYS[2]) - redis.call('HSET', KEYS[1], 'b', '0') - redis.call('HSET', KEYS[1], 'dr', '10000') - redis.call('HSET', KEYS[1], 'db', '10000') - redis.call('EXPIRE', KEYS[1], KEYS[5]) - return {0, 0, 1, 1} - end - - last = tonumber(last) - local burst = tonumber(redis.call('HGET', KEYS[1], 'b')) - -- Perform leak - if burst > 0 then - if last < tonumber(KEYS[2]) then - local rate = tonumber(KEYS[3]) - dynr = tonumber(redis.call('HGET', KEYS[1], 'dr')) / 10000.0 - rate = rate * dynr - local leaked = ((now - last) * rate) - burst = burst - leaked - redis.call('HINCRBYFLOAT', KEYS[1], 'b', -(leaked)) - end - else - burst = 0 - redis.call('HSET', KEYS[1], 'b', '0') - end - - dynb = tonumber(redis.call('HGET', KEYS[1], 'db')) / 10000.0 - - if (burst + 1) * dynb > tonumber(KEYS[4]) then - return {1, tostring(burst), tostring(dynr), tostring(dynb)} - end - - return {0, tostring(burst), tostring(dynr), tostring(dynb)} -]] -local bucket_check_id - - --- Updates a bucket --- KEYS[1] - prefix to update, e.g. RL__ --- KEYS[2] - current time in milliseconds --- KEYS[3] - dynamic rate multiplier --- KEYS[4] - dynamic burst multiplier --- KEYS[5] - max dyn rate (min: 1/x) --- KEYS[6] - max burst rate (min: 1/x) --- KEYS[7] - expire for a bucket --- Redis keys used: --- l - last hit --- b - current burst --- dr - current dynamic rate multiplier --- db - current dynamic burst multiplier -local bucket_update_script = [[ - local last = redis.call('HGET', KEYS[1], 'l') - local now = tonumber(KEYS[2]) - if not last then - -- New bucket - redis.call('HSET', KEYS[1], 'l', KEYS[2]) - redis.call('HSET', KEYS[1], 'b', '1') - redis.call('HSET', KEYS[1], 'dr', '10000') - redis.call('HSET', KEYS[1], 'db', '10000') - redis.call('EXPIRE', KEYS[1], KEYS[7]) - return {1, 1, 1} - end - - local burst = tonumber(redis.call('HGET', KEYS[1], 'b')) - local db = tonumber(redis.call('HGET', KEYS[1], 'db')) / 10000 - local dr = tonumber(redis.call('HGET', KEYS[1], 'dr')) / 10000 - - if dr < tonumber(KEYS[5]) and dr > 1.0 / tonumber(KEYS[5]) then - dr = dr * tonumber(KEYS[3]) - redis.call('HSET', KEYS[1], 'dr', tostring(math.floor(dr * 10000))) - end - - if db < tonumber(KEYS[6]) and db > 1.0 / tonumber(KEYS[6]) then - db = db * tonumber(KEYS[4]) - redis.call('HSET', KEYS[1], 'db', tostring(math.floor(db * 10000))) - end - - redis.call('HINCRBYFLOAT', KEYS[1], 'b', 1) - redis.call('HSET', KEYS[1], 'l', KEYS[2]) - redis.call('EXPIRE', KEYS[1], KEYS[7]) - - return {tostring(burst), tostring(dr), tostring(db)} -]] -local bucket_update_id - --- message_func(task, limit_type, prefix, bucket) -local message_func = function(_, limit_type, _, _) - return string.format('Ratelimit "%s" exceeded', limit_type) -end - -local rspamd_logger = require "rspamd_logger" -local rspamd_util = require "rspamd_util" -local rspamd_lua_utils = require "lua_util" -local lua_redis = require "lua_redis" -local fun = require "fun" -local lua_maps = require "lua_maps" -local lua_util = require "lua_util" -local rspamd_hash = require "rspamd_cryptobox_hash" - - -local function load_scripts(cfg, ev_base) - bucket_check_id = lua_redis.add_redis_script(bucket_check_script, redis_params) - bucket_update_id = lua_redis.add_redis_script(bucket_update_script, redis_params) -end - -local limit_parser -local function parse_string_limit(lim, no_error) - local function parse_time_suffix(s) - if s == 's' then - return 1 - elseif s == 'm' then - return 60 - elseif s == 'h' then - return 3600 - elseif s == 'd' then - return 86400 - end - end - local function parse_num_suffix(s) - if s == '' then - return 1 - elseif s == 'k' then - return 1000 - elseif s == 'm' then - return 1000000 - elseif s == 'g' then - return 1000000000 - end - end - local lpeg = require "lpeg" - - if not limit_parser then - local digit = lpeg.R("09") - limit_parser = {} - limit_parser.integer = - (lpeg.S("+-") ^ -1) * - (digit ^ 1) - limit_parser.fractional = - (lpeg.P(".") ) * - (digit ^ 1) - limit_parser.number = - (limit_parser.integer * - (limit_parser.fractional ^ -1)) + - (lpeg.S("+-") * limit_parser.fractional) - limit_parser.time = lpeg.Cf(lpeg.Cc(1) * - (limit_parser.number / tonumber) * - ((lpeg.S("smhd") / parse_time_suffix) ^ -1), - function (acc, val) return acc * val end) - limit_parser.suffixed_number = lpeg.Cf(lpeg.Cc(1) * - (limit_parser.number / tonumber) * - ((lpeg.S("kmg") / parse_num_suffix) ^ -1), - function (acc, val) return acc * val end) - limit_parser.limit = lpeg.Ct(limit_parser.suffixed_number * - (lpeg.S(" ") ^ 0) * lpeg.S("/") * (lpeg.S(" ") ^ 0) * - limit_parser.time) - end - local t = lpeg.match(limit_parser.limit, lim) - - if t and t[1] and t[2] and t[2] ~= 0 then - return t[2], t[1] - end - - if not no_error then - rspamd_logger.errx(rspamd_config, 'bad limit: %s', lim) - end - - return nil -end - -local function parse_limit(name, data) - local buckets = {} - if type(data) == 'table' then - -- 3 cases here: - -- * old limit in format [burst, rate] - -- * vector of strings in Andrew's string format - -- * proper bucket table - if #data == 2 and tonumber(data[1]) and tonumber(data[2]) then - -- Old style ratelimit - rspamd_logger.warnx(rspamd_config, 'old style ratelimit for %s', name) - if tonumber(data[1]) > 0 and tonumber(data[2]) > 0 then - table.insert(buckets, { - burst = data[1], - rate = data[2] - }) - elseif data[1] ~= 0 then - rspamd_logger.warnx(rspamd_config, 'invalid numbers for %s', name) - else - rspamd_logger.infox(rspamd_config, 'disable limit %s, burst is zero', name) - end - else - -- Recursively map parse_limit and flatten the list - fun.each(function(l) - -- Flatten list - for _,b in ipairs(l) do table.insert(buckets, b) end - end, fun.map(function(d) return parse_limit(d, name) end, data)) - end - elseif type(data) == 'string' then - local rep_rate, burst = parse_string_limit(data) - - if rep_rate and burst then - table.insert(buckets, { - burst = burst, - rate = 1.0 / rep_rate -- reciprocal - }) - end - end - - -- Filter valid - return fun.totable(fun.filter(function(val) - return type(val.burst) == 'number' and type(val.rate) == 'number' - end, buckets)) -end - ---- Check whether this addr is bounce -local function check_bounce(from) - return fun.any(function(b) return b == from end, settings.bounce_senders) -end - -local keywords = { - ['ip'] = { - ['get_value'] = function(task) - local ip = task:get_ip() - if ip and ip:is_valid() then return tostring(ip) end - return nil - end, - }, - ['rip'] = { - ['get_value'] = function(task) - local ip = task:get_ip() - if ip and ip:is_valid() and not ip:is_local() then return tostring(ip) end - return nil - end, - }, - ['from'] = { - ['get_value'] = function(task) - local from = task:get_from(0) - if ((from or E)[1] or E).addr then - return string.lower(from[1]['addr']) - end - return nil - end, - }, - ['bounce'] = { - ['get_value'] = function(task) - local from = task:get_from(0) - if not ((from or E)[1] or E).user then - return '_' - end - if check_bounce(from[1]['user']) then return '_' else return nil end - end, - }, - ['asn'] = { - ['get_value'] = function(task) - local asn = task:get_mempool():get_variable('asn') - if not asn then - return nil - else - return asn - end - end, - }, - ['user'] = { - ['get_value'] = function(task) - local auser = task:get_user() - if not auser then - return nil - else - return auser - end - end, - }, - ['to'] = { - ['get_value'] = function(task) - return task:get_principal_recipient() - end, - }, -} - -local function gen_rate_key(task, rtype, bucket) - local key_t = {tostring(lua_util.round(100000.0 / bucket.burst))} - local key_keywords = lua_util.str_split(rtype, '_') - local have_user = false - - for _, v in ipairs(key_keywords) do - local ret - - if keywords[v] and type(keywords[v]['get_value']) == 'function' then - ret = keywords[v]['get_value'](task) - end - if not ret then return nil end - if v == 'user' then have_user = true end - if type(ret) ~= 'string' then ret = tostring(ret) end - table.insert(key_t, ret) - end - - if have_user and not task:get_user() then - return nil - end - - return table.concat(key_t, ":") -end - -local function make_prefix(redis_key, name, bucket) - local hash_len = 24 - if hash_len > #redis_key then hash_len = #redis_key end - local hash = settings.prefix .. - string.sub(rspamd_hash.create(redis_key):base32(), 1, hash_len) - -- Fill defaults - if not bucket.spam_factor_rate then - bucket.spam_factor_rate = settings.spam_factor_rate - end - if not bucket.ham_factor_rate then - bucket.ham_factor_rate = settings.ham_factor_rate - end - if not bucket.spam_factor_burst then - bucket.spam_factor_burst = settings.spam_factor_burst - end - if not bucket.ham_factor_burst then - bucket.ham_factor_burst = settings.ham_factor_burst - end - - return { - bucket = bucket, - name = name, - hash = hash - } -end - -local function limit_to_prefixes(task, k, v, prefixes) - local n = 0 - for _,bucket in ipairs(v) do - local prefix = gen_rate_key(task, k, bucket) - - if prefix then - prefixes[prefix] = make_prefix(prefix, k, bucket) - n = n + 1 - end - end - - return n -end - -local function ratelimit_cb(task) - if not settings.allow_local and - rspamd_lua_utils.is_rspamc_or_controller(task) then return end - - -- Get initial task data - local ip = task:get_from_ip() - if ip and ip:is_valid() and settings.whitelisted_ip then - if settings.whitelisted_ip:get_key(ip) then - -- Do not check whitelisted ip - rspamd_logger.infox(task, 'skip ratelimit for whitelisted IP') - return - end - end - -- Parse all rcpts - local rcpts = task:get_recipients() - local rcpts_user = {} - if rcpts then - fun.each(function(r) - fun.each(function(type) table.insert(rcpts_user, r[type]) end, {'user', 'addr'}) - end, rcpts) - - if fun.any(function(r) return settings.whitelisted_rcpts:get_key(r) end, rcpts_user) then - rspamd_logger.infox(task, 'skip ratelimit for whitelisted recipient') - return - end - end - -- Get user (authuser) - if settings.whitelisted_user then - local auser = task:get_user() - if settings.whitelisted_user:get_key(auser) then - rspamd_logger.infox(task, 'skip ratelimit for whitelisted user') - return - end - end - -- Now create all ratelimit prefixes - local prefixes = {} - local nprefixes = 0 - - for k,v in pairs(settings.limits) do - nprefixes = nprefixes + limit_to_prefixes(task, k, v, prefixes) - end - - for k, hdl in pairs(settings.custom_keywords or E) do - local ret, redis_key, bd = pcall(hdl, task) - - if ret then - local bucket = parse_limit(k, bd) - if bucket[1] then - prefixes[redis_key] = make_prefix(redis_key, k, bucket[1]) - end - nprefixes = nprefixes + 1 - else - rspamd_logger.errx(task, 'cannot call handler for %s: %s', - k, redis_key) - end - end - - local function gen_check_cb(prefix, bucket, lim_name) - return function(err, data) - if err then - rspamd_logger.errx('cannot check limit %s: %s %s', prefix, err, data) - elseif type(data) == 'table' and data[1] and data[1] == 1 then - -- set symbol only and do NOT soft reject - if settings.symbol then - task:insert_result(settings.symbol, 0.0, lim_name .. "(" .. prefix .. ")") - rspamd_logger.infox(task, - 'set_symbol_only: ratelimit "%s(%s)" exceeded, (%s / %s): %s (%s:%s dyn)', - lim_name, prefix, - bucket.burst, bucket.rate, - data[2], data[3], data[4]) - return - -- set INFO symbol and soft reject - elseif settings.info_symbol then - task:insert_result(settings.info_symbol, 1.0, - lim_name .. "(" .. prefix .. ")") - end - rspamd_logger.infox(task, - 'ratelimit "%s(%s)" exceeded, (%s / %s): %s (%s:%s dyn)', - lim_name, prefix, - bucket.burst, bucket.rate, - data[2], data[3], data[4]) - task:set_pre_result('soft reject', - message_func(task, lim_name, prefix, bucket)) - end - end - end - - -- Don't do anything if pre-result has been already set - if task:has_pre_result() then return end - - if nprefixes > 0 then - -- Save prefixes to the cache to allow update - task:cache_set('ratelimit_prefixes', prefixes) - local now = rspamd_util.get_time() - now = lua_util.round(now * 1000.0) -- Get milliseconds - -- Now call check script for all defined prefixes - - for pr,value in pairs(prefixes) do - local bucket = value.bucket - local rate = (bucket.rate) / 1000.0 -- Leak rate in messages/ms - rspamd_logger.debugm(N, task, "check limit %s:%s -> %s (%s/%s)", - value.name, pr, value.hash, bucket.burst, bucket.rate) - lua_redis.exec_redis_script(bucket_check_id, - {key = value.hash, task = task, is_write = true}, - gen_check_cb(pr, bucket, value.name), - {value.hash, tostring(now), tostring(rate), tostring(bucket.burst), - tostring(settings.expire)}) - end - end -end - -local function ratelimit_update_cb(task) - local prefixes = task:cache_get('ratelimit_prefixes') - - if prefixes then - if task:has_pre_result() then - -- Already rate limited/greylisted, do nothing - rspamd_logger.debugm(N, task, 'pre-action has been set, do not update') - return - end - - local is_spam = not (task:get_metric_action() == 'no action') - - -- Update each bucket - for k, v in pairs(prefixes) do - local bucket = v.bucket - local function update_bucket_cb(err, data) - if err then - rspamd_logger.errx(task, 'cannot update rate bucket %s: %s', - k, err) - else - rspamd_logger.debugm(N, task, - "updated limit %s:%s -> %s (%s/%s), burst: %s, dyn_rate: %s, dyn_burst: %s", - v.name, k, v.hash, - bucket.burst, bucket.rate, - data[1], data[2], data[3]) - end - end - local now = rspamd_util.get_time() - now = lua_util.round(now * 1000.0) -- Get milliseconds - local mult_burst = bucket.ham_factor_burst or 1.0 - local mult_rate = bucket.ham_factor_burst or 1.0 - - if is_spam then - mult_burst = bucket.spam_factor_burst or 1.0 - mult_rate = bucket.spam_factor_rate or 1.0 - end - - lua_redis.exec_redis_script(bucket_update_id, - {key = v.hash, task = task, is_write = true}, - update_bucket_cb, - {v.hash, tostring(now), tostring(mult_rate), tostring(mult_burst), - tostring(settings.max_rate_mult), tostring(settings.max_bucket_mult), - tostring(settings.expire)}) - end - end -end - -local opts = rspamd_config:get_all_opt(N) -if opts then - - settings = lua_util.override_defaults(settings, opts) - - if opts['limit'] then - rspamd_logger.errx(rspamd_config, 'Legacy ratelimit config format no longer supported') - end - - if opts['rates'] and type(opts['rates']) == 'table' then - -- new way of setting limits - fun.each(function(t, lim) - local buckets = parse_limit(t, lim) - - if buckets and #buckets > 0 then - settings.limits[t] = buckets - end - end, opts['rates']) - end - - local enabled_limits = fun.totable(fun.map(function(t) - return t - end, settings.limits)) - rspamd_logger.infox(rspamd_config, - 'enabled rate buckets: [%1]', table.concat(enabled_limits, ',')) - - -- Ret, ret, ret: stupid legacy stuff: - -- If we have a string with commas then load it as as static map - -- otherwise, apply normal logic of Rspamd maps - - local wrcpts = opts['whitelisted_rcpts'] - if type(wrcpts) == 'string' then - if string.find(wrcpts, ',') then - settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl( - lua_util.rspamd_str_split(wrcpts, ','), 'set', 'Ratelimit whitelisted rcpts') - else - settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(wrcpts, 'set', - 'Ratelimit whitelisted rcpts') - end - elseif type(opts['whitelisted_rcpts']) == 'table' then - settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(wrcpts, 'set', - 'Ratelimit whitelisted rcpts') - else - -- Stupid default... - settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl( - settings.whitelisted_rcpts, 'set', 'Ratelimit whitelisted rcpts') - end - - if opts['whitelisted_ip'] then - settings.whitelisted_ip = lua_maps.rspamd_map_add('ratelimit', 'whitelisted_ip', 'radix', - 'Ratelimit whitelist ip map') - end - - if opts['whitelisted_user'] then - settings.whitelisted_user = lua_maps.rspamd_map_add('ratelimit', 'whitelisted_user', 'set', - 'Ratelimit whitelist user map') - end - - settings.custom_keywords = {} - if opts['custom_keywords'] then - local ret, res_or_err = pcall(loadfile(opts['custom_keywords'])) - - if ret then - opts['custom_keywords'] = {} - if type(res_or_err) == 'table' then - for k,hdl in pairs(res_or_err) do - settings['custom_keywords'][k] = hdl - end - elseif type(res_or_err) == 'function' then - settings['custom_keywords']['custom'] = res_or_err - end - else - rspamd_logger.errx(rspamd_config, 'cannot execute %s: %s', - opts['custom_keywords'], res_or_err) - settings['custom_keywords'] = {} - end - end - - if opts['message_func'] then - message_func = assert(load(opts['message_func']))() - end - - redis_params = lua_redis.parse_redis_server('ratelimit') - - if not redis_params then - rspamd_logger.infox(rspamd_config, 'no servers are specified, disabling module') - lua_util.disable_module(N, "redis") - else - local s = { - type = 'prefilter,nostat', - name = 'RATELIMIT_CHECK', - priority = 7, - callback = ratelimit_cb, - flags = 'empty', - } - - if settings.symbol then - s.name = settings.symbol - elseif settings.info_symbol then - s.name = settings.info_symbol - end - - rspamd_config:register_symbol(s) - rspamd_config:register_symbol { - type = 'idempotent', - name = 'RATELIMIT_UPDATE', - callback = ratelimit_update_cb, - } - end -end - -rspamd_config:add_on_load(function(cfg, ev_base, worker) - load_scripts(cfg, ev_base) -end) diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 30a06d24..970ec252 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -7,46 +7,50 @@ ENV GOSU_VERSION 1.9 # Prerequisites RUN apt-get update && apt-get install -y --no-install-recommends \ - apt-transport-https \ - ca-certificates \ - cron \ - gnupg \ - mysql-client \ - supervisor \ - syslog-ng \ - syslog-ng-core \ - syslog-ng-mod-redis \ - dirmngr \ - netcat \ - psmisc \ - wget \ - patch \ - && rm -rf /var/lib/apt/lists/* \ - && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true + apt-transport-https \ + ca-certificates \ + cron \ + gettext \ + gnupg \ + mysql-client \ + rsync \ + supervisor \ + syslog-ng \ + syslog-ng-core \ + syslog-ng-mod-redis \ + dirmngr \ + netcat \ + psmisc \ + wget \ + patch \ + && rm -rf /var/lib/apt/lists/* \ + && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \ + && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \ + && chmod +x /usr/local/bin/gosu \ + && gosu nobody true RUN mkdir /usr/share/doc/sogo \ - && touch /usr/share/doc/sogo/empty.sh \ - && apt-key adv --keyserver keyserver.ubuntu.com --recv-key 0x810273C4 \ - && echo "deb http://packages.inverse.ca/SOGo/nightly/4/debian/ stretch stretch" > /etc/apt/sources.list.d/sogo.list \ - && apt-get update && apt-get install -y --force-yes \ - sogo \ - sogo-activesync \ - && rm -rf /var/lib/apt/lists/* \ - && echo '* * * * * sogo /usr/sbin/sogo-ealarms-notify 2>/dev/null' > /etc/cron.d/sogo \ - && echo '* * * * * sogo /usr/sbin/sogo-tool expire-sessions 60' >> /etc/cron.d/sogo \ - && echo '0 0 * * * sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds' >> /etc/cron.d/sogo \ - && touch /etc/default/locale + && touch /usr/share/doc/sogo/empty.sh \ + && apt-key adv --keyserver keyserver.ubuntu.com --recv-key 0x810273C4 \ + && echo "deb http://packages.inverse.ca/SOGo/nightly/4/debian/ stretch stretch" > /etc/apt/sources.list.d/sogo.list \ + && apt-get update && apt-get install -y --force-yes \ + sogo \ + sogo-activesync \ + && rm -rf /var/lib/apt/lists/* \ + && echo '* * * * * sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/sieve.creds 2>/dev/null' > /etc/cron.d/sogo \ + && echo '* * * * * sogo /usr/sbin/sogo-tool expire-sessions 60' >> /etc/cron.d/sogo \ + && echo '0 0 * * * sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds' >> /etc/cron.d/sogo \ + && touch /etc/default/locale -COPY ./bootstrap-sogo.sh / +COPY ./bootstrap-sogo.sh /bootstrap-sogo.sh COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf COPY supervisord.conf /etc/supervisor/supervisord.conf -COPY theme-blue.js /usr/lib/GNUstep/SOGo/WebServerResources/js/theme-blue.js -COPY theme-blue.css /usr/lib/GNUstep/SOGo/WebServerResources/css/theme-default.css -COPY sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg COPY acl.diff /acl.diff +COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh + +RUN chmod +x /bootstrap-sogo.sh \ + /usr/local/sbin/stop-supervisor.sh + CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf RUN rm -rf /tmp/* /var/tmp/* diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index 46d8ec6c..7f1835db 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -1,7 +1,7 @@ #!/bin/bash # Wait for MySQL to warm-up -while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do +while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do echo "Waiting for database to come up..." sleep 2 done @@ -13,20 +13,31 @@ do sleep 3 done +# Wait for updated schema +DBV_NOW=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions;" -BN) +DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2) +while [[ ${DBV_NOW} != ${DBV_NEW} ]]; do + echo "Waiting for schema update..." + DBV_NOW=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions;" -BN) + DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2) + sleep 5 +done +echo "DB schema is ${DBV_NOW}" + # Recreate view -mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view" +mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view" while [[ ${VIEW_OK} != 'OK' ]]; do - mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF -CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, home, kind, multiple_bookings) AS -SELECT mailbox.username, mailbox.domain, mailbox.username, if(json_extract(attributes, '$.force_pw_update') LIKE '%0%', password, 'invalid'), mailbox.name, mailbox.username, IFNULL(GROUP_CONCAT(ga.aliases SEPARATOR ' '), ''), IFNULL(gda.ad_alias, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox + mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF +CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, kind, multiple_bookings) AS +SELECT mailbox.username, mailbox.domain, mailbox.username, if(json_extract(attributes, '$.force_pw_update') LIKE '%0%', if(json_extract(attributes, '$.sogo_access') LIKE '%1%', password, 'invalid'), 'invalid'), mailbox.name, mailbox.username, IFNULL(GROUP_CONCAT(ga.aliases SEPARATOR ' '), ''), IFNULL(gda.ad_alias, ''), mailbox.kind, mailbox.multiple_bookings FROM mailbox LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)') LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username WHERE mailbox.active = '1' GROUP BY mailbox.username; EOF - if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then + if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then VIEW_OK=OK else echo "Will retry to setup SOGo view in 3s" @@ -37,11 +48,11 @@ done # Wait for static view table if missing after update and update content while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do - if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then + if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then STATIC_VIEW_OK=OK echo "Updating _sogo_static_view content..." - mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view SELECT * from sogo_view" - mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')" + mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, kind, multiple_bookings) SELECT c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, kind, multiple_bookings from sogo_view;" + mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')" else echo "Waiting for database initialization..." sleep 3 @@ -50,10 +61,10 @@ done # Recreate password update trigger -mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password" +mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password" while [[ ${TRIGGER_OK} != 'OK' ]]; do - mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF + mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF DELIMITER - CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view FOR EACH ROW @@ -63,7 +74,7 @@ END; - DELIMITER ; EOF - if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then + if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then TRIGGER_OK=OK else echo "Will retry to setup SOGo password update trigger in 3s" @@ -72,28 +83,41 @@ EOF done -mkdir -p /var/lib/sogo/GNUstep/Defaults/ +if [[ "${ALLOW_ADMIN_EMAIL_LOGIN}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + TRUST_PROXY="YES" +else + TRUST_PROXY="NO" +fi +# cat /dev/urandom seems to hang here occasionally and is not recommended anyway, better use openssl +RAND_PASS=$(openssl rand -base64 16 | tr -dc _A-Z-a-z-0-9) # Generate plist header with timezone data +mkdir -p /var/lib/sogo/GNUstep/Defaults/ cat < /var/lib/sogo/GNUstep/Defaults/sogod.plist OCSAclURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_acl + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_acl + SOGoIMAPServer + imap://${IPV4_NETWORK}.250:143/?tls=YES + SOGoTrustProxyAuthentication + ${TRUST_PROXY} + SOGoEncryptionKey + ${RAND_PASS} OCSCacheFolderURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_cache_folder + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_cache_folder OCSEMailAlarmsFolderURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_alarms_folder + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_alarms_folder OCSFolderInfoURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_folder_info + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_folder_info OCSSessionsFolderURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_sessions_folder + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_sessions_folder OCSStoreURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_store + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_store SOGoProfileURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_user_profile + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_user_profile SOGoTimeZone ${TZ} domains @@ -101,9 +125,9 @@ cat < /var/lib/sogo/GNUstep/Defaults/sogod.plist EOF # Generate multi-domain setup -while read line - do - echo " ${line} +while read -r line gal + do + echo " ${line} SOGoMailDomain ${line} @@ -126,11 +150,11 @@ while read line canAuthenticate YES displayName - GAL + GAL ${line} id ${line} isAddressBook - YES + ${gal} type sql userPasswordAlgorithm @@ -138,11 +162,14 @@ while read line prependPasswordScheme YES viewURL - mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/_sogo_static_view - - + mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/_sogo_static_view + " >> /var/lib/sogo/GNUstep/Defaults/sogod.plist + # Generate alternative LDAP authentication dict, when SQL authentication fails + # This will nevertheless read attributes from LDAP + line=${line} envsubst < /etc/sogo/plist_ldap >> /var/lib/sogo/GNUstep/Defaults/sogod.plist + echo " " >> /var/lib/sogo/GNUstep/Defaults/sogod.plist -done < <(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain;" -B -N) +done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain, CASE gal WHEN '1' THEN 'YES' ELSE 'NO' END AS gal FROM domain;" -B -N) # Generate footer echo ' @@ -153,46 +180,24 @@ echo ' chown sogo:sogo -R /var/lib/sogo/ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist -# Prevent theme switching -sed -i \ - -e 's/eaf5e9/E3F2FD/g' \ - -e 's/cbe5c8/BBDEFB/g' \ - -e 's/aad6a5/90CAF9/g' \ - -e 's/88c781/64B5F6/g' \ - -e 's/66b86a/42A5F5/g' \ - -e 's/56b04c/2196F3/g' \ - -e 's/4da143/1E88E5/g' \ - -e 's/388e3c/1976D2/g' \ - -e 's/367d2e/1565C0/g' \ - -e 's/225e1b/0D47A1/g' \ - -e 's/fafafa/82B1FF/g' \ - -e 's/69f0ae/448AFF/g' \ - -e 's/00e676/2979ff/g' \ - -e 's/00c853/2962ff/g' \ - /usr/lib/GNUstep/SOGo/WebServerResources/js/Common/Common.app.js \ - /usr/lib/GNUstep/SOGo/WebServerResources/js/Common.js - -sed -i \ - -e 's/default: "900"/default: "700"/g' \ - -e 's/default: "500"/default: "700"/g' \ - -e 's/"hue-1": "400"/"hue-1": "500"/g' \ - -e 's/"hue-1": "A100"/"hue-1": "500"/g' \ - -e 's/"hue-2": "800"/"hue-2": "700"/g' \ - -e 's/"hue-2": "300"/"hue-2": "700"/g' \ - -e 's/"hue-3": "A700"/"hue-3": "A200"/' \ - -e 's/default:"900"/default:"700"/g' \ - -e 's/default:"500"/default:"700"/g' \ - -e 's/"hue-1":"400"/"hue-1":"500"/g' \ - -e 's/"hue-1":"A100"/"hue-1":"500"/g' \ - -e 's/"hue-2":"800"/"hue-2":"700"/g' \ - -e 's/"hue-2":"300"/"hue-2":"700"/g' \ - -e 's/"hue-3":"A700"/"hue-3":"A200"/' \ - /usr/lib/GNUstep/SOGo/WebServerResources/js/Common/Common.app.js \ - /usr/lib/GNUstep/SOGo/WebServerResources/js/Common.js - -# Patch ACLs (comment this out to enable any or authenticated targets for ACL) -if patch -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then - patch /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff; +# Patch ACLs +if [[ ${ACL_ANYONE} == 'allow' ]]; then + #enable any or authenticated targets for ACL + if patch -R -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then + patch -R /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff; + fi +else + #disable any or authenticated targets for ACL + if patch -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then + patch /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff; + fi fi +# Copy logo, if any +[[ -f /etc/sogo/sogo-full.svg ]] && cp /etc/sogo/sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg + +# Rsync web content +echo "Syncing web content with named volume" +rsync -a /usr/lib/GNUstep/SOGo/. /sogo_web/ + exec gosu sogo /usr/sbin/sogod diff --git a/data/Dockerfiles/sogo/sogo-full.svg b/data/Dockerfiles/sogo/sogo-full.svg deleted file mode 100644 index 281ee7c6..00000000 --- a/data/Dockerfiles/sogo/sogo-full.svg +++ /dev/null @@ -1,160 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/data/Dockerfiles/sogo/stop-supervisor.sh b/data/Dockerfiles/sogo/stop-supervisor.sh new file mode 100755 index 00000000..5394490c --- /dev/null +++ b/data/Dockerfiles/sogo/stop-supervisor.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +printf "READY\n"; + +while read line; do + echo "Processing Event: $line" >&2; + kill -3 $(cat "/var/run/supervisord.pid") +done < /dev/stdin diff --git a/data/Dockerfiles/sogo/supervisord.conf b/data/Dockerfiles/sogo/supervisord.conf index 2a889560..551a8e12 100644 --- a/data/Dockerfiles/sogo/supervisord.conf +++ b/data/Dockerfiles/sogo/supervisord.conf @@ -16,13 +16,6 @@ command=/usr/sbin/cron -f autorestart=true priority=2 -[program:sogo-webres] -command=/usr/bin/python -u -m SimpleHTTPServer 9192 -directory=/usr/lib/GNUstep/SOGo/ -user=sogo -autorestart=true -priority=4 - [program:bootstrap-sogo] command=/bootstrap-sogo.sh stdout_logfile=/dev/stdout @@ -33,3 +26,7 @@ priority=3 startretries=10 autorestart=true stopwaitsecs=120 + +[eventlistener:processes] +command=/usr/local/sbin/stop-supervisor.sh +events=PROCESS_STATE_STOPPED, PROCESS_STATE_EXITED, PROCESS_STATE_FATAL diff --git a/data/Dockerfiles/sogo/theme-blue.css b/data/Dockerfiles/sogo/theme-blue.css deleted file mode 100644 index 1282d405..00000000 --- a/data/Dockerfiles/sogo/theme-blue.css +++ /dev/null @@ -1,16 +0,0 @@ -md-autocomplete.md-default-theme input, md-autocomplete input{color:rgba(0,0,0,0.87)}.md-autocomplete-suggestions-container.md-default-theme li, .md-autocomplete-suggestions-container li{color:rgba(0,0,0,0.87)}md-bottom-sheet.md-default-theme.md-list md-list-item, md-bottom-sheet.md-list md-list-item{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-primary, .md-button.md-primary{color:rgb(25,118,210)}.md-button.md-default-theme.md-primary.md-fab, .md-button.md-primary.md-fab,.md-button.md-default-theme.md-primary.md-raised, .md-button.md-primary.md-raised{color:rgba(255,255,255,0.87);background-color:rgb(25,118,210)}.md-button.md-default-theme.md-primary.md-fab:not([disabled]) md-icon, .md-button.md-primary.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-primary.md-raised:not([disabled]) md-icon, .md-button.md-primary.md-raised:not([disabled]) md-icon{color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-primary.md-fab:not([disabled]).md-focused, .md-button.md-primary.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-primary.md-fab:not([disabled]):hover, .md-button.md-primary.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-primary.md-raised:not([disabled]).md-focused, .md-button.md-primary.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-primary.md-raised:not([disabled]):hover, .md-button.md-primary.md-raised:not([disabled]):hover{background-color:rgb(30,136,229)}.md-button.md-default-theme.md-primary:not([disabled]) md-icon, .md-button.md-primary:not([disabled]) md-icon{color:rgb(25,118,210)}._md a.md-default-theme:not(.md-button).md-primary, ._md a:not(.md-button).md-primary{color:rgb(25,118,210)}._md a.md-default-theme:not(.md-button).md-primary:hover, ._md a:not(.md-button).md-primary:hover{color:rgb(25,118,210)}md-card.md-default-theme .md-card-image, md-card .md-card-image{border-radius:2px 2px 0 0}md-card.md-default-theme md-card-header md-card-header-text .md-subhead, md-card md-card-header md-card-header-text .md-subhead,md-card.md-default-theme md-card-title md-card-title-text:not(:only-child) .md-subhead, md-card md-card-title md-card-title-text:not(:only-child) .md-subhead{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme .md-ink-ripple, md-checkbox .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not(.md-checked) .md-icon, md-checkbox:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not([disabled]).md-primary .md-ripple, md-checkbox:not([disabled]).md-primary .md-ripple{color:rgb(30,136,229)}md-checkbox.md-default-theme:not([disabled]).md-primary.md-checked .md-ripple, md-checkbox:not([disabled]).md-primary.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme:not([disabled]).md-primary .md-ink-ripple, md-checkbox:not([disabled]).md-primary .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not([disabled]).md-primary.md-checked .md-ink-ripple, md-checkbox:not([disabled]).md-primary.md-checked .md-ink-ripple{color:rgba(25,118,210,0.87)}md-checkbox.md-default-theme:not([disabled]).md-primary:not(.md-checked) .md-icon, md-checkbox:not([disabled]).md-primary:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not([disabled]).md-primary.md-checked .md-icon, md-checkbox:not([disabled]).md-primary.md-checked .md-icon{background-color:rgba(25,118,210,0.87)}md-checkbox.md-default-theme:not([disabled]).md-primary.md-checked.md-focused .md-container:before, md-checkbox:not([disabled]).md-primary.md-checked.md-focused .md-container:before{background-color:rgba(25,118,210,0.26)}md-checkbox.md-default-theme:not([disabled]).md-primary.md-checked .md-icon:after, md-checkbox:not([disabled]).md-primary.md-checked .md-icon:after{border-color:rgba(255,255,255,0.87)}md-checkbox.md-default-theme:not([disabled]).md-primary .md-indeterminate[disabled] .md-container, md-checkbox:not([disabled]).md-primary .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme[disabled]:not(.md-checked) .md-icon, md-checkbox[disabled]:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme[disabled] .md-icon:after, md-checkbox[disabled] .md-icon:after{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme[disabled] .md-label, md-checkbox[disabled] .md-label{color:rgba(0,0,0,0.38)}md-chips.md-default-theme .md-chips, md-chips .md-chips{box-shadow:0 1px rgba(0,0,0,0.12)}md-chips.md-default-theme .md-chips.md-focused, md-chips .md-chips.md-focused{box-shadow:0 2px rgb(25,118,210)}md-chips.md-default-theme .md-chips .md-chip-input-container input, md-chips .md-chips .md-chip-input-container input{color:rgba(0,0,0,0.87)}md-chips.md-default-theme .md-chips .md-chip-input-container input:-moz-placeholder, md-chips .md-chips .md-chip-input-container input:-moz-placeholder,md-chips.md-default-theme .md-chips .md-chip-input-container input::-moz-placeholder, md-chips .md-chips .md-chip-input-container input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme .md-chips .md-chip-input-container input:-ms-input-placeholder, md-chips .md-chips .md-chip-input-container input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme .md-chips .md-chip-input-container input::-webkit-input-placeholder, md-chips .md-chips .md-chip-input-container input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme md-chip.md-focused, md-chips md-chip.md-focused{background:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-chips.md-default-theme md-chip.md-focused md-icon, md-chips md-chip.md-focused md-icon{color:rgba(255,255,255,0.87)}.md-default-theme .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator, .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator{border:1px solid rgb(33,150,243)}.md-default-theme .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled, .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled{color:rgba(33,150,243,0.6)}.md-default-theme .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator,.md-default-theme .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator{background:rgb(33,150,243);color:rgba(0,0,0,0.87);border-color:transparent}.md-default-theme .md-calendar-date-disabled, .md-calendar-date-disabled,.md-default-theme .md-calendar-month-label-disabled, .md-calendar-month-label-disabled{color:rgba(0,0,0,0.38)}.md-default-theme .md-calendar-month-label md-icon, .md-calendar-month-label md-icon,.md-default-theme .md-datepicker-input, .md-datepicker-input{color:rgba(0,0,0,0.87)}.md-default-theme .md-datepicker-input:-moz-placeholder, .md-datepicker-input:-moz-placeholder,.md-default-theme .md-datepicker-input::-moz-placeholder, .md-datepicker-input::-moz-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme .md-datepicker-input:-ms-input-placeholder, .md-datepicker-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme .md-datepicker-input::-webkit-input-placeholder, .md-datepicker-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme .md-datepicker-input-container, .md-datepicker-input-container{border-bottom-color:rgba(0,0,0,0.12)}.md-default-theme .md-datepicker-input-container.md-datepicker-focused, .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(25,118,210)}.md-default-theme .md-datepicker-triangle-button .md-datepicker-expand-triangle, .md-datepicker-triangle-button .md-datepicker-expand-triangle{border-top-color:rgba(0,0,0,0.54)}.md-default-theme .md-datepicker-open .md-datepicker-calendar-icon, .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(25,118,210)}md-dialog.md-default-theme.md-content-overflow .md-actions, md-dialog.md-content-overflow .md-actions,md-dialog.md-default-theme.md-content-overflow md-dialog-actions, md-dialog.md-content-overflow md-dialog-actions,md-divider.md-default-theme, md-divider{border-top-color:rgba(0,0,0,0.12)}.layout-gt-lg-row>md-divider.md-default-theme, .layout-gt-lg-row>md-divider,.layout-gt-md-row>md-divider.md-default-theme, .layout-gt-md-row>md-divider,.layout-gt-sm-row>md-divider.md-default-theme, .layout-gt-sm-row>md-divider,.layout-gt-xs-row>md-divider.md-default-theme, .layout-gt-xs-row>md-divider,.layout-lg-row>md-divider.md-default-theme, .layout-lg-row>md-divider,.layout-md-row>md-divider.md-default-theme, .layout-md-row>md-divider,.layout-row>md-divider.md-default-theme, .layout-row>md-divider,.layout-sm-row>md-divider.md-default-theme, .layout-sm-row>md-divider,.layout-xl-row>md-divider.md-default-theme, .layout-xl-row>md-divider,.layout-xs-row>md-divider.md-default-theme, .layout-xs-row>md-divider{border-right-color:rgba(0,0,0,0.12)}md-icon.md-default-theme, md-icon{color:rgba(0,0,0,0.54)}md-icon.md-default-theme.md-primary, md-icon.md-primary{color:rgb(25,118,210)}md-input-container.md-default-theme .md-input, md-input-container .md-input{color:rgba(0,0,0,0.87);border-color:rgba(0,0,0,0.12)}md-input-container.md-default-theme .md-input:-moz-placeholder, md-input-container .md-input:-moz-placeholder,md-input-container.md-default-theme .md-input::-moz-placeholder, md-input-container .md-input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme .md-input:-ms-input-placeholder, md-input-container .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme .md-input::-webkit-input-placeholder, md-input-container .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme>md-icon, md-input-container>md-icon{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme .md-placeholder, md-input-container .md-placeholder,md-input-container.md-default-theme label, md-input-container label{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme:not(.md-input-focused):not(.md-input-invalid) label.md-required:after, md-input-container:not(.md-input-focused):not(.md-input-invalid) label.md-required:after{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme .md-input-message-animation .md-char-counter, md-input-container .md-input-message-animation .md-char-counter,md-input-container.md-default-theme .md-input-messages-animation .md-char-counter, md-input-container .md-input-messages-animation .md-char-counter{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-input-focused .md-input:-moz-placeholder, md-input-container.md-input-focused .md-input:-moz-placeholder,md-input-container.md-default-theme.md-input-focused .md-input::-moz-placeholder, md-input-container.md-input-focused .md-input::-moz-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-input-focused .md-input:-ms-input-placeholder, md-input-container.md-input-focused .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-input-focused .md-input::-webkit-input-placeholder, md-input-container.md-input-focused .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-has-value label, md-input-container:not(.md-input-invalid).md-input-has-value label{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused .md-input, md-input-container:not(.md-input-invalid).md-input-focused .md-input,md-input-container.md-default-theme:not(.md-input-invalid).md-input-resized .md-input, md-input-container:not(.md-input-invalid).md-input-resized .md-input{border-color:rgb(25,118,210)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused label, md-input-container:not(.md-input-invalid).md-input-focused label,md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused md-icon, md-input-container:not(.md-input-invalid).md-input-focused md-icon{color:rgb(25,118,210)}md-list.md-default-theme md-list-item.md-2-line .md-list-item-text h3, md-list md-list-item.md-2-line .md-list-item-text h3,md-list.md-default-theme md-list-item.md-2-line .md-list-item-text h4, md-list md-list-item.md-2-line .md-list-item-text h4,md-list.md-default-theme md-list-item.md-3-line .md-list-item-text h3, md-list md-list-item.md-3-line .md-list-item-text h3,md-list.md-default-theme md-list-item.md-3-line .md-list-item-text h4, md-list md-list-item.md-3-line .md-list-item-text h4{color:rgba(0,0,0,0.87)}md-list.md-default-theme md-list-item.md-2-line .md-list-item-text p, md-list md-list-item.md-2-line .md-list-item-text p,md-list.md-default-theme md-list-item.md-3-line .md-list-item-text p, md-list md-list-item.md-3-line .md-list-item-text p{color:rgba(0,0,0,0.54)}md-list.md-default-theme md-list-item>md-icon, md-list md-list-item>md-icon{color:rgba(0,0,0,0.54)}md-list.md-default-theme md-list-item>md-icon.md-highlight, md-list md-list-item>md-icon.md-highlight{color:rgb(25,118,210)}md-menu-content.md-default-theme md-menu-item, md-menu-content md-menu-item{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme md-menu-item md-icon, md-menu-content md-menu-item md-icon{color:rgba(0,0,0,0.54)}md-menu-content.md-default-theme md-menu-item .md-button[disabled], md-menu-content md-menu-item .md-button[disabled],md-menu-content.md-default-theme md-menu-item .md-button[disabled] md-icon, md-menu-content md-menu-item .md-button[disabled] md-icon{color:rgba(0,0,0,0.38)}md-menu-bar.md-default-theme>button.md-button, md-menu-bar>button.md-button{color:rgba(0,0,0,0.87);border-radius:2px}md-menu-bar.md-default-theme md-menu>button, md-menu-bar md-menu>button{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme .md-menu>.md-button:after, md-menu-content .md-menu>.md-button:after{color:rgba(0,0,0,0.54)}md-toolbar.md-default-theme.md-menu-toolbar md-toolbar-filler, md-toolbar.md-menu-toolbar md-toolbar-filler{background-color:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme.md-menu-toolbar md-toolbar-filler md-icon, md-toolbar.md-menu-toolbar md-toolbar-filler md-icon{color:rgba(255,255,255,0.87)}md-nav-bar.md-default-theme .md-button._md-nav-button.md-unselected, md-nav-bar .md-button._md-nav-button.md-unselected{color:rgba(0,0,0,0.54)}md-nav-bar.md-default-theme .md-button._md-nav-button[disabled], md-nav-bar .md-button._md-nav-button[disabled]{color:rgba(0,0,0,0.38)}md-nav-bar.md-default-theme.md-primary>.md-nav-bar, md-nav-bar.md-primary>.md-nav-bar{background-color:rgb(25,118,210)}md-nav-bar.md-default-theme.md-primary>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-primary>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-nav-bar.md-default-theme.md-primary>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-primary>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-nav-bar.md-default-theme.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-toolbar>md-nav-bar.md-default-theme>.md-nav-bar, md-toolbar>md-nav-bar>.md-nav-bar{background-color:rgb(25,118,210)}md-toolbar>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button, md-toolbar>md-nav-bar>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-toolbar>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-toolbar>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-progress-circular.md-default-theme path, md-progress-circular path{stroke:rgb(25,118,210)}md-progress-linear.md-default-theme .md-container, md-progress-linear .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme .md-bar, md-progress-linear .md-bar{background-color:rgb(25,118,210)}md-progress-linear.md-default-theme[md-mode=buffer].md-primary .md-bar1, md-progress-linear[md-mode=buffer].md-primary .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme[md-mode=buffer].md-primary .md-dashed:before, md-progress-linear[md-mode=buffer].md-primary .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme .md-off, md-radio-button .md-off{border-color:rgba(0,0,0,0.54)}md-radio-button.md-default-theme:not([disabled]).md-primary .md-on, md-radio-button:not([disabled]).md-primary .md-on,md-radio-button.md-default-theme:not([disabled]) .md-primary .md-on, md-radio-button:not([disabled]) .md-primary .md-on,md-radio-group.md-default-theme:not([disabled]).md-primary .md-on, md-radio-group:not([disabled]).md-primary .md-on,md-radio-group.md-default-theme:not([disabled]) .md-primary .md-on, md-radio-group:not([disabled]) .md-primary .md-on{background-color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme:not([disabled]).md-primary.md-checked .md-off, md-radio-button:not([disabled]).md-primary.md-checked .md-off,md-radio-button.md-default-theme:not([disabled]) .md-primary.md-checked .md-off, md-radio-button:not([disabled]) .md-primary.md-checked .md-off,md-radio-button.md-default-theme:not([disabled]).md-primary .md-checked .md-off, md-radio-button:not([disabled]).md-primary .md-checked .md-off,md-radio-button.md-default-theme:not([disabled]) .md-primary .md-checked .md-off, md-radio-button:not([disabled]) .md-primary .md-checked .md-off,md-radio-group.md-default-theme:not([disabled]).md-primary.md-checked .md-off, md-radio-group:not([disabled]).md-primary.md-checked .md-off,md-radio-group.md-default-theme:not([disabled]) .md-primary.md-checked .md-off, md-radio-group:not([disabled]) .md-primary.md-checked .md-off,md-radio-group.md-default-theme:not([disabled]).md-primary .md-checked .md-off, md-radio-group:not([disabled]).md-primary .md-checked .md-off,md-radio-group.md-default-theme:not([disabled]) .md-primary .md-checked .md-off, md-radio-group:not([disabled]) .md-primary .md-checked .md-off{border-color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-button:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-button:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-button:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-button:not([disabled]) .md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-group:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-group:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-group:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-group:not([disabled]) .md-primary .md-checked .md-ink-ripple{color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme:not([disabled]).md-primary .md-container .md-ripple, md-radio-button:not([disabled]).md-primary .md-container .md-ripple,md-radio-button.md-default-theme:not([disabled]) .md-primary .md-container .md-ripple, md-radio-button:not([disabled]) .md-primary .md-container .md-ripple,md-radio-group.md-default-theme:not([disabled]).md-primary .md-container .md-ripple, md-radio-group:not([disabled]).md-primary .md-container .md-ripple,md-radio-group.md-default-theme:not([disabled]) .md-primary .md-container .md-ripple, md-radio-group:not([disabled]) .md-primary .md-container .md-ripple{color:rgb(30,136,229)}md-radio-button.md-default-theme[disabled], md-radio-button[disabled],md-radio-group.md-default-theme[disabled], md-radio-group[disabled]{color:rgba(0,0,0,0.38)}md-radio-button.md-default-theme[disabled] .md-container .md-off, md-radio-button[disabled] .md-container .md-off,md-radio-button.md-default-theme[disabled] .md-container .md-on, md-radio-button[disabled] .md-container .md-on,md-radio-group.md-default-theme[disabled] .md-container .md-off, md-radio-group[disabled] .md-container .md-off,md-radio-group.md-default-theme[disabled] .md-container .md-on, md-radio-group[disabled] .md-container .md-on{border-color:rgba(0,0,0,0.38)}md-radio-group.md-default-theme .md-checked:not([disabled]).md-primary .md-ink-ripple, md-radio-group .md-checked:not([disabled]).md-primary .md-ink-ripple,md-radio-group.md-default-theme.md-primary .md-checked:not([disabled]) .md-ink-ripple, md-radio-group.md-primary .md-checked:not([disabled]) .md-ink-ripple{color:rgba(25,118,210,0.26)}md-radio-group.md-default-theme.md-focused:not(:empty) .md-checked.md-primary .md-container:before, md-radio-group.md-focused:not(:empty) .md-checked.md-primary .md-container:before,md-radio-group.md-default-theme.md-focused:not(:empty).md-primary .md-checked .md-container:before, md-radio-group.md-focused:not(:empty).md-primary .md-checked .md-container:before{background-color:rgba(25,118,210,0.26)}md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-default-theme .md-select-value span:first-child:after, md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select .md-select-value span:first-child:after{color:rgba(0,0,0,0.38)}md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme .md-select-value, md-input-container.md-input-focused:not(.md-input-has-value) md-select .md-select-value,md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme .md-select-value.md-select-placeholder, md-input-container.md-input-focused:not(.md-input-has-value) md-select .md-select-value.md-select-placeholder{color:rgb(25,118,210)}md-input-container.md-input-invalid md-select.md-default-theme.md-no-underline .md-select-value, md-input-container.md-input-invalid md-select.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme .md-select-value, md-select .md-select-value{border-bottom-color:rgba(0,0,0,0.12)}md-select.md-default-theme .md-select-value.md-select-placeholder, md-select .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-no-underline .md-select-value, md-select.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.ng-invalid.ng-touched.md-no-underline .md-select-value, md-select.ng-invalid.ng-touched.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme:not([disabled]):focus .md-select-value, md-select:not([disabled]):focus .md-select-value{border-bottom-color:rgb(25,118,210);color:rgba(0,0,0,0.87)}md-select.md-default-theme:not([disabled]):focus .md-select-value.md-select-placeholder, md-select:not([disabled]):focus .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.87)}md-select.md-default-theme:not([disabled]):focus.md-no-underline .md-select-value, md-select:not([disabled]):focus.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme[disabled] .md-select-icon, md-select[disabled] .md-select-icon,md-select.md-default-theme[disabled] .md-select-value, md-select[disabled] .md-select-value,md-select.md-default-theme[disabled] .md-select-value.md-select-placeholder, md-select[disabled] .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme .md-select-icon, md-select .md-select-icon{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme md-content md-optgroup, md-select-menu md-content md-optgroup{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme md-content md-option, md-select-menu md-content md-option{color:rgba(0,0,0,0.87)}md-select-menu.md-default-theme md-content md-option[disabled] .md-text, md-select-menu md-content md-option[disabled] .md-text{color:rgba(0,0,0,0.38)}md-select-menu.md-default-theme md-content md-option[selected], md-select-menu md-content md-option[selected]{color:rgb(33,150,243)}md-select-menu.md-default-theme md-content md-option[selected]:focus, md-select-menu md-content md-option[selected]:focus{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme .md-ripple, .md-checkbox-enabled .md-ripple{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme .md-ink-ripple, .md-checkbox-enabled .md-ink-ripple{color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme[selected] .md-ink-ripple, .md-checkbox-enabled[selected] .md-ink-ripple{color:rgba(25,118,210,0.87)}.md-checkbox-enabled.md-default-theme:not(.md-checked) .md-icon, .md-checkbox-enabled:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme[selected] .md-icon, .md-checkbox-enabled[selected] .md-icon{background-color:rgba(25,118,210,0.87)}.md-checkbox-enabled.md-default-theme[selected].md-focused .md-container:before, .md-checkbox-enabled[selected].md-focused .md-container:before{background-color:rgba(25,118,210,0.26)}.md-checkbox-enabled.md-default-theme[selected] .md-icon:after, .md-checkbox-enabled[selected] .md-icon:after{border-color:rgba(255,255,255,0.87)}.md-checkbox-enabled.md-default-theme .md-indeterminate[disabled] .md-container, .md-checkbox-enabled .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}.md-checkbox-enabled.md-default-theme md-option .md-text, .md-checkbox-enabled md-option .md-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-primary .md-focus-ring, md-slider.md-primary .md-focus-ring{background-color:rgba(144,202,249,0.38)}md-slider.md-default-theme.md-primary .md-track.md-track-fill, md-slider.md-primary .md-track.md-track-fill{background-color:rgb(25,118,210)}md-slider.md-default-theme.md-primary .md-thumb:after, md-slider.md-primary .md-thumb:after{border-color:rgb(25,118,210);background-color:rgb(25,118,210)}md-slider.md-default-theme.md-primary .md-sign, md-slider.md-primary .md-sign{background-color:rgb(25,118,210)}md-slider.md-default-theme.md-primary .md-sign:after, md-slider.md-primary .md-sign:after{border-top-color:rgb(25,118,210)}md-slider.md-default-theme.md-primary[md-vertical] .md-sign:after, md-slider.md-primary[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(25,118,210)}md-slider.md-default-theme.md-primary .md-thumb-text, md-slider.md-primary .md-thumb-text{color:rgba(255,255,255,0.87)}md-slider.md-default-theme[disabled] .md-thumb:after, md-slider[disabled] .md-thumb:after{border-color:transparent}md-slider-container[disabled]>:first-child:not(md-slider),md-slider-container[disabled]>:last-child:not(md-slider){color:rgba(0,0,0,0.38)}.md-subheader.md-default-theme.md-primary, .md-subheader.md-primary{color:rgb(25,118,210)}md-switch.md-default-theme.md-checked.md-primary .md-ink-ripple, md-switch.md-checked.md-primary .md-ink-ripple{color:rgb(25,118,210)}md-switch.md-default-theme.md-checked.md-primary .md-thumb, md-switch.md-checked.md-primary .md-thumb{background-color:rgb(25,118,210)}md-switch.md-default-theme.md-checked.md-primary .md-bar, md-switch.md-checked.md-primary .md-bar{background-color:rgba(25,118,210,0.5)}md-switch.md-default-theme.md-checked.md-primary.md-focused .md-thumb:before, md-switch.md-checked.md-primary.md-focused .md-thumb:before{background-color:rgba(25,118,210,0.26)}md-tabs.md-default-theme .md-paginator md-icon, md-tabs .md-paginator md-icon{color:rgb(25,118,210)}md-tabs.md-default-theme .md-tab, md-tabs .md-tab{color:rgba(0,0,0,0.54)}md-tabs.md-default-theme .md-tab[disabled], md-tabs .md-tab[disabled],md-tabs.md-default-theme .md-tab[disabled] md-icon, md-tabs .md-tab[disabled] md-icon{color:rgba(0,0,0,0.38)}md-tabs.md-default-theme .md-tab.md-active, md-tabs .md-tab.md-active,md-tabs.md-default-theme .md-tab.md-active md-icon, md-tabs .md-tab.md-active md-icon,md-tabs.md-default-theme .md-tab.md-focused, md-tabs .md-tab.md-focused,md-tabs.md-default-theme .md-tab.md-focused md-icon, md-tabs .md-tab.md-focused md-icon{color:rgb(25,118,210)}md-tabs.md-default-theme .md-tab.md-focused, md-tabs .md-tab.md-focused{background:rgba(25,118,210,0.1)}md-tabs.md-default-theme.md-primary>md-tabs-wrapper, md-tabs.md-primary>md-tabs-wrapper{background-color:rgb(25,118,210)}md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-tabs.md-default-theme.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper, md-toolbar>md-tabs>md-tabs-wrapper{background-color:rgb(25,118,210)}md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-toolbar>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toast.md-default-theme .md-toast-content .md-button.md-highlight.md-primary, md-toast .md-toast-content .md-button.md-highlight.md-primary{color:rgb(25,118,210)}md-toolbar.md-default-theme:not(.md-menu-toolbar), md-toolbar:not(.md-menu-toolbar){background-color:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme:not(.md-menu-toolbar) md-icon, md-toolbar:not(.md-menu-toolbar) md-icon{color:rgba(255,255,255,0.87);fill:rgba(255,255,255,0.87)}md-toolbar.md-default-theme:not(.md-menu-toolbar) .md-button[disabled] md-icon, md-toolbar:not(.md-menu-toolbar) .md-button[disabled] md-icon{color:rgba(255,255,255,0.26);fill:rgba(255,255,255,0.26)} -md-autocomplete.md-default-theme.md-hue-1 input, md-autocomplete.md-hue-1 input{color:rgba(0,0,0,0.87)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-1 li, .md-autocomplete-suggestions-container.md-hue-1 li{color:rgba(0,0,0,0.87)}md-bottom-sheet.md-default-theme.md-hue-1.md-list md-list-item, md-bottom-sheet.md-hue-1.md-list md-list-item{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-primary, .md-button.md-hue-1.md-primary{color:rgb(33,150,243)}.md-button.md-default-theme.md-hue-1.md-primary.md-fab, .md-button.md-hue-1.md-primary.md-fab,.md-button.md-default-theme.md-hue-1.md-primary.md-raised, .md-button.md-hue-1.md-primary.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(33,150,243)}.md-button.md-default-theme.md-hue-1.md-primary.md-fab:not([disabled]) md-icon, .md-button.md-hue-1.md-primary.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-1.md-primary.md-raised:not([disabled]) md-icon, .md-button.md-hue-1.md-primary.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-primary.md-fab:not([disabled]).md-focused, .md-button.md-hue-1.md-primary.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-primary.md-fab:not([disabled]):hover, .md-button.md-hue-1.md-primary.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-1.md-primary.md-raised:not([disabled]).md-focused, .md-button.md-hue-1.md-primary.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-primary.md-raised:not([disabled]):hover, .md-button.md-hue-1.md-primary.md-raised:not([disabled]):hover{background-color:rgb(30,136,229)}.md-button.md-default-theme.md-hue-1.md-primary:not([disabled]) md-icon, .md-button.md-hue-1.md-primary:not([disabled]) md-icon{color:rgb(33,150,243)}._md a.md-default-theme.md-hue-1:not(.md-button).md-primary, ._md a.md-hue-1:not(.md-button).md-primary{color:rgb(33,150,243)}._md a.md-default-theme.md-hue-1:not(.md-button).md-primary:hover, ._md a.md-hue-1:not(.md-button).md-primary:hover{color:rgb(25,118,210)}md-card.md-default-theme.md-hue-1 .md-card-image, md-card.md-hue-1 .md-card-image{border-radius:2px 2px 0 0}md-card.md-default-theme.md-hue-1 md-card-header md-card-header-text .md-subhead, md-card.md-hue-1 md-card-header md-card-header-text .md-subhead,md-card.md-default-theme.md-hue-1 md-card-title md-card-title-text:not(:only-child) .md-subhead, md-card.md-hue-1 md-card-title md-card-title-text:not(:only-child) .md-subhead{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1 .md-ink-ripple, md-checkbox.md-hue-1 .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not(.md-checked) .md-icon, md-checkbox.md-hue-1:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary .md-ripple, md-checkbox.md-hue-1:not([disabled]).md-primary .md-ripple{color:rgb(30,136,229)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-ripple, md-checkbox.md-hue-1:not([disabled]).md-primary.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary .md-ink-ripple, md-checkbox.md-hue-1:not([disabled]).md-primary .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple, md-checkbox.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple{color:rgba(33,150,243,0.87)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary:not(.md-checked) .md-icon, md-checkbox.md-hue-1:not([disabled]).md-primary:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-icon, md-checkbox.md-hue-1:not([disabled]).md-primary.md-checked .md-icon{background-color:rgba(33,150,243,0.87)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked.md-focused .md-container:before, md-checkbox.md-hue-1:not([disabled]).md-primary.md-checked.md-focused .md-container:before{background-color:rgba(33,150,243,0.26)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-icon:after, md-checkbox.md-hue-1:not([disabled]).md-primary.md-checked .md-icon:after{border-color:rgba(0,0,0,0.87)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-primary .md-indeterminate[disabled] .md-container, md-checkbox.md-hue-1:not([disabled]).md-primary .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-1[disabled]:not(.md-checked) .md-icon, md-checkbox.md-hue-1[disabled]:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-1[disabled] .md-icon:after, md-checkbox.md-hue-1[disabled] .md-icon:after{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-1[disabled] .md-label, md-checkbox.md-hue-1[disabled] .md-label{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-1 .md-chips, md-chips.md-hue-1 .md-chips{box-shadow:0 1px rgba(0,0,0,0.12)}md-chips.md-default-theme.md-hue-1 .md-chips.md-focused, md-chips.md-hue-1 .md-chips.md-focused{box-shadow:0 2px rgb(33,150,243)}md-chips.md-default-theme.md-hue-1 .md-chips .md-chip-input-container input, md-chips.md-hue-1 .md-chips .md-chip-input-container input{color:rgba(0,0,0,0.87)}md-chips.md-default-theme.md-hue-1 .md-chips .md-chip-input-container input:-moz-placeholder, md-chips.md-hue-1 .md-chips .md-chip-input-container input:-moz-placeholder,md-chips.md-default-theme.md-hue-1 .md-chips .md-chip-input-container input::-moz-placeholder, md-chips.md-hue-1 .md-chips .md-chip-input-container input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-1 .md-chips .md-chip-input-container input:-ms-input-placeholder, md-chips.md-hue-1 .md-chips .md-chip-input-container input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-1 .md-chips .md-chip-input-container input::-webkit-input-placeholder, md-chips.md-hue-1 .md-chips .md-chip-input-container input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-1 md-chip.md-focused, md-chips.md-hue-1 md-chip.md-focused{background:rgb(33,150,243);color:rgba(0,0,0,0.87)}md-chips.md-default-theme.md-hue-1 md-chip.md-focused md-icon, md-chips.md-hue-1 md-chip.md-focused md-icon{color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-1 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator, .md-hue-1 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator{border:1px solid rgb(33,150,243)}.md-default-theme.md-hue-1 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled, .md-hue-1 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled{color:rgba(33,150,243,0.6)}.md-default-theme.md-hue-1 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-1 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator,.md-default-theme.md-hue-1 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-1 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator{background:rgb(33,150,243);color:rgba(0,0,0,0.87);border-color:transparent}.md-default-theme.md-hue-1 .md-calendar-date-disabled, .md-hue-1 .md-calendar-date-disabled,.md-default-theme.md-hue-1 .md-calendar-month-label-disabled, .md-hue-1 .md-calendar-month-label-disabled{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-1 .md-calendar-month-label md-icon, .md-hue-1 .md-calendar-month-label md-icon,.md-default-theme.md-hue-1 .md-datepicker-input, .md-hue-1 .md-datepicker-input{color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-1 .md-datepicker-input:-moz-placeholder, .md-hue-1 .md-datepicker-input:-moz-placeholder,.md-default-theme.md-hue-1 .md-datepicker-input::-moz-placeholder, .md-hue-1 .md-datepicker-input::-moz-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-1 .md-datepicker-input:-ms-input-placeholder, .md-hue-1 .md-datepicker-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-1 .md-datepicker-input::-webkit-input-placeholder, .md-hue-1 .md-datepicker-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-1 .md-datepicker-input-container, .md-hue-1 .md-datepicker-input-container{border-bottom-color:rgba(0,0,0,0.12)}.md-default-theme.md-hue-1 .md-datepicker-input-container.md-datepicker-focused, .md-hue-1 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(33,150,243)}.md-default-theme.md-hue-1 .md-datepicker-triangle-button .md-datepicker-expand-triangle, .md-hue-1 .md-datepicker-triangle-button .md-datepicker-expand-triangle{border-top-color:rgba(0,0,0,0.54)}.md-default-theme.md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon, .md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(33,150,243)}md-dialog.md-default-theme.md-hue-1.md-content-overflow .md-actions, md-dialog.md-hue-1.md-content-overflow .md-actions,md-dialog.md-default-theme.md-hue-1.md-content-overflow md-dialog-actions, md-dialog.md-hue-1.md-content-overflow md-dialog-actions,md-divider.md-default-theme.md-hue-1, md-divider.md-hue-1{border-top-color:rgba(0,0,0,0.12)}.layout-gt-lg-row>md-divider.md-default-theme.md-hue-1, .layout-gt-lg-row>md-divider.md-hue-1,.layout-gt-md-row>md-divider.md-default-theme.md-hue-1, .layout-gt-md-row>md-divider.md-hue-1,.layout-gt-sm-row>md-divider.md-default-theme.md-hue-1, .layout-gt-sm-row>md-divider.md-hue-1,.layout-gt-xs-row>md-divider.md-default-theme.md-hue-1, .layout-gt-xs-row>md-divider.md-hue-1,.layout-lg-row>md-divider.md-default-theme.md-hue-1, .layout-lg-row>md-divider.md-hue-1,.layout-md-row>md-divider.md-default-theme.md-hue-1, .layout-md-row>md-divider.md-hue-1,.layout-row>md-divider.md-default-theme.md-hue-1, .layout-row>md-divider.md-hue-1,.layout-sm-row>md-divider.md-default-theme.md-hue-1, .layout-sm-row>md-divider.md-hue-1,.layout-xl-row>md-divider.md-default-theme.md-hue-1, .layout-xl-row>md-divider.md-hue-1,.layout-xs-row>md-divider.md-default-theme.md-hue-1, .layout-xs-row>md-divider.md-hue-1{border-right-color:rgba(0,0,0,0.12)}md-icon.md-default-theme.md-hue-1, md-icon.md-hue-1{color:rgba(0,0,0,0.54)}md-icon.md-default-theme.md-hue-1.md-primary, md-icon.md-hue-1.md-primary{color:rgb(33,150,243)}md-input-container.md-default-theme.md-hue-1 .md-input, md-input-container.md-hue-1 .md-input{color:rgba(0,0,0,0.87);border-color:rgba(0,0,0,0.12)}md-input-container.md-default-theme.md-hue-1 .md-input:-moz-placeholder, md-input-container.md-hue-1 .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-1 .md-input::-moz-placeholder, md-input-container.md-hue-1 .md-input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-1 .md-input:-ms-input-placeholder, md-input-container.md-hue-1 .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-1 .md-input::-webkit-input-placeholder, md-input-container.md-hue-1 .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-1>md-icon, md-input-container.md-hue-1>md-icon{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-1 .md-placeholder, md-input-container.md-hue-1 .md-placeholder,md-input-container.md-default-theme.md-hue-1 label, md-input-container.md-hue-1 label{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-1:not(.md-input-focused):not(.md-input-invalid) label.md-required:after, md-input-container.md-hue-1:not(.md-input-focused):not(.md-input-invalid) label.md-required:after{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-1 .md-input-message-animation .md-char-counter, md-input-container.md-hue-1 .md-input-message-animation .md-char-counter,md-input-container.md-default-theme.md-hue-1 .md-input-messages-animation .md-char-counter, md-input-container.md-hue-1 .md-input-messages-animation .md-char-counter{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-1.md-input-focused .md-input:-moz-placeholder, md-input-container.md-hue-1.md-input-focused .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-1.md-input-focused .md-input::-moz-placeholder, md-input-container.md-hue-1.md-input-focused .md-input::-moz-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-1.md-input-focused .md-input:-ms-input-placeholder, md-input-container.md-hue-1.md-input-focused .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-1.md-input-focused .md-input::-webkit-input-placeholder, md-input-container.md-hue-1.md-input-focused .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-has-value label, md-input-container.md-hue-1:not(.md-input-invalid).md-input-has-value label{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused .md-input, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused .md-input,md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-resized .md-input, md-input-container.md-hue-1:not(.md-input-invalid).md-input-resized .md-input{border-color:rgb(33,150,243)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused label, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused label,md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused md-icon, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused md-icon{color:rgb(33,150,243)}md-list.md-default-theme.md-hue-1 md-list-item.md-2-line .md-list-item-text h3, md-list.md-hue-1 md-list-item.md-2-line .md-list-item-text h3,md-list.md-default-theme.md-hue-1 md-list-item.md-2-line .md-list-item-text h4, md-list.md-hue-1 md-list-item.md-2-line .md-list-item-text h4,md-list.md-default-theme.md-hue-1 md-list-item.md-3-line .md-list-item-text h3, md-list.md-hue-1 md-list-item.md-3-line .md-list-item-text h3,md-list.md-default-theme.md-hue-1 md-list-item.md-3-line .md-list-item-text h4, md-list.md-hue-1 md-list-item.md-3-line .md-list-item-text h4{color:rgba(0,0,0,0.87)}md-list.md-default-theme.md-hue-1 md-list-item.md-2-line .md-list-item-text p, md-list.md-hue-1 md-list-item.md-2-line .md-list-item-text p,md-list.md-default-theme.md-hue-1 md-list-item.md-3-line .md-list-item-text p, md-list.md-hue-1 md-list-item.md-3-line .md-list-item-text p{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-1 md-list-item>md-icon, md-list.md-hue-1 md-list-item>md-icon{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-1 md-list-item>md-icon.md-highlight, md-list.md-hue-1 md-list-item>md-icon.md-highlight{color:rgb(33,150,243)}md-menu-content.md-default-theme.md-hue-1 md-menu-item, md-menu-content.md-hue-1 md-menu-item{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-1 md-menu-item md-icon, md-menu-content.md-hue-1 md-menu-item md-icon{color:rgba(0,0,0,0.54)}md-menu-content.md-default-theme.md-hue-1 md-menu-item .md-button[disabled], md-menu-content.md-hue-1 md-menu-item .md-button[disabled],md-menu-content.md-default-theme.md-hue-1 md-menu-item .md-button[disabled] md-icon, md-menu-content.md-hue-1 md-menu-item .md-button[disabled] md-icon{color:rgba(0,0,0,0.38)}md-menu-bar.md-default-theme.md-hue-1>button.md-button, md-menu-bar.md-hue-1>button.md-button{color:rgba(0,0,0,0.87);border-radius:2px}md-menu-bar.md-default-theme.md-hue-1 md-menu>button, md-menu-bar.md-hue-1 md-menu>button{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-1 .md-menu>.md-button:after, md-menu-content.md-hue-1 .md-menu>.md-button:after{color:rgba(0,0,0,0.54)}md-toolbar.md-default-theme.md-hue-1.md-menu-toolbar md-toolbar-filler, md-toolbar.md-hue-1.md-menu-toolbar md-toolbar-filler{background-color:rgb(33,150,243);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1.md-menu-toolbar md-toolbar-filler md-icon, md-toolbar.md-hue-1.md-menu-toolbar md-toolbar-filler md-icon{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-1 .md-button._md-nav-button.md-unselected, md-nav-bar.md-hue-1 .md-button._md-nav-button.md-unselected{color:rgba(0,0,0,0.54)}md-nav-bar.md-default-theme.md-hue-1 .md-button._md-nav-button[disabled], md-nav-bar.md-hue-1 .md-button._md-nav-button[disabled]{color:rgba(0,0,0,0.38)}md-nav-bar.md-default-theme.md-hue-1.md-primary>.md-nav-bar, md-nav-bar.md-hue-1.md-primary>.md-nav-bar{background-color:rgb(33,150,243)}md-nav-bar.md-default-theme.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-nav-bar.md-default-theme.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar, md-toolbar>md-nav-bar.md-hue-1>.md-nav-bar{background-color:rgb(33,150,243)}md-toolbar>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button, md-toolbar>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-toolbar>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-progress-circular.md-default-theme.md-hue-1 path, md-progress-circular.md-hue-1 path{stroke:rgb(33,150,243)}md-progress-linear.md-default-theme.md-hue-1 .md-container, md-progress-linear.md-hue-1 .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-1 .md-bar, md-progress-linear.md-hue-1 .md-bar{background-color:rgb(33,150,243)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-primary .md-bar1, md-progress-linear.md-hue-1[md-mode=buffer].md-primary .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-primary .md-dashed:before, md-progress-linear.md-hue-1[md-mode=buffer].md-primary .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-1 .md-off, md-radio-button.md-hue-1 .md-off{border-color:rgba(0,0,0,0.54)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary .md-on, md-radio-button.md-hue-1:not([disabled]).md-primary .md-on,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-on, md-radio-button.md-hue-1:not([disabled]) .md-primary .md-on,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary .md-on, md-radio-group.md-hue-1:not([disabled]).md-primary .md-on,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-on, md-radio-group.md-hue-1:not([disabled]) .md-primary .md-on{background-color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-off, md-radio-button.md-hue-1:not([disabled]).md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary.md-checked .md-off, md-radio-button.md-hue-1:not([disabled]) .md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary .md-checked .md-off, md-radio-button.md-hue-1:not([disabled]).md-primary .md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-checked .md-off, md-radio-button.md-hue-1:not([disabled]) .md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-off, md-radio-group.md-hue-1:not([disabled]).md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary.md-checked .md-off, md-radio-group.md-hue-1:not([disabled]) .md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary .md-checked .md-off, md-radio-group.md-hue-1:not([disabled]).md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-checked .md-off, md-radio-group.md-hue-1:not([disabled]) .md-primary .md-checked .md-off{border-color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]) .md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]) .md-primary .md-checked .md-ink-ripple{color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-primary .md-container .md-ripple, md-radio-button.md-hue-1:not([disabled]).md-primary .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-container .md-ripple, md-radio-button.md-hue-1:not([disabled]) .md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-primary .md-container .md-ripple, md-radio-group.md-hue-1:not([disabled]).md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-primary .md-container .md-ripple, md-radio-group.md-hue-1:not([disabled]) .md-primary .md-container .md-ripple{color:rgb(30,136,229)}md-radio-button.md-default-theme.md-hue-1[disabled], md-radio-button.md-hue-1[disabled],md-radio-group.md-default-theme.md-hue-1[disabled], md-radio-group.md-hue-1[disabled]{color:rgba(0,0,0,0.38)}md-radio-button.md-default-theme.md-hue-1[disabled] .md-container .md-off, md-radio-button.md-hue-1[disabled] .md-container .md-off,md-radio-button.md-default-theme.md-hue-1[disabled] .md-container .md-on, md-radio-button.md-hue-1[disabled] .md-container .md-on,md-radio-group.md-default-theme.md-hue-1[disabled] .md-container .md-off, md-radio-group.md-hue-1[disabled] .md-container .md-off,md-radio-group.md-default-theme.md-hue-1[disabled] .md-container .md-on, md-radio-group.md-hue-1[disabled] .md-container .md-on{border-color:rgba(0,0,0,0.38)}md-radio-group.md-default-theme.md-hue-1 .md-checked:not([disabled]).md-primary .md-ink-ripple, md-radio-group.md-hue-1 .md-checked:not([disabled]).md-primary .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1.md-primary .md-checked:not([disabled]) .md-ink-ripple, md-radio-group.md-hue-1.md-primary .md-checked:not([disabled]) .md-ink-ripple{color:rgba(33,150,243,0.26)}md-radio-group.md-default-theme.md-hue-1.md-focused:not(:empty) .md-checked.md-primary .md-container:before, md-radio-group.md-hue-1.md-focused:not(:empty) .md-checked.md-primary .md-container:before,md-radio-group.md-default-theme.md-hue-1.md-focused:not(:empty).md-primary .md-checked .md-container:before, md-radio-group.md-hue-1.md-focused:not(:empty).md-primary .md-checked .md-container:before{background-color:rgba(33,150,243,0.26)}md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-default-theme.md-hue-1 .md-select-value span:first-child:after, md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-hue-1 .md-select-value span:first-child:after{color:rgba(0,0,0,0.38)}md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-1 .md-select-value, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-1 .md-select-value,md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-1 .md-select-value.md-select-placeholder, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-1 .md-select-value.md-select-placeholder{color:rgb(33,150,243)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-1.md-no-underline .md-select-value, md-input-container.md-input-invalid md-select.md-hue-1.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-1 .md-select-value, md-select.md-hue-1 .md-select-value{border-bottom-color:rgba(0,0,0,0.12)}md-select.md-default-theme.md-hue-1 .md-select-value.md-select-placeholder, md-select.md-hue-1 .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-1.md-no-underline .md-select-value, md-select.md-hue-1.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-1.ng-invalid.ng-touched.md-no-underline .md-select-value, md-select.md-hue-1.ng-invalid.ng-touched.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-1:not([disabled]):focus .md-select-value, md-select.md-hue-1:not([disabled]):focus .md-select-value{border-bottom-color:rgb(33,150,243);color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-1:not([disabled]):focus .md-select-value.md-select-placeholder, md-select.md-hue-1:not([disabled]):focus .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-1:not([disabled]):focus.md-no-underline .md-select-value, md-select.md-hue-1:not([disabled]):focus.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-1[disabled] .md-select-icon, md-select.md-hue-1[disabled] .md-select-icon,md-select.md-default-theme.md-hue-1[disabled] .md-select-value, md-select.md-hue-1[disabled] .md-select-value,md-select.md-default-theme.md-hue-1[disabled] .md-select-value.md-select-placeholder, md-select.md-hue-1[disabled] .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-1 .md-select-icon, md-select.md-hue-1 .md-select-icon{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-1 md-content md-optgroup, md-select-menu.md-hue-1 md-content md-optgroup{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-1 md-content md-option, md-select-menu.md-hue-1 md-content md-option{color:rgba(0,0,0,0.87)}md-select-menu.md-default-theme.md-hue-1 md-content md-option[disabled] .md-text, md-select-menu.md-hue-1 md-content md-option[disabled] .md-text{color:rgba(0,0,0,0.38)}md-select-menu.md-default-theme.md-hue-1 md-content md-option[selected], md-select-menu.md-hue-1 md-content md-option[selected]{color:rgb(33,150,243)}md-select-menu.md-default-theme.md-hue-1 md-content md-option[selected]:focus, md-select-menu.md-hue-1 md-content md-option[selected]:focus{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-1 .md-ripple, .md-checkbox-enabled.md-hue-1 .md-ripple{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-1 .md-ink-ripple, .md-checkbox-enabled.md-hue-1 .md-ink-ripple{color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-1[selected] .md-ink-ripple, .md-checkbox-enabled.md-hue-1[selected] .md-ink-ripple{color:rgba(33,150,243,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-1:not(.md-checked) .md-icon, .md-checkbox-enabled.md-hue-1:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-1[selected] .md-icon, .md-checkbox-enabled.md-hue-1[selected] .md-icon{background-color:rgba(33,150,243,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-1[selected].md-focused .md-container:before, .md-checkbox-enabled.md-hue-1[selected].md-focused .md-container:before{background-color:rgba(33,150,243,0.26)}.md-checkbox-enabled.md-default-theme.md-hue-1[selected] .md-icon:after, .md-checkbox-enabled.md-hue-1[selected] .md-icon:after{border-color:rgba(0,0,0,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-1 .md-indeterminate[disabled] .md-container, .md-checkbox-enabled.md-hue-1 .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}.md-checkbox-enabled.md-default-theme.md-hue-1 md-option .md-text, .md-checkbox-enabled.md-hue-1 md-option .md-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-1.md-primary .md-focus-ring, md-slider.md-hue-1.md-primary .md-focus-ring{background-color:rgba(144,202,249,0.38)}md-slider.md-default-theme.md-hue-1.md-primary .md-track.md-track-fill, md-slider.md-hue-1.md-primary .md-track.md-track-fill{background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-1.md-primary .md-thumb:after, md-slider.md-hue-1.md-primary .md-thumb:after{border-color:rgb(33,150,243);background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-1.md-primary .md-sign, md-slider.md-hue-1.md-primary .md-sign{background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-1.md-primary .md-sign:after, md-slider.md-hue-1.md-primary .md-sign:after{border-top-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-1.md-primary[md-vertical] .md-sign:after, md-slider.md-hue-1.md-primary[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-1.md-primary .md-thumb-text, md-slider.md-hue-1.md-primary .md-thumb-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-1[disabled] .md-thumb:after, md-slider.md-hue-1[disabled] .md-thumb:after{border-color:transparent}md-slider-container[disabled]>:first-child:not(md-slider),md-slider-container[disabled]>:last-child:not(md-slider){color:rgba(0,0,0,0.38)}.md-subheader.md-default-theme.md-hue-1.md-primary, .md-subheader.md-hue-1.md-primary{color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-1.md-checked.md-primary .md-ink-ripple, md-switch.md-hue-1.md-checked.md-primary .md-ink-ripple{color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-1.md-checked.md-primary .md-thumb, md-switch.md-hue-1.md-checked.md-primary .md-thumb{background-color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-1.md-checked.md-primary .md-bar, md-switch.md-hue-1.md-checked.md-primary .md-bar{background-color:rgba(33,150,243,0.5)}md-switch.md-default-theme.md-hue-1.md-checked.md-primary.md-focused .md-thumb:before, md-switch.md-hue-1.md-checked.md-primary.md-focused .md-thumb:before{background-color:rgba(33,150,243,0.26)}md-tabs.md-default-theme.md-hue-1 .md-paginator md-icon, md-tabs.md-hue-1 .md-paginator md-icon{color:rgb(33,150,243)}md-tabs.md-default-theme.md-hue-1 .md-tab, md-tabs.md-hue-1 .md-tab{color:rgba(0,0,0,0.54)}md-tabs.md-default-theme.md-hue-1 .md-tab[disabled], md-tabs.md-hue-1 .md-tab[disabled],md-tabs.md-default-theme.md-hue-1 .md-tab[disabled] md-icon, md-tabs.md-hue-1 .md-tab[disabled] md-icon{color:rgba(0,0,0,0.38)}md-tabs.md-default-theme.md-hue-1 .md-tab.md-active, md-tabs.md-hue-1 .md-tab.md-active,md-tabs.md-default-theme.md-hue-1 .md-tab.md-active md-icon, md-tabs.md-hue-1 .md-tab.md-active md-icon,md-tabs.md-default-theme.md-hue-1 .md-tab.md-focused, md-tabs.md-hue-1 .md-tab.md-focused,md-tabs.md-default-theme.md-hue-1 .md-tab.md-focused md-icon, md-tabs.md-hue-1 .md-tab.md-focused md-icon{color:rgb(33,150,243)}md-tabs.md-default-theme.md-hue-1 .md-tab.md-focused, md-tabs.md-hue-1 .md-tab.md-focused{background:rgba(33,150,243,0.1)}md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper, md-tabs.md-hue-1.md-primary>md-tabs-wrapper{background-color:rgb(33,150,243)}md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper{background-color:rgb(33,150,243)}md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toast.md-default-theme.md-hue-1 .md-toast-content .md-button.md-highlight.md-primary, md-toast.md-hue-1 .md-toast-content .md-button.md-highlight.md-primary{color:rgb(33,150,243)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar), md-toolbar.md-hue-1:not(.md-menu-toolbar){background-color:rgb(33,150,243);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar) md-icon, md-toolbar.md-hue-1:not(.md-menu-toolbar) md-icon{color:rgba(0,0,0,0.87);fill:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar) .md-button[disabled] md-icon, md-toolbar.md-hue-1:not(.md-menu-toolbar) .md-button[disabled] md-icon{color:rgba(0,0,0,0.26);fill:rgba(0,0,0,0.26)} -md-autocomplete.md-default-theme.md-hue-2 input, md-autocomplete.md-hue-2 input{color:rgba(0,0,0,0.87)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-2 li, .md-autocomplete-suggestions-container.md-hue-2 li{color:rgba(0,0,0,0.87)}md-bottom-sheet.md-default-theme.md-hue-2.md-list md-list-item, md-bottom-sheet.md-hue-2.md-list md-list-item{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2.md-primary, .md-button.md-hue-2.md-primary{color:rgb(25,118,210)}.md-button.md-default-theme.md-hue-2.md-primary.md-fab, .md-button.md-hue-2.md-primary.md-fab,.md-button.md-default-theme.md-hue-2.md-primary.md-raised, .md-button.md-hue-2.md-primary.md-raised{color:rgba(255,255,255,0.87);background-color:rgb(25,118,210)}.md-button.md-default-theme.md-hue-2.md-primary.md-fab:not([disabled]) md-icon, .md-button.md-hue-2.md-primary.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-2.md-primary.md-raised:not([disabled]) md-icon, .md-button.md-hue-2.md-primary.md-raised:not([disabled]) md-icon{color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-hue-2.md-primary.md-fab:not([disabled]).md-focused, .md-button.md-hue-2.md-primary.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-primary.md-fab:not([disabled]):hover, .md-button.md-hue-2.md-primary.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-2.md-primary.md-raised:not([disabled]).md-focused, .md-button.md-hue-2.md-primary.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-primary.md-raised:not([disabled]):hover, .md-button.md-hue-2.md-primary.md-raised:not([disabled]):hover{background-color:rgb(30,136,229)}.md-button.md-default-theme.md-hue-2.md-primary:not([disabled]) md-icon, .md-button.md-hue-2.md-primary:not([disabled]) md-icon{color:rgb(25,118,210)}._md a.md-default-theme.md-hue-2:not(.md-button).md-primary, ._md a.md-hue-2:not(.md-button).md-primary{color:rgb(25,118,210)}._md a.md-default-theme.md-hue-2:not(.md-button).md-primary:hover, ._md a.md-hue-2:not(.md-button).md-primary:hover{color:rgb(25,118,210)}md-card.md-default-theme.md-hue-2 .md-card-image, md-card.md-hue-2 .md-card-image{border-radius:2px 2px 0 0}md-card.md-default-theme.md-hue-2 md-card-header md-card-header-text .md-subhead, md-card.md-hue-2 md-card-header md-card-header-text .md-subhead,md-card.md-default-theme.md-hue-2 md-card-title md-card-title-text:not(:only-child) .md-subhead, md-card.md-hue-2 md-card-title md-card-title-text:not(:only-child) .md-subhead{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2 .md-ink-ripple, md-checkbox.md-hue-2 .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not(.md-checked) .md-icon, md-checkbox.md-hue-2:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary .md-ripple, md-checkbox.md-hue-2:not([disabled]).md-primary .md-ripple{color:rgb(30,136,229)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-ripple, md-checkbox.md-hue-2:not([disabled]).md-primary.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary .md-ink-ripple, md-checkbox.md-hue-2:not([disabled]).md-primary .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple, md-checkbox.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple{color:rgba(25,118,210,0.87)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary:not(.md-checked) .md-icon, md-checkbox.md-hue-2:not([disabled]).md-primary:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-icon, md-checkbox.md-hue-2:not([disabled]).md-primary.md-checked .md-icon{background-color:rgba(25,118,210,0.87)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked.md-focused .md-container:before, md-checkbox.md-hue-2:not([disabled]).md-primary.md-checked.md-focused .md-container:before{background-color:rgba(25,118,210,0.26)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-icon:after, md-checkbox.md-hue-2:not([disabled]).md-primary.md-checked .md-icon:after{border-color:rgba(255,255,255,0.87)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-primary .md-indeterminate[disabled] .md-container, md-checkbox.md-hue-2:not([disabled]).md-primary .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-2[disabled]:not(.md-checked) .md-icon, md-checkbox.md-hue-2[disabled]:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-2[disabled] .md-icon:after, md-checkbox.md-hue-2[disabled] .md-icon:after{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-2[disabled] .md-label, md-checkbox.md-hue-2[disabled] .md-label{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-2 .md-chips, md-chips.md-hue-2 .md-chips{box-shadow:0 1px rgba(0,0,0,0.12)}md-chips.md-default-theme.md-hue-2 .md-chips.md-focused, md-chips.md-hue-2 .md-chips.md-focused{box-shadow:0 2px rgb(25,118,210)}md-chips.md-default-theme.md-hue-2 .md-chips .md-chip-input-container input, md-chips.md-hue-2 .md-chips .md-chip-input-container input{color:rgba(0,0,0,0.87)}md-chips.md-default-theme.md-hue-2 .md-chips .md-chip-input-container input:-moz-placeholder, md-chips.md-hue-2 .md-chips .md-chip-input-container input:-moz-placeholder,md-chips.md-default-theme.md-hue-2 .md-chips .md-chip-input-container input::-moz-placeholder, md-chips.md-hue-2 .md-chips .md-chip-input-container input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-2 .md-chips .md-chip-input-container input:-ms-input-placeholder, md-chips.md-hue-2 .md-chips .md-chip-input-container input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-2 .md-chips .md-chip-input-container input::-webkit-input-placeholder, md-chips.md-hue-2 .md-chips .md-chip-input-container input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-2 md-chip.md-focused, md-chips.md-hue-2 md-chip.md-focused{background:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-chips.md-default-theme.md-hue-2 md-chip.md-focused md-icon, md-chips.md-hue-2 md-chip.md-focused md-icon{color:rgba(255,255,255,0.87)}.md-default-theme.md-hue-2 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator, .md-hue-2 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator{border:1px solid rgb(33,150,243)}.md-default-theme.md-hue-2 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled, .md-hue-2 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled{color:rgba(33,150,243,0.6)}.md-default-theme.md-hue-2 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-2 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator,.md-default-theme.md-hue-2 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-2 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator{background:rgb(33,150,243);color:rgba(0,0,0,0.87);border-color:transparent}.md-default-theme.md-hue-2 .md-calendar-date-disabled, .md-hue-2 .md-calendar-date-disabled,.md-default-theme.md-hue-2 .md-calendar-month-label-disabled, .md-hue-2 .md-calendar-month-label-disabled{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-2 .md-calendar-month-label md-icon, .md-hue-2 .md-calendar-month-label md-icon,.md-default-theme.md-hue-2 .md-datepicker-input, .md-hue-2 .md-datepicker-input{color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-2 .md-datepicker-input:-moz-placeholder, .md-hue-2 .md-datepicker-input:-moz-placeholder,.md-default-theme.md-hue-2 .md-datepicker-input::-moz-placeholder, .md-hue-2 .md-datepicker-input::-moz-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-2 .md-datepicker-input:-ms-input-placeholder, .md-hue-2 .md-datepicker-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-2 .md-datepicker-input::-webkit-input-placeholder, .md-hue-2 .md-datepicker-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-2 .md-datepicker-input-container, .md-hue-2 .md-datepicker-input-container{border-bottom-color:rgba(0,0,0,0.12)}.md-default-theme.md-hue-2 .md-datepicker-input-container.md-datepicker-focused, .md-hue-2 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(25,118,210)}.md-default-theme.md-hue-2 .md-datepicker-triangle-button .md-datepicker-expand-triangle, .md-hue-2 .md-datepicker-triangle-button .md-datepicker-expand-triangle{border-top-color:rgba(0,0,0,0.54)}.md-default-theme.md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon, .md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(25,118,210)}md-dialog.md-default-theme.md-hue-2.md-content-overflow .md-actions, md-dialog.md-hue-2.md-content-overflow .md-actions,md-dialog.md-default-theme.md-hue-2.md-content-overflow md-dialog-actions, md-dialog.md-hue-2.md-content-overflow md-dialog-actions,md-divider.md-default-theme.md-hue-2, md-divider.md-hue-2{border-top-color:rgba(0,0,0,0.12)}.layout-gt-lg-row>md-divider.md-default-theme.md-hue-2, .layout-gt-lg-row>md-divider.md-hue-2,.layout-gt-md-row>md-divider.md-default-theme.md-hue-2, .layout-gt-md-row>md-divider.md-hue-2,.layout-gt-sm-row>md-divider.md-default-theme.md-hue-2, .layout-gt-sm-row>md-divider.md-hue-2,.layout-gt-xs-row>md-divider.md-default-theme.md-hue-2, .layout-gt-xs-row>md-divider.md-hue-2,.layout-lg-row>md-divider.md-default-theme.md-hue-2, .layout-lg-row>md-divider.md-hue-2,.layout-md-row>md-divider.md-default-theme.md-hue-2, .layout-md-row>md-divider.md-hue-2,.layout-row>md-divider.md-default-theme.md-hue-2, .layout-row>md-divider.md-hue-2,.layout-sm-row>md-divider.md-default-theme.md-hue-2, .layout-sm-row>md-divider.md-hue-2,.layout-xl-row>md-divider.md-default-theme.md-hue-2, .layout-xl-row>md-divider.md-hue-2,.layout-xs-row>md-divider.md-default-theme.md-hue-2, .layout-xs-row>md-divider.md-hue-2{border-right-color:rgba(0,0,0,0.12)}md-icon.md-default-theme.md-hue-2, md-icon.md-hue-2{color:rgba(0,0,0,0.54)}md-icon.md-default-theme.md-hue-2.md-primary, md-icon.md-hue-2.md-primary{color:rgb(25,118,210)}md-input-container.md-default-theme.md-hue-2 .md-input, md-input-container.md-hue-2 .md-input{color:rgba(0,0,0,0.87);border-color:rgba(0,0,0,0.12)}md-input-container.md-default-theme.md-hue-2 .md-input:-moz-placeholder, md-input-container.md-hue-2 .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-2 .md-input::-moz-placeholder, md-input-container.md-hue-2 .md-input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-2 .md-input:-ms-input-placeholder, md-input-container.md-hue-2 .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-2 .md-input::-webkit-input-placeholder, md-input-container.md-hue-2 .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-2>md-icon, md-input-container.md-hue-2>md-icon{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-2 .md-placeholder, md-input-container.md-hue-2 .md-placeholder,md-input-container.md-default-theme.md-hue-2 label, md-input-container.md-hue-2 label{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-2:not(.md-input-focused):not(.md-input-invalid) label.md-required:after, md-input-container.md-hue-2:not(.md-input-focused):not(.md-input-invalid) label.md-required:after{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-2 .md-input-message-animation .md-char-counter, md-input-container.md-hue-2 .md-input-message-animation .md-char-counter,md-input-container.md-default-theme.md-hue-2 .md-input-messages-animation .md-char-counter, md-input-container.md-hue-2 .md-input-messages-animation .md-char-counter{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-2.md-input-focused .md-input:-moz-placeholder, md-input-container.md-hue-2.md-input-focused .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-2.md-input-focused .md-input::-moz-placeholder, md-input-container.md-hue-2.md-input-focused .md-input::-moz-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-2.md-input-focused .md-input:-ms-input-placeholder, md-input-container.md-hue-2.md-input-focused .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-2.md-input-focused .md-input::-webkit-input-placeholder, md-input-container.md-hue-2.md-input-focused .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-has-value label, md-input-container.md-hue-2:not(.md-input-invalid).md-input-has-value label{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused .md-input, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused .md-input,md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-resized .md-input, md-input-container.md-hue-2:not(.md-input-invalid).md-input-resized .md-input{border-color:rgb(25,118,210)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused label, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused label,md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused md-icon, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused md-icon{color:rgb(25,118,210)}md-list.md-default-theme.md-hue-2 md-list-item.md-2-line .md-list-item-text h3, md-list.md-hue-2 md-list-item.md-2-line .md-list-item-text h3,md-list.md-default-theme.md-hue-2 md-list-item.md-2-line .md-list-item-text h4, md-list.md-hue-2 md-list-item.md-2-line .md-list-item-text h4,md-list.md-default-theme.md-hue-2 md-list-item.md-3-line .md-list-item-text h3, md-list.md-hue-2 md-list-item.md-3-line .md-list-item-text h3,md-list.md-default-theme.md-hue-2 md-list-item.md-3-line .md-list-item-text h4, md-list.md-hue-2 md-list-item.md-3-line .md-list-item-text h4{color:rgba(0,0,0,0.87)}md-list.md-default-theme.md-hue-2 md-list-item.md-2-line .md-list-item-text p, md-list.md-hue-2 md-list-item.md-2-line .md-list-item-text p,md-list.md-default-theme.md-hue-2 md-list-item.md-3-line .md-list-item-text p, md-list.md-hue-2 md-list-item.md-3-line .md-list-item-text p{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-2 md-list-item>md-icon, md-list.md-hue-2 md-list-item>md-icon{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-2 md-list-item>md-icon.md-highlight, md-list.md-hue-2 md-list-item>md-icon.md-highlight{color:rgb(25,118,210)}md-menu-content.md-default-theme.md-hue-2 md-menu-item, md-menu-content.md-hue-2 md-menu-item{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-2 md-menu-item md-icon, md-menu-content.md-hue-2 md-menu-item md-icon{color:rgba(0,0,0,0.54)}md-menu-content.md-default-theme.md-hue-2 md-menu-item .md-button[disabled], md-menu-content.md-hue-2 md-menu-item .md-button[disabled],md-menu-content.md-default-theme.md-hue-2 md-menu-item .md-button[disabled] md-icon, md-menu-content.md-hue-2 md-menu-item .md-button[disabled] md-icon{color:rgba(0,0,0,0.38)}md-menu-bar.md-default-theme.md-hue-2>button.md-button, md-menu-bar.md-hue-2>button.md-button{color:rgba(0,0,0,0.87);border-radius:2px}md-menu-bar.md-default-theme.md-hue-2 md-menu>button, md-menu-bar.md-hue-2 md-menu>button{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-2 .md-menu>.md-button:after, md-menu-content.md-hue-2 .md-menu>.md-button:after{color:rgba(0,0,0,0.54)}md-toolbar.md-default-theme.md-hue-2.md-menu-toolbar md-toolbar-filler, md-toolbar.md-hue-2.md-menu-toolbar md-toolbar-filler{background-color:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme.md-hue-2.md-menu-toolbar md-toolbar-filler md-icon, md-toolbar.md-hue-2.md-menu-toolbar md-toolbar-filler md-icon{color:rgba(255,255,255,0.87)}md-nav-bar.md-default-theme.md-hue-2 .md-button._md-nav-button.md-unselected, md-nav-bar.md-hue-2 .md-button._md-nav-button.md-unselected{color:rgba(0,0,0,0.54)}md-nav-bar.md-default-theme.md-hue-2 .md-button._md-nav-button[disabled], md-nav-bar.md-hue-2 .md-button._md-nav-button[disabled]{color:rgba(0,0,0,0.38)}md-nav-bar.md-default-theme.md-hue-2.md-primary>.md-nav-bar, md-nav-bar.md-hue-2.md-primary>.md-nav-bar{background-color:rgb(25,118,210)}md-nav-bar.md-default-theme.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-nav-bar.md-default-theme.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-nav-bar.md-default-theme.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-toolbar>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar, md-toolbar>md-nav-bar.md-hue-2>.md-nav-bar{background-color:rgb(25,118,210)}md-toolbar>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button, md-toolbar>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-toolbar>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-toolbar>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-progress-circular.md-default-theme.md-hue-2 path, md-progress-circular.md-hue-2 path{stroke:rgb(25,118,210)}md-progress-linear.md-default-theme.md-hue-2 .md-container, md-progress-linear.md-hue-2 .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-2 .md-bar, md-progress-linear.md-hue-2 .md-bar{background-color:rgb(25,118,210)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-primary .md-bar1, md-progress-linear.md-hue-2[md-mode=buffer].md-primary .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-primary .md-dashed:before, md-progress-linear.md-hue-2[md-mode=buffer].md-primary .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-2 .md-off, md-radio-button.md-hue-2 .md-off{border-color:rgba(0,0,0,0.54)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary .md-on, md-radio-button.md-hue-2:not([disabled]).md-primary .md-on,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-on, md-radio-button.md-hue-2:not([disabled]) .md-primary .md-on,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary .md-on, md-radio-group.md-hue-2:not([disabled]).md-primary .md-on,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-on, md-radio-group.md-hue-2:not([disabled]) .md-primary .md-on{background-color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-off, md-radio-button.md-hue-2:not([disabled]).md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary.md-checked .md-off, md-radio-button.md-hue-2:not([disabled]) .md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary .md-checked .md-off, md-radio-button.md-hue-2:not([disabled]).md-primary .md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-checked .md-off, md-radio-button.md-hue-2:not([disabled]) .md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-off, md-radio-group.md-hue-2:not([disabled]).md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary.md-checked .md-off, md-radio-group.md-hue-2:not([disabled]) .md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary .md-checked .md-off, md-radio-group.md-hue-2:not([disabled]).md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-checked .md-off, md-radio-group.md-hue-2:not([disabled]) .md-primary .md-checked .md-off{border-color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]) .md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]) .md-primary .md-checked .md-ink-ripple{color:rgba(25,118,210,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-primary .md-container .md-ripple, md-radio-button.md-hue-2:not([disabled]).md-primary .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-container .md-ripple, md-radio-button.md-hue-2:not([disabled]) .md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-primary .md-container .md-ripple, md-radio-group.md-hue-2:not([disabled]).md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-primary .md-container .md-ripple, md-radio-group.md-hue-2:not([disabled]) .md-primary .md-container .md-ripple{color:rgb(30,136,229)}md-radio-button.md-default-theme.md-hue-2[disabled], md-radio-button.md-hue-2[disabled],md-radio-group.md-default-theme.md-hue-2[disabled], md-radio-group.md-hue-2[disabled]{color:rgba(0,0,0,0.38)}md-radio-button.md-default-theme.md-hue-2[disabled] .md-container .md-off, md-radio-button.md-hue-2[disabled] .md-container .md-off,md-radio-button.md-default-theme.md-hue-2[disabled] .md-container .md-on, md-radio-button.md-hue-2[disabled] .md-container .md-on,md-radio-group.md-default-theme.md-hue-2[disabled] .md-container .md-off, md-radio-group.md-hue-2[disabled] .md-container .md-off,md-radio-group.md-default-theme.md-hue-2[disabled] .md-container .md-on, md-radio-group.md-hue-2[disabled] .md-container .md-on{border-color:rgba(0,0,0,0.38)}md-radio-group.md-default-theme.md-hue-2 .md-checked:not([disabled]).md-primary .md-ink-ripple, md-radio-group.md-hue-2 .md-checked:not([disabled]).md-primary .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2.md-primary .md-checked:not([disabled]) .md-ink-ripple, md-radio-group.md-hue-2.md-primary .md-checked:not([disabled]) .md-ink-ripple{color:rgba(25,118,210,0.26)}md-radio-group.md-default-theme.md-hue-2.md-focused:not(:empty) .md-checked.md-primary .md-container:before, md-radio-group.md-hue-2.md-focused:not(:empty) .md-checked.md-primary .md-container:before,md-radio-group.md-default-theme.md-hue-2.md-focused:not(:empty).md-primary .md-checked .md-container:before, md-radio-group.md-hue-2.md-focused:not(:empty).md-primary .md-checked .md-container:before{background-color:rgba(25,118,210,0.26)}md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-default-theme.md-hue-2 .md-select-value span:first-child:after, md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-hue-2 .md-select-value span:first-child:after{color:rgba(0,0,0,0.38)}md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-2 .md-select-value, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-2 .md-select-value,md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-2 .md-select-value.md-select-placeholder, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-2 .md-select-value.md-select-placeholder{color:rgb(25,118,210)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-2.md-no-underline .md-select-value, md-input-container.md-input-invalid md-select.md-hue-2.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-2 .md-select-value, md-select.md-hue-2 .md-select-value{border-bottom-color:rgba(0,0,0,0.12)}md-select.md-default-theme.md-hue-2 .md-select-value.md-select-placeholder, md-select.md-hue-2 .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-2.md-no-underline .md-select-value, md-select.md-hue-2.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-2.ng-invalid.ng-touched.md-no-underline .md-select-value, md-select.md-hue-2.ng-invalid.ng-touched.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-2:not([disabled]):focus .md-select-value, md-select.md-hue-2:not([disabled]):focus .md-select-value{border-bottom-color:rgb(25,118,210);color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-2:not([disabled]):focus .md-select-value.md-select-placeholder, md-select.md-hue-2:not([disabled]):focus .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-2:not([disabled]):focus.md-no-underline .md-select-value, md-select.md-hue-2:not([disabled]):focus.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-2[disabled] .md-select-icon, md-select.md-hue-2[disabled] .md-select-icon,md-select.md-default-theme.md-hue-2[disabled] .md-select-value, md-select.md-hue-2[disabled] .md-select-value,md-select.md-default-theme.md-hue-2[disabled] .md-select-value.md-select-placeholder, md-select.md-hue-2[disabled] .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-2 .md-select-icon, md-select.md-hue-2 .md-select-icon{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-2 md-content md-optgroup, md-select-menu.md-hue-2 md-content md-optgroup{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-2 md-content md-option, md-select-menu.md-hue-2 md-content md-option{color:rgba(0,0,0,0.87)}md-select-menu.md-default-theme.md-hue-2 md-content md-option[disabled] .md-text, md-select-menu.md-hue-2 md-content md-option[disabled] .md-text{color:rgba(0,0,0,0.38)}md-select-menu.md-default-theme.md-hue-2 md-content md-option[selected], md-select-menu.md-hue-2 md-content md-option[selected]{color:rgb(33,150,243)}md-select-menu.md-default-theme.md-hue-2 md-content md-option[selected]:focus, md-select-menu.md-hue-2 md-content md-option[selected]:focus{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-2 .md-ripple, .md-checkbox-enabled.md-hue-2 .md-ripple{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-2 .md-ink-ripple, .md-checkbox-enabled.md-hue-2 .md-ink-ripple{color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-2[selected] .md-ink-ripple, .md-checkbox-enabled.md-hue-2[selected] .md-ink-ripple{color:rgba(25,118,210,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-2:not(.md-checked) .md-icon, .md-checkbox-enabled.md-hue-2:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-2[selected] .md-icon, .md-checkbox-enabled.md-hue-2[selected] .md-icon{background-color:rgba(25,118,210,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-2[selected].md-focused .md-container:before, .md-checkbox-enabled.md-hue-2[selected].md-focused .md-container:before{background-color:rgba(25,118,210,0.26)}.md-checkbox-enabled.md-default-theme.md-hue-2[selected] .md-icon:after, .md-checkbox-enabled.md-hue-2[selected] .md-icon:after{border-color:rgba(255,255,255,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-2 .md-indeterminate[disabled] .md-container, .md-checkbox-enabled.md-hue-2 .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}.md-checkbox-enabled.md-default-theme.md-hue-2 md-option .md-text, .md-checkbox-enabled.md-hue-2 md-option .md-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-2.md-primary .md-focus-ring, md-slider.md-hue-2.md-primary .md-focus-ring{background-color:rgba(144,202,249,0.38)}md-slider.md-default-theme.md-hue-2.md-primary .md-track.md-track-fill, md-slider.md-hue-2.md-primary .md-track.md-track-fill{background-color:rgb(25,118,210)}md-slider.md-default-theme.md-hue-2.md-primary .md-thumb:after, md-slider.md-hue-2.md-primary .md-thumb:after{border-color:rgb(25,118,210);background-color:rgb(25,118,210)}md-slider.md-default-theme.md-hue-2.md-primary .md-sign, md-slider.md-hue-2.md-primary .md-sign{background-color:rgb(25,118,210)}md-slider.md-default-theme.md-hue-2.md-primary .md-sign:after, md-slider.md-hue-2.md-primary .md-sign:after{border-top-color:rgb(25,118,210)}md-slider.md-default-theme.md-hue-2.md-primary[md-vertical] .md-sign:after, md-slider.md-hue-2.md-primary[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(25,118,210)}md-slider.md-default-theme.md-hue-2.md-primary .md-thumb-text, md-slider.md-hue-2.md-primary .md-thumb-text{color:rgba(255,255,255,0.87)}md-slider.md-default-theme.md-hue-2[disabled] .md-thumb:after, md-slider.md-hue-2[disabled] .md-thumb:after{border-color:transparent}md-slider-container[disabled]>:first-child:not(md-slider),md-slider-container[disabled]>:last-child:not(md-slider){color:rgba(0,0,0,0.38)}.md-subheader.md-default-theme.md-hue-2.md-primary, .md-subheader.md-hue-2.md-primary{color:rgb(25,118,210)}md-switch.md-default-theme.md-hue-2.md-checked.md-primary .md-ink-ripple, md-switch.md-hue-2.md-checked.md-primary .md-ink-ripple{color:rgb(25,118,210)}md-switch.md-default-theme.md-hue-2.md-checked.md-primary .md-thumb, md-switch.md-hue-2.md-checked.md-primary .md-thumb{background-color:rgb(25,118,210)}md-switch.md-default-theme.md-hue-2.md-checked.md-primary .md-bar, md-switch.md-hue-2.md-checked.md-primary .md-bar{background-color:rgba(25,118,210,0.5)}md-switch.md-default-theme.md-hue-2.md-checked.md-primary.md-focused .md-thumb:before, md-switch.md-hue-2.md-checked.md-primary.md-focused .md-thumb:before{background-color:rgba(25,118,210,0.26)}md-tabs.md-default-theme.md-hue-2 .md-paginator md-icon, md-tabs.md-hue-2 .md-paginator md-icon{color:rgb(25,118,210)}md-tabs.md-default-theme.md-hue-2 .md-tab, md-tabs.md-hue-2 .md-tab{color:rgba(0,0,0,0.54)}md-tabs.md-default-theme.md-hue-2 .md-tab[disabled], md-tabs.md-hue-2 .md-tab[disabled],md-tabs.md-default-theme.md-hue-2 .md-tab[disabled] md-icon, md-tabs.md-hue-2 .md-tab[disabled] md-icon{color:rgba(0,0,0,0.38)}md-tabs.md-default-theme.md-hue-2 .md-tab.md-active, md-tabs.md-hue-2 .md-tab.md-active,md-tabs.md-default-theme.md-hue-2 .md-tab.md-active md-icon, md-tabs.md-hue-2 .md-tab.md-active md-icon,md-tabs.md-default-theme.md-hue-2 .md-tab.md-focused, md-tabs.md-hue-2 .md-tab.md-focused,md-tabs.md-default-theme.md-hue-2 .md-tab.md-focused md-icon, md-tabs.md-hue-2 .md-tab.md-focused md-icon{color:rgb(25,118,210)}md-tabs.md-default-theme.md-hue-2 .md-tab.md-focused, md-tabs.md-hue-2 .md-tab.md-focused{background:rgba(25,118,210,0.1)}md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper, md-tabs.md-hue-2.md-primary>md-tabs-wrapper{background-color:rgb(25,118,210)}md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-tabs.md-default-theme.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper{background-color:rgb(25,118,210)}md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-toolbar>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toast.md-default-theme.md-hue-2 .md-toast-content .md-button.md-highlight.md-primary, md-toast.md-hue-2 .md-toast-content .md-button.md-highlight.md-primary{color:rgb(25,118,210)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar), md-toolbar.md-hue-2:not(.md-menu-toolbar){background-color:rgb(25,118,210);color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar) md-icon, md-toolbar.md-hue-2:not(.md-menu-toolbar) md-icon{color:rgba(255,255,255,0.87);fill:rgba(255,255,255,0.87)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar) .md-button[disabled] md-icon, md-toolbar.md-hue-2:not(.md-menu-toolbar) .md-button[disabled] md-icon{color:rgba(255,255,255,0.26);fill:rgba(255,255,255,0.26)} -md-autocomplete.md-default-theme.md-hue-3 input, md-autocomplete.md-hue-3 input{color:rgba(0,0,0,0.87)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-3 li, .md-autocomplete-suggestions-container.md-hue-3 li{color:rgba(0,0,0,0.87)}md-bottom-sheet.md-default-theme.md-hue-3.md-list md-list-item, md-bottom-sheet.md-hue-3.md-list md-list-item{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-primary, .md-button.md-hue-3.md-primary{color:rgb(68,138,255)}.md-button.md-default-theme.md-hue-3.md-primary.md-fab, .md-button.md-hue-3.md-primary.md-fab,.md-button.md-default-theme.md-hue-3.md-primary.md-raised, .md-button.md-hue-3.md-primary.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(68,138,255)}.md-button.md-default-theme.md-hue-3.md-primary.md-fab:not([disabled]) md-icon, .md-button.md-hue-3.md-primary.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-3.md-primary.md-raised:not([disabled]) md-icon, .md-button.md-hue-3.md-primary.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-primary.md-fab:not([disabled]).md-focused, .md-button.md-hue-3.md-primary.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-primary.md-fab:not([disabled]):hover, .md-button.md-hue-3.md-primary.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-3.md-primary.md-raised:not([disabled]).md-focused, .md-button.md-hue-3.md-primary.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-primary.md-raised:not([disabled]):hover, .md-button.md-hue-3.md-primary.md-raised:not([disabled]):hover{background-color:rgb(30,136,229)}.md-button.md-default-theme.md-hue-3.md-primary:not([disabled]) md-icon, .md-button.md-hue-3.md-primary:not([disabled]) md-icon{color:rgb(68,138,255)}._md a.md-default-theme.md-hue-3:not(.md-button).md-primary, ._md a.md-hue-3:not(.md-button).md-primary{color:rgb(68,138,255)}._md a.md-default-theme.md-hue-3:not(.md-button).md-primary:hover, ._md a.md-hue-3:not(.md-button).md-primary:hover{color:rgb(25,118,210)}md-card.md-default-theme.md-hue-3 .md-card-image, md-card.md-hue-3 .md-card-image{border-radius:2px 2px 0 0}md-card.md-default-theme.md-hue-3 md-card-header md-card-header-text .md-subhead, md-card.md-hue-3 md-card-header md-card-header-text .md-subhead,md-card.md-default-theme.md-hue-3 md-card-title md-card-title-text:not(:only-child) .md-subhead, md-card.md-hue-3 md-card-title md-card-title-text:not(:only-child) .md-subhead{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3 .md-ink-ripple, md-checkbox.md-hue-3 .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not(.md-checked) .md-icon, md-checkbox.md-hue-3:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary .md-ripple, md-checkbox.md-hue-3:not([disabled]).md-primary .md-ripple{color:rgb(30,136,229)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-ripple, md-checkbox.md-hue-3:not([disabled]).md-primary.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary .md-ink-ripple, md-checkbox.md-hue-3:not([disabled]).md-primary .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple, md-checkbox.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple{color:rgba(68,138,255,0.87)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary:not(.md-checked) .md-icon, md-checkbox.md-hue-3:not([disabled]).md-primary:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-icon, md-checkbox.md-hue-3:not([disabled]).md-primary.md-checked .md-icon{background-color:rgba(68,138,255,0.87)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked.md-focused .md-container:before, md-checkbox.md-hue-3:not([disabled]).md-primary.md-checked.md-focused .md-container:before{background-color:rgba(68,138,255,0.26)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-icon:after, md-checkbox.md-hue-3:not([disabled]).md-primary.md-checked .md-icon:after{border-color:rgba(0,0,0,0.87)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-primary .md-indeterminate[disabled] .md-container, md-checkbox.md-hue-3:not([disabled]).md-primary .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-3[disabled]:not(.md-checked) .md-icon, md-checkbox.md-hue-3[disabled]:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-3[disabled] .md-icon:after, md-checkbox.md-hue-3[disabled] .md-icon:after{border-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-3[disabled] .md-label, md-checkbox.md-hue-3[disabled] .md-label{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-3 .md-chips, md-chips.md-hue-3 .md-chips{box-shadow:0 1px rgba(0,0,0,0.12)}md-chips.md-default-theme.md-hue-3 .md-chips.md-focused, md-chips.md-hue-3 .md-chips.md-focused{box-shadow:0 2px rgb(68,138,255)}md-chips.md-default-theme.md-hue-3 .md-chips .md-chip-input-container input, md-chips.md-hue-3 .md-chips .md-chip-input-container input{color:rgba(0,0,0,0.87)}md-chips.md-default-theme.md-hue-3 .md-chips .md-chip-input-container input:-moz-placeholder, md-chips.md-hue-3 .md-chips .md-chip-input-container input:-moz-placeholder,md-chips.md-default-theme.md-hue-3 .md-chips .md-chip-input-container input::-moz-placeholder, md-chips.md-hue-3 .md-chips .md-chip-input-container input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-3 .md-chips .md-chip-input-container input:-ms-input-placeholder, md-chips.md-hue-3 .md-chips .md-chip-input-container input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-3 .md-chips .md-chip-input-container input::-webkit-input-placeholder, md-chips.md-hue-3 .md-chips .md-chip-input-container input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-chips.md-default-theme.md-hue-3 md-chip.md-focused, md-chips.md-hue-3 md-chip.md-focused{background:rgb(68,138,255);color:rgba(0,0,0,0.87)}md-chips.md-default-theme.md-hue-3 md-chip.md-focused md-icon, md-chips.md-hue-3 md-chip.md-focused md-icon{color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-3 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator, .md-hue-3 .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator{border:1px solid rgb(33,150,243)}.md-default-theme.md-hue-3 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled, .md-hue-3 .md-calendar-date.md-calendar-date-today.md-calendar-date-disabled{color:rgba(33,150,243,0.6)}.md-default-theme.md-hue-3 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-3 .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator,.md-default-theme.md-hue-3 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator, .md-hue-3 .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator{background:rgb(33,150,243);color:rgba(0,0,0,0.87);border-color:transparent}.md-default-theme.md-hue-3 .md-calendar-date-disabled, .md-hue-3 .md-calendar-date-disabled,.md-default-theme.md-hue-3 .md-calendar-month-label-disabled, .md-hue-3 .md-calendar-month-label-disabled{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-3 .md-calendar-month-label md-icon, .md-hue-3 .md-calendar-month-label md-icon,.md-default-theme.md-hue-3 .md-datepicker-input, .md-hue-3 .md-datepicker-input{color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-3 .md-datepicker-input:-moz-placeholder, .md-hue-3 .md-datepicker-input:-moz-placeholder,.md-default-theme.md-hue-3 .md-datepicker-input::-moz-placeholder, .md-hue-3 .md-datepicker-input::-moz-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-3 .md-datepicker-input:-ms-input-placeholder, .md-hue-3 .md-datepicker-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-3 .md-datepicker-input::-webkit-input-placeholder, .md-hue-3 .md-datepicker-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}.md-default-theme.md-hue-3 .md-datepicker-input-container, .md-hue-3 .md-datepicker-input-container{border-bottom-color:rgba(0,0,0,0.12)}.md-default-theme.md-hue-3 .md-datepicker-input-container.md-datepicker-focused, .md-hue-3 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(68,138,255)}.md-default-theme.md-hue-3 .md-datepicker-triangle-button .md-datepicker-expand-triangle, .md-hue-3 .md-datepicker-triangle-button .md-datepicker-expand-triangle{border-top-color:rgba(0,0,0,0.54)}.md-default-theme.md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon, .md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(68,138,255)}md-dialog.md-default-theme.md-hue-3.md-content-overflow .md-actions, md-dialog.md-hue-3.md-content-overflow .md-actions,md-dialog.md-default-theme.md-hue-3.md-content-overflow md-dialog-actions, md-dialog.md-hue-3.md-content-overflow md-dialog-actions,md-divider.md-default-theme.md-hue-3, md-divider.md-hue-3{border-top-color:rgba(0,0,0,0.12)}.layout-gt-lg-row>md-divider.md-default-theme.md-hue-3, .layout-gt-lg-row>md-divider.md-hue-3,.layout-gt-md-row>md-divider.md-default-theme.md-hue-3, .layout-gt-md-row>md-divider.md-hue-3,.layout-gt-sm-row>md-divider.md-default-theme.md-hue-3, .layout-gt-sm-row>md-divider.md-hue-3,.layout-gt-xs-row>md-divider.md-default-theme.md-hue-3, .layout-gt-xs-row>md-divider.md-hue-3,.layout-lg-row>md-divider.md-default-theme.md-hue-3, .layout-lg-row>md-divider.md-hue-3,.layout-md-row>md-divider.md-default-theme.md-hue-3, .layout-md-row>md-divider.md-hue-3,.layout-row>md-divider.md-default-theme.md-hue-3, .layout-row>md-divider.md-hue-3,.layout-sm-row>md-divider.md-default-theme.md-hue-3, .layout-sm-row>md-divider.md-hue-3,.layout-xl-row>md-divider.md-default-theme.md-hue-3, .layout-xl-row>md-divider.md-hue-3,.layout-xs-row>md-divider.md-default-theme.md-hue-3, .layout-xs-row>md-divider.md-hue-3{border-right-color:rgba(0,0,0,0.12)}md-icon.md-default-theme.md-hue-3, md-icon.md-hue-3{color:rgba(0,0,0,0.54)}md-icon.md-default-theme.md-hue-3.md-primary, md-icon.md-hue-3.md-primary{color:rgb(68,138,255)}md-input-container.md-default-theme.md-hue-3 .md-input, md-input-container.md-hue-3 .md-input{color:rgba(0,0,0,0.87);border-color:rgba(0,0,0,0.12)}md-input-container.md-default-theme.md-hue-3 .md-input:-moz-placeholder, md-input-container.md-hue-3 .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-3 .md-input::-moz-placeholder, md-input-container.md-hue-3 .md-input::-moz-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-3 .md-input:-ms-input-placeholder, md-input-container.md-hue-3 .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-3 .md-input::-webkit-input-placeholder, md-input-container.md-hue-3 .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-3>md-icon, md-input-container.md-hue-3>md-icon{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-3 .md-placeholder, md-input-container.md-hue-3 .md-placeholder,md-input-container.md-default-theme.md-hue-3 label, md-input-container.md-hue-3 label{color:rgba(0,0,0,0.38)}md-input-container.md-default-theme.md-hue-3:not(.md-input-focused):not(.md-input-invalid) label.md-required:after, md-input-container.md-hue-3:not(.md-input-focused):not(.md-input-invalid) label.md-required:after{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-3 .md-input-message-animation .md-char-counter, md-input-container.md-hue-3 .md-input-message-animation .md-char-counter,md-input-container.md-default-theme.md-hue-3 .md-input-messages-animation .md-char-counter, md-input-container.md-hue-3 .md-input-messages-animation .md-char-counter{color:rgba(0,0,0,0.87)}md-input-container.md-default-theme.md-hue-3.md-input-focused .md-input:-moz-placeholder, md-input-container.md-hue-3.md-input-focused .md-input:-moz-placeholder,md-input-container.md-default-theme.md-hue-3.md-input-focused .md-input::-moz-placeholder, md-input-container.md-hue-3.md-input-focused .md-input::-moz-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-3.md-input-focused .md-input:-ms-input-placeholder, md-input-container.md-hue-3.md-input-focused .md-input:-ms-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-3.md-input-focused .md-input::-webkit-input-placeholder, md-input-container.md-hue-3.md-input-focused .md-input::-webkit-input-placeholder{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-has-value label, md-input-container.md-hue-3:not(.md-input-invalid).md-input-has-value label{color:rgba(0,0,0,0.54)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused .md-input, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused .md-input,md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-resized .md-input, md-input-container.md-hue-3:not(.md-input-invalid).md-input-resized .md-input{border-color:rgb(68,138,255)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused label, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused label,md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused md-icon, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused md-icon{color:rgb(68,138,255)}md-list.md-default-theme.md-hue-3 md-list-item.md-2-line .md-list-item-text h3, md-list.md-hue-3 md-list-item.md-2-line .md-list-item-text h3,md-list.md-default-theme.md-hue-3 md-list-item.md-2-line .md-list-item-text h4, md-list.md-hue-3 md-list-item.md-2-line .md-list-item-text h4,md-list.md-default-theme.md-hue-3 md-list-item.md-3-line .md-list-item-text h3, md-list.md-hue-3 md-list-item.md-3-line .md-list-item-text h3,md-list.md-default-theme.md-hue-3 md-list-item.md-3-line .md-list-item-text h4, md-list.md-hue-3 md-list-item.md-3-line .md-list-item-text h4{color:rgba(0,0,0,0.87)}md-list.md-default-theme.md-hue-3 md-list-item.md-2-line .md-list-item-text p, md-list.md-hue-3 md-list-item.md-2-line .md-list-item-text p,md-list.md-default-theme.md-hue-3 md-list-item.md-3-line .md-list-item-text p, md-list.md-hue-3 md-list-item.md-3-line .md-list-item-text p{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-3 md-list-item>md-icon, md-list.md-hue-3 md-list-item>md-icon{color:rgba(0,0,0,0.54)}md-list.md-default-theme.md-hue-3 md-list-item>md-icon.md-highlight, md-list.md-hue-3 md-list-item>md-icon.md-highlight{color:rgb(68,138,255)}md-menu-content.md-default-theme.md-hue-3 md-menu-item, md-menu-content.md-hue-3 md-menu-item{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-3 md-menu-item md-icon, md-menu-content.md-hue-3 md-menu-item md-icon{color:rgba(0,0,0,0.54)}md-menu-content.md-default-theme.md-hue-3 md-menu-item .md-button[disabled], md-menu-content.md-hue-3 md-menu-item .md-button[disabled],md-menu-content.md-default-theme.md-hue-3 md-menu-item .md-button[disabled] md-icon, md-menu-content.md-hue-3 md-menu-item .md-button[disabled] md-icon{color:rgba(0,0,0,0.38)}md-menu-bar.md-default-theme.md-hue-3>button.md-button, md-menu-bar.md-hue-3>button.md-button{color:rgba(0,0,0,0.87);border-radius:2px}md-menu-bar.md-default-theme.md-hue-3 md-menu>button, md-menu-bar.md-hue-3 md-menu>button{color:rgba(0,0,0,0.87)}md-menu-content.md-default-theme.md-hue-3 .md-menu>.md-button:after, md-menu-content.md-hue-3 .md-menu>.md-button:after{color:rgba(0,0,0,0.54)}md-toolbar.md-default-theme.md-hue-3.md-menu-toolbar md-toolbar-filler, md-toolbar.md-hue-3.md-menu-toolbar md-toolbar-filler{background-color:rgb(68,138,255);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3.md-menu-toolbar md-toolbar-filler md-icon, md-toolbar.md-hue-3.md-menu-toolbar md-toolbar-filler md-icon{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-3 .md-button._md-nav-button.md-unselected, md-nav-bar.md-hue-3 .md-button._md-nav-button.md-unselected{color:rgba(0,0,0,0.54)}md-nav-bar.md-default-theme.md-hue-3 .md-button._md-nav-button[disabled], md-nav-bar.md-hue-3 .md-button._md-nav-button[disabled]{color:rgba(0,0,0,0.38)}md-nav-bar.md-default-theme.md-hue-3.md-primary>.md-nav-bar, md-nav-bar.md-hue-3.md-primary>.md-nav-bar{background-color:rgb(68,138,255)}md-nav-bar.md-default-theme.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-nav-bar.md-default-theme.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-primary>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar, md-toolbar>md-nav-bar.md-hue-3>.md-nav-bar{background-color:rgb(68,138,255)}md-toolbar>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button, md-toolbar>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button{color:rgb(187,222,251)}md-toolbar>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-progress-circular.md-default-theme.md-hue-3 path, md-progress-circular.md-hue-3 path{stroke:rgb(68,138,255)}md-progress-linear.md-default-theme.md-hue-3 .md-container, md-progress-linear.md-hue-3 .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-3 .md-bar, md-progress-linear.md-hue-3 .md-bar{background-color:rgb(68,138,255)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-primary .md-bar1, md-progress-linear.md-hue-3[md-mode=buffer].md-primary .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-primary .md-dashed:before, md-progress-linear.md-hue-3[md-mode=buffer].md-primary .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-3 .md-off, md-radio-button.md-hue-3 .md-off{border-color:rgba(0,0,0,0.54)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary .md-on, md-radio-button.md-hue-3:not([disabled]).md-primary .md-on,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-on, md-radio-button.md-hue-3:not([disabled]) .md-primary .md-on,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary .md-on, md-radio-group.md-hue-3:not([disabled]).md-primary .md-on,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-on, md-radio-group.md-hue-3:not([disabled]) .md-primary .md-on{background-color:rgba(68,138,255,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-off, md-radio-button.md-hue-3:not([disabled]).md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary.md-checked .md-off, md-radio-button.md-hue-3:not([disabled]) .md-primary.md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary .md-checked .md-off, md-radio-button.md-hue-3:not([disabled]).md-primary .md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-checked .md-off, md-radio-button.md-hue-3:not([disabled]) .md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-off, md-radio-group.md-hue-3:not([disabled]).md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary.md-checked .md-off, md-radio-group.md-hue-3:not([disabled]) .md-primary.md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary .md-checked .md-off, md-radio-group.md-hue-3:not([disabled]).md-primary .md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-checked .md-off, md-radio-group.md-hue-3:not([disabled]) .md-primary .md-checked .md-off{border-color:rgba(68,138,255,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]) .md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]).md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary.md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]) .md-primary.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]).md-primary .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]) .md-primary .md-checked .md-ink-ripple{color:rgba(68,138,255,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-primary .md-container .md-ripple, md-radio-button.md-hue-3:not([disabled]).md-primary .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-container .md-ripple, md-radio-button.md-hue-3:not([disabled]) .md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-primary .md-container .md-ripple, md-radio-group.md-hue-3:not([disabled]).md-primary .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-primary .md-container .md-ripple, md-radio-group.md-hue-3:not([disabled]) .md-primary .md-container .md-ripple{color:rgb(30,136,229)}md-radio-button.md-default-theme.md-hue-3[disabled], md-radio-button.md-hue-3[disabled],md-radio-group.md-default-theme.md-hue-3[disabled], md-radio-group.md-hue-3[disabled]{color:rgba(0,0,0,0.38)}md-radio-button.md-default-theme.md-hue-3[disabled] .md-container .md-off, md-radio-button.md-hue-3[disabled] .md-container .md-off,md-radio-button.md-default-theme.md-hue-3[disabled] .md-container .md-on, md-radio-button.md-hue-3[disabled] .md-container .md-on,md-radio-group.md-default-theme.md-hue-3[disabled] .md-container .md-off, md-radio-group.md-hue-3[disabled] .md-container .md-off,md-radio-group.md-default-theme.md-hue-3[disabled] .md-container .md-on, md-radio-group.md-hue-3[disabled] .md-container .md-on{border-color:rgba(0,0,0,0.38)}md-radio-group.md-default-theme.md-hue-3 .md-checked:not([disabled]).md-primary .md-ink-ripple, md-radio-group.md-hue-3 .md-checked:not([disabled]).md-primary .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3.md-primary .md-checked:not([disabled]) .md-ink-ripple, md-radio-group.md-hue-3.md-primary .md-checked:not([disabled]) .md-ink-ripple{color:rgba(68,138,255,0.26)}md-radio-group.md-default-theme.md-hue-3.md-focused:not(:empty) .md-checked.md-primary .md-container:before, md-radio-group.md-hue-3.md-focused:not(:empty) .md-checked.md-primary .md-container:before,md-radio-group.md-default-theme.md-hue-3.md-focused:not(:empty).md-primary .md-checked .md-container:before, md-radio-group.md-hue-3.md-focused:not(:empty).md-primary .md-checked .md-container:before{background-color:rgba(68,138,255,0.26)}md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-default-theme.md-hue-3 .md-select-value span:first-child:after, md-input-container:not(.md-input-focused):not(.md-input-invalid) md-select.md-hue-3 .md-select-value span:first-child:after{color:rgba(0,0,0,0.38)}md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-3 .md-select-value, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-3 .md-select-value,md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-default-theme.md-hue-3 .md-select-value.md-select-placeholder, md-input-container.md-input-focused:not(.md-input-has-value) md-select.md-hue-3 .md-select-value.md-select-placeholder{color:rgb(68,138,255)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-3.md-no-underline .md-select-value, md-input-container.md-input-invalid md-select.md-hue-3.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-3 .md-select-value, md-select.md-hue-3 .md-select-value{border-bottom-color:rgba(0,0,0,0.12)}md-select.md-default-theme.md-hue-3 .md-select-value.md-select-placeholder, md-select.md-hue-3 .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-3.md-no-underline .md-select-value, md-select.md-hue-3.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-3.ng-invalid.ng-touched.md-no-underline .md-select-value, md-select.md-hue-3.ng-invalid.ng-touched.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-3:not([disabled]):focus .md-select-value, md-select.md-hue-3:not([disabled]):focus .md-select-value{border-bottom-color:rgb(68,138,255);color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-3:not([disabled]):focus .md-select-value.md-select-placeholder, md-select.md-hue-3:not([disabled]):focus .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.87)}md-select.md-default-theme.md-hue-3:not([disabled]):focus.md-no-underline .md-select-value, md-select.md-hue-3:not([disabled]):focus.md-no-underline .md-select-value{border-bottom-color:transparent!important}md-select.md-default-theme.md-hue-3[disabled] .md-select-icon, md-select.md-hue-3[disabled] .md-select-icon,md-select.md-default-theme.md-hue-3[disabled] .md-select-value, md-select.md-hue-3[disabled] .md-select-value,md-select.md-default-theme.md-hue-3[disabled] .md-select-value.md-select-placeholder, md-select.md-hue-3[disabled] .md-select-value.md-select-placeholder{color:rgba(0,0,0,0.38)}md-select.md-default-theme.md-hue-3 .md-select-icon, md-select.md-hue-3 .md-select-icon{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-3 md-content md-optgroup, md-select-menu.md-hue-3 md-content md-optgroup{color:rgba(0,0,0,0.54)}md-select-menu.md-default-theme.md-hue-3 md-content md-option, md-select-menu.md-hue-3 md-content md-option{color:rgba(0,0,0,0.87)}md-select-menu.md-default-theme.md-hue-3 md-content md-option[disabled] .md-text, md-select-menu.md-hue-3 md-content md-option[disabled] .md-text{color:rgba(0,0,0,0.38)}md-select-menu.md-default-theme.md-hue-3 md-content md-option[selected], md-select-menu.md-hue-3 md-content md-option[selected]{color:rgb(33,150,243)}md-select-menu.md-default-theme.md-hue-3 md-content md-option[selected]:focus, md-select-menu.md-hue-3 md-content md-option[selected]:focus{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-3 .md-ripple, .md-checkbox-enabled.md-hue-3 .md-ripple{color:rgb(30,136,229)}.md-checkbox-enabled.md-default-theme.md-hue-3 .md-ink-ripple, .md-checkbox-enabled.md-hue-3 .md-ink-ripple{color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-3[selected] .md-ink-ripple, .md-checkbox-enabled.md-hue-3[selected] .md-ink-ripple{color:rgba(68,138,255,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-3:not(.md-checked) .md-icon, .md-checkbox-enabled.md-hue-3:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}.md-checkbox-enabled.md-default-theme.md-hue-3[selected] .md-icon, .md-checkbox-enabled.md-hue-3[selected] .md-icon{background-color:rgba(68,138,255,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-3[selected].md-focused .md-container:before, .md-checkbox-enabled.md-hue-3[selected].md-focused .md-container:before{background-color:rgba(68,138,255,0.26)}.md-checkbox-enabled.md-default-theme.md-hue-3[selected] .md-icon:after, .md-checkbox-enabled.md-hue-3[selected] .md-icon:after{border-color:rgba(0,0,0,0.87)}.md-checkbox-enabled.md-default-theme.md-hue-3 .md-indeterminate[disabled] .md-container, .md-checkbox-enabled.md-hue-3 .md-indeterminate[disabled] .md-container{color:rgba(0,0,0,0.38)}.md-checkbox-enabled.md-default-theme.md-hue-3 md-option .md-text, .md-checkbox-enabled.md-hue-3 md-option .md-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-3.md-primary .md-focus-ring, md-slider.md-hue-3.md-primary .md-focus-ring{background-color:rgba(144,202,249,0.38)}md-slider.md-default-theme.md-hue-3.md-primary .md-track.md-track-fill, md-slider.md-hue-3.md-primary .md-track.md-track-fill{background-color:rgb(68,138,255)}md-slider.md-default-theme.md-hue-3.md-primary .md-thumb:after, md-slider.md-hue-3.md-primary .md-thumb:after{border-color:rgb(68,138,255);background-color:rgb(68,138,255)}md-slider.md-default-theme.md-hue-3.md-primary .md-sign, md-slider.md-hue-3.md-primary .md-sign{background-color:rgb(68,138,255)}md-slider.md-default-theme.md-hue-3.md-primary .md-sign:after, md-slider.md-hue-3.md-primary .md-sign:after{border-top-color:rgb(68,138,255)}md-slider.md-default-theme.md-hue-3.md-primary[md-vertical] .md-sign:after, md-slider.md-hue-3.md-primary[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(68,138,255)}md-slider.md-default-theme.md-hue-3.md-primary .md-thumb-text, md-slider.md-hue-3.md-primary .md-thumb-text{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-3[disabled] .md-thumb:after, md-slider.md-hue-3[disabled] .md-thumb:after{border-color:transparent}md-slider-container[disabled]>:first-child:not(md-slider),md-slider-container[disabled]>:last-child:not(md-slider){color:rgba(0,0,0,0.38)}.md-subheader.md-default-theme.md-hue-3.md-primary, .md-subheader.md-hue-3.md-primary{color:rgb(68,138,255)}md-switch.md-default-theme.md-hue-3.md-checked.md-primary .md-ink-ripple, md-switch.md-hue-3.md-checked.md-primary .md-ink-ripple{color:rgb(68,138,255)}md-switch.md-default-theme.md-hue-3.md-checked.md-primary .md-thumb, md-switch.md-hue-3.md-checked.md-primary .md-thumb{background-color:rgb(68,138,255)}md-switch.md-default-theme.md-hue-3.md-checked.md-primary .md-bar, md-switch.md-hue-3.md-checked.md-primary .md-bar{background-color:rgba(68,138,255,0.5)}md-switch.md-default-theme.md-hue-3.md-checked.md-primary.md-focused .md-thumb:before, md-switch.md-hue-3.md-checked.md-primary.md-focused .md-thumb:before{background-color:rgba(68,138,255,0.26)}md-tabs.md-default-theme.md-hue-3 .md-paginator md-icon, md-tabs.md-hue-3 .md-paginator md-icon{color:rgb(68,138,255)}md-tabs.md-default-theme.md-hue-3 .md-tab, md-tabs.md-hue-3 .md-tab{color:rgba(0,0,0,0.54)}md-tabs.md-default-theme.md-hue-3 .md-tab[disabled], md-tabs.md-hue-3 .md-tab[disabled],md-tabs.md-default-theme.md-hue-3 .md-tab[disabled] md-icon, md-tabs.md-hue-3 .md-tab[disabled] md-icon{color:rgba(0,0,0,0.38)}md-tabs.md-default-theme.md-hue-3 .md-tab.md-active, md-tabs.md-hue-3 .md-tab.md-active,md-tabs.md-default-theme.md-hue-3 .md-tab.md-active md-icon, md-tabs.md-hue-3 .md-tab.md-active md-icon,md-tabs.md-default-theme.md-hue-3 .md-tab.md-focused, md-tabs.md-hue-3 .md-tab.md-focused,md-tabs.md-default-theme.md-hue-3 .md-tab.md-focused md-icon, md-tabs.md-hue-3 .md-tab.md-focused md-icon{color:rgb(68,138,255)}md-tabs.md-default-theme.md-hue-3 .md-tab.md-focused, md-tabs.md-hue-3 .md-tab.md-focused{background:rgba(68,138,255,0.1)}md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper, md-tabs.md-hue-3.md-primary>md-tabs-wrapper{background-color:rgb(68,138,255)}md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-primary>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper{background-color:rgb(68,138,255)}md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(187,222,251)}md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toast.md-default-theme.md-hue-3 .md-toast-content .md-button.md-highlight.md-primary, md-toast.md-hue-3 .md-toast-content .md-button.md-highlight.md-primary{color:rgb(68,138,255)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar), md-toolbar.md-hue-3:not(.md-menu-toolbar){background-color:rgb(68,138,255);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar) md-icon, md-toolbar.md-hue-3:not(.md-menu-toolbar) md-icon{color:rgba(0,0,0,0.87);fill:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar) .md-button[disabled] md-icon, md-toolbar.md-hue-3:not(.md-menu-toolbar) .md-button[disabled] md-icon{color:rgba(0,0,0,0.26);fill:rgba(0,0,0,0.26)} -.md-button.md-default-theme.md-fab md-icon, .md-button.md-fab md-icon{color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-fab, .md-button.md-fab{background-color:rgb(21,101,192);color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-fab:not([disabled]) .md-icon, .md-button.md-fab:not([disabled]) .md-icon{color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-fab:not([disabled]).md-focused, .md-button.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-fab:not([disabled]):hover, .md-button.md-fab:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-accent, .md-button.md-accent{color:rgb(21,101,192)}.md-button.md-default-theme.md-accent.md-fab, .md-button.md-accent.md-fab,.md-button.md-default-theme.md-accent.md-raised, .md-button.md-accent.md-raised{color:rgba(255,255,255,0.87);background-color:rgb(21,101,192)}.md-button.md-default-theme.md-accent.md-fab:not([disabled]) md-icon, .md-button.md-accent.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-accent.md-raised:not([disabled]) md-icon, .md-button.md-accent.md-raised:not([disabled]) md-icon{color:rgba(255,255,255,0.87)}.md-button.md-default-theme.md-accent.md-fab:not([disabled]).md-focused, .md-button.md-accent.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-accent.md-fab:not([disabled]):hover, .md-button.md-accent.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-accent.md-raised:not([disabled]).md-focused, .md-button.md-accent.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-accent.md-raised:not([disabled]):hover, .md-button.md-accent.md-raised:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-accent:not([disabled]) md-icon, .md-button.md-accent:not([disabled]) md-icon{color:rgb(21,101,192)}.md-button.md-default-theme.md-accent[disabled], .md-button.md-accent[disabled],.md-button.md-default-theme.md-fab[disabled], .md-button.md-fab[disabled],.md-button.md-default-theme.md-raised[disabled], .md-button.md-raised[disabled],.md-button.md-default-theme.md-warn[disabled], .md-button.md-warn[disabled],.md-button.md-default-theme[disabled], .md-button[disabled]{color:rgba(0,0,0,0.38);cursor:default}.md-button.md-default-theme.md-accent[disabled] md-icon, .md-button.md-accent[disabled] md-icon,.md-button.md-default-theme.md-fab[disabled] md-icon, .md-button.md-fab[disabled] md-icon,.md-button.md-default-theme.md-raised[disabled] md-icon, .md-button.md-raised[disabled] md-icon,.md-button.md-default-theme.md-warn[disabled] md-icon, .md-button.md-warn[disabled] md-icon,.md-button.md-default-theme[disabled] md-icon, .md-button[disabled] md-icon{color:rgba(0,0,0,0.38)}._md a.md-default-theme:not(.md-button).md-accent, ._md a:not(.md-button).md-accent{color:rgb(21,101,192)}._md a.md-default-theme:not(.md-button).md-accent:hover, ._md a:not(.md-button).md-accent:hover{color:rgb(41,98,255)}md-checkbox.md-default-theme .md-ripple, md-checkbox .md-ripple{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-checked.md-focused .md-container:before, md-checkbox.md-checked.md-focused .md-container:before{background-color:rgba(21,101,192,0.26)}md-checkbox.md-default-theme.md-checked .md-ink-ripple, md-checkbox.md-checked .md-ink-ripple{color:rgba(21,101,192,0.87)}md-checkbox.md-default-theme.md-checked .md-icon, md-checkbox.md-checked .md-icon{background-color:rgba(21,101,192,0.87)}md-checkbox.md-default-theme.md-checked .md-icon:after, md-checkbox.md-checked .md-icon:after{border-color:rgba(255,255,255,0.87)}.md-accent .md-default-theme .md-datepicker-input-container.md-datepicker-focused, .md-accent .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(21,101,192)}.md-accent .md-default-theme .md-datepicker-open .md-datepicker-calendar-icon, .md-accent .md-datepicker-open .md-datepicker-calendar-icon,.md-default-theme .md-datepicker-open.md-accent .md-datepicker-calendar-icon, .md-datepicker-open.md-accent .md-datepicker-calendar-icon{color:rgb(21,101,192)}md-icon.md-default-theme.md-accent, md-icon.md-accent{color:rgb(21,101,192)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-accent .md-input, md-input-container:not(.md-input-invalid).md-input-focused.md-accent .md-input{border-color:rgb(21,101,192)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-accent label, md-input-container:not(.md-input-invalid).md-input-focused.md-accent label,md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-accent md-icon, md-input-container:not(.md-input-invalid).md-input-focused.md-accent md-icon{color:rgb(21,101,192)}md-list.md-default-theme md-list-item>md-icon.md-highlight.md-accent, md-list md-list-item>md-icon.md-highlight.md-accent{color:rgb(21,101,192)}md-nav-bar.md-default-theme md-nav-ink-bar, md-nav-bar md-nav-ink-bar{color:rgb(21,101,192);background:rgb(21,101,192)}md-nav-bar.md-default-theme.md-accent>.md-nav-bar, md-nav-bar.md-accent>.md-nav-bar{background-color:rgb(21,101,192)}md-nav-bar.md-default-theme.md-accent>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-accent>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-nav-bar.md-default-theme.md-accent>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-accent>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-nav-bar.md-default-theme.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-nav-bar.md-default-theme.md-accent>.md-nav-bar md-nav-ink-bar, md-nav-bar.md-accent>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar, md-toolbar.md-accent>md-nav-bar>.md-nav-bar{background-color:rgb(21,101,192)}md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-accent>md-nav-bar>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-accent>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(255,255,255,0.87)}md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-accent>md-nav-bar.md-default-theme>.md-nav-bar md-nav-ink-bar, md-toolbar.md-accent>md-nav-bar>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-progress-circular.md-default-theme.md-accent path, md-progress-circular.md-accent path{stroke:rgb(21,101,192)}md-progress-linear.md-default-theme.md-accent .md-container, md-progress-linear.md-accent .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-accent .md-bar, md-progress-linear.md-accent .md-bar{background-color:rgb(21,101,192)}md-progress-linear.md-default-theme[md-mode=buffer].md-accent .md-bar1, md-progress-linear[md-mode=buffer].md-accent .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme[md-mode=buffer].md-accent .md-dashed:before, md-progress-linear[md-mode=buffer].md-accent .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme .md-on, md-radio-button .md-on{background-color:rgba(21,101,192,0.87)}md-radio-button.md-default-theme.md-checked .md-off, md-radio-button.md-checked .md-off{border-color:rgba(21,101,192,0.87)}md-radio-button.md-default-theme.md-checked .md-ink-ripple, md-radio-button.md-checked .md-ink-ripple{color:rgba(21,101,192,0.87)}md-radio-button.md-default-theme .md-container .md-ripple, md-radio-button .md-container .md-ripple{color:rgb(41,98,255)}md-radio-group.md-default-theme .md-checked .md-ink-ripple, md-radio-group .md-checked .md-ink-ripple{color:rgba(21,101,192,0.26)}md-radio-group.md-default-theme.md-focused:not(:empty) .md-checked .md-container:before, md-radio-group.md-focused:not(:empty) .md-checked .md-container:before{background-color:rgba(21,101,192,0.26)}md-select.md-default-theme:not([disabled]):focus.md-accent .md-select-value, md-select:not([disabled]):focus.md-accent .md-select-value{border-bottom-color:rgb(21,101,192)}md-select-menu.md-default-theme md-content md-option[selected].md-accent, md-select-menu md-content md-option[selected].md-accent{color:rgb(21,101,192)}md-select-menu.md-default-theme md-content md-option[selected].md-accent:focus, md-select-menu md-content md-option[selected].md-accent:focus{color:rgb(41,98,255)}md-slider.md-default-theme .md-focus-ring, md-slider .md-focus-ring{background-color:rgba(68,138,255,0.2)}md-slider.md-default-theme .md-track.md-track-fill, md-slider .md-track.md-track-fill{background-color:rgb(21,101,192)}md-slider.md-default-theme .md-thumb:after, md-slider .md-thumb:after{border-color:rgb(21,101,192);background-color:rgb(21,101,192)}md-slider.md-default-theme .md-sign, md-slider .md-sign{background-color:rgb(21,101,192)}md-slider.md-default-theme .md-sign:after, md-slider .md-sign:after{border-top-color:rgb(21,101,192)}md-slider.md-default-theme[md-vertical] .md-sign:after, md-slider[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(21,101,192)}md-slider.md-default-theme .md-thumb-text, md-slider .md-thumb-text{color:rgba(255,255,255,0.87)}.md-subheader.md-default-theme.md-accent, .md-subheader.md-accent{color:rgb(21,101,192)}md-switch.md-default-theme.md-checked .md-ink-ripple, md-switch.md-checked .md-ink-ripple{color:rgb(21,101,192)}md-switch.md-default-theme.md-checked .md-thumb, md-switch.md-checked .md-thumb{background-color:rgb(21,101,192)}md-switch.md-default-theme.md-checked .md-bar, md-switch.md-checked .md-bar{background-color:rgba(21,101,192,0.5)}md-switch.md-default-theme.md-checked.md-focused .md-thumb:before, md-switch.md-checked.md-focused .md-thumb:before{background-color:rgba(21,101,192,0.26)}md-tabs.md-default-theme md-ink-bar, md-tabs md-ink-bar{color:rgb(21,101,192);background:rgb(21,101,192)}md-tabs.md-default-theme .md-tab .md-ripple-container, md-tabs .md-tab .md-ripple-container{color:rgb(130,177,255)}md-tabs.md-default-theme.md-accent>md-tabs-wrapper, md-tabs.md-accent>md-tabs-wrapper{background-color:rgb(21,101,192)}md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-tabs.md-default-theme.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-tabs.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper, md-toolbar.md-accent>md-tabs>md-tabs-wrapper{background-color:rgb(21,101,192)}md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(255,255,255,0.87)}md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-accent>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-toolbar.md-accent>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toast.md-default-theme .md-toast-content .md-button.md-highlight, md-toast .md-toast-content .md-button.md-highlight{color:rgb(21,101,192)}md-toolbar.md-default-theme:not(.md-menu-toolbar).md-accent, md-toolbar:not(.md-menu-toolbar).md-accent{background-color:rgb(21,101,192);color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme:not(.md-menu-toolbar).md-accent .md-ink-ripple, md-toolbar:not(.md-menu-toolbar).md-accent .md-ink-ripple{color:rgba(255,255,255,0.87)}md-toolbar.md-default-theme:not(.md-menu-toolbar).md-accent md-icon, md-toolbar:not(.md-menu-toolbar).md-accent md-icon{color:rgba(255,255,255,0.87);fill:rgba(255,255,255,0.87)}md-toolbar.md-default-theme:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon, md-toolbar:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon{color:rgba(255,255,255,0.26);fill:rgba(255,255,255,0.26)} -.md-button.md-default-theme.md-hue-1.md-fab md-icon, .md-button.md-hue-1.md-fab md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-fab, .md-button.md-hue-1.md-fab{background-color:rgb(227,242,253);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-fab:not([disabled]) .md-icon, .md-button.md-hue-1.md-fab:not([disabled]) .md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-fab:not([disabled]).md-focused, .md-button.md-hue-1.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-fab:not([disabled]):hover, .md-button.md-hue-1.md-fab:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-1.md-accent, .md-button.md-hue-1.md-accent{color:rgb(227,242,253)}.md-button.md-default-theme.md-hue-1.md-accent.md-fab, .md-button.md-hue-1.md-accent.md-fab,.md-button.md-default-theme.md-hue-1.md-accent.md-raised, .md-button.md-hue-1.md-accent.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(227,242,253)}.md-button.md-default-theme.md-hue-1.md-accent.md-fab:not([disabled]) md-icon, .md-button.md-hue-1.md-accent.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-1.md-accent.md-raised:not([disabled]) md-icon, .md-button.md-hue-1.md-accent.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-accent.md-fab:not([disabled]).md-focused, .md-button.md-hue-1.md-accent.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-accent.md-fab:not([disabled]):hover, .md-button.md-hue-1.md-accent.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-1.md-accent.md-raised:not([disabled]).md-focused, .md-button.md-hue-1.md-accent.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-accent.md-raised:not([disabled]):hover, .md-button.md-hue-1.md-accent.md-raised:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-1.md-accent:not([disabled]) md-icon, .md-button.md-hue-1.md-accent:not([disabled]) md-icon{color:rgb(227,242,253)}.md-button.md-default-theme.md-hue-1.md-accent[disabled], .md-button.md-hue-1.md-accent[disabled],.md-button.md-default-theme.md-hue-1.md-fab[disabled], .md-button.md-hue-1.md-fab[disabled],.md-button.md-default-theme.md-hue-1.md-raised[disabled], .md-button.md-hue-1.md-raised[disabled],.md-button.md-default-theme.md-hue-1.md-warn[disabled], .md-button.md-hue-1.md-warn[disabled],.md-button.md-default-theme.md-hue-1[disabled], .md-button.md-hue-1[disabled]{color:rgba(0,0,0,0.38);cursor:default}.md-button.md-default-theme.md-hue-1.md-accent[disabled] md-icon, .md-button.md-hue-1.md-accent[disabled] md-icon,.md-button.md-default-theme.md-hue-1.md-fab[disabled] md-icon, .md-button.md-hue-1.md-fab[disabled] md-icon,.md-button.md-default-theme.md-hue-1.md-raised[disabled] md-icon, .md-button.md-hue-1.md-raised[disabled] md-icon,.md-button.md-default-theme.md-hue-1.md-warn[disabled] md-icon, .md-button.md-hue-1.md-warn[disabled] md-icon,.md-button.md-default-theme.md-hue-1[disabled] md-icon, .md-button.md-hue-1[disabled] md-icon{color:rgba(0,0,0,0.38)}._md a.md-default-theme.md-hue-1:not(.md-button).md-accent, ._md a.md-hue-1:not(.md-button).md-accent{color:rgb(227,242,253)}._md a.md-default-theme.md-hue-1:not(.md-button).md-accent:hover, ._md a.md-hue-1:not(.md-button).md-accent:hover{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-1 .md-ripple, md-checkbox.md-hue-1 .md-ripple{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-1.md-checked.md-focused .md-container:before, md-checkbox.md-hue-1.md-checked.md-focused .md-container:before{background-color:rgba(227,242,253,0.26)}md-checkbox.md-default-theme.md-hue-1.md-checked .md-ink-ripple, md-checkbox.md-hue-1.md-checked .md-ink-ripple{color:rgba(227,242,253,0.87)}md-checkbox.md-default-theme.md-hue-1.md-checked .md-icon, md-checkbox.md-hue-1.md-checked .md-icon{background-color:rgba(227,242,253,0.87)}md-checkbox.md-default-theme.md-hue-1.md-checked .md-icon:after, md-checkbox.md-hue-1.md-checked .md-icon:after{border-color:rgba(0,0,0,0.87)}.md-accent .md-default-theme.md-hue-1 .md-datepicker-input-container.md-datepicker-focused, .md-accent .md-hue-1 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(227,242,253)}.md-accent .md-default-theme.md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon, .md-accent .md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon,.md-default-theme.md-hue-1 .md-datepicker-open.md-accent .md-datepicker-calendar-icon, .md-hue-1 .md-datepicker-open.md-accent .md-datepicker-calendar-icon{color:rgb(227,242,253)}md-icon.md-default-theme.md-hue-1.md-accent, md-icon.md-hue-1.md-accent{color:rgb(227,242,253)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent .md-input, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent .md-input{border-color:rgb(227,242,253)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent label, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent label,md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent md-icon, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-accent md-icon{color:rgb(227,242,253)}md-list.md-default-theme.md-hue-1 md-list-item>md-icon.md-highlight.md-accent, md-list.md-hue-1 md-list-item>md-icon.md-highlight.md-accent{color:rgb(227,242,253)}md-nav-bar.md-default-theme.md-hue-1 md-nav-ink-bar, md-nav-bar.md-hue-1 md-nav-ink-bar{color:rgb(227,242,253);background:rgb(227,242,253)}md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar, md-nav-bar.md-hue-1.md-accent>.md-nav-bar{background-color:rgb(227,242,253)}md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-nav-bar.md-default-theme.md-hue-1.md-accent>.md-nav-bar md-nav-ink-bar, md-nav-bar.md-hue-1.md-accent>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar{background-color:rgb(227,242,253)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar md-nav-ink-bar, md-toolbar.md-accent>md-nav-bar.md-hue-1>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-progress-circular.md-default-theme.md-hue-1.md-accent path, md-progress-circular.md-hue-1.md-accent path{stroke:rgb(227,242,253)}md-progress-linear.md-default-theme.md-hue-1.md-accent .md-container, md-progress-linear.md-hue-1.md-accent .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-1.md-accent .md-bar, md-progress-linear.md-hue-1.md-accent .md-bar{background-color:rgb(227,242,253)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-accent .md-bar1, md-progress-linear.md-hue-1[md-mode=buffer].md-accent .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-accent .md-dashed:before, md-progress-linear.md-hue-1[md-mode=buffer].md-accent .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-1 .md-on, md-radio-button.md-hue-1 .md-on{background-color:rgba(227,242,253,0.87)}md-radio-button.md-default-theme.md-hue-1.md-checked .md-off, md-radio-button.md-hue-1.md-checked .md-off{border-color:rgba(227,242,253,0.87)}md-radio-button.md-default-theme.md-hue-1.md-checked .md-ink-ripple, md-radio-button.md-hue-1.md-checked .md-ink-ripple{color:rgba(227,242,253,0.87)}md-radio-button.md-default-theme.md-hue-1 .md-container .md-ripple, md-radio-button.md-hue-1 .md-container .md-ripple{color:rgb(41,98,255)}md-radio-group.md-default-theme.md-hue-1 .md-checked .md-ink-ripple, md-radio-group.md-hue-1 .md-checked .md-ink-ripple{color:rgba(227,242,253,0.26)}md-radio-group.md-default-theme.md-hue-1.md-focused:not(:empty) .md-checked .md-container:before, md-radio-group.md-hue-1.md-focused:not(:empty) .md-checked .md-container:before{background-color:rgba(227,242,253,0.26)}md-select.md-default-theme.md-hue-1:not([disabled]):focus.md-accent .md-select-value, md-select.md-hue-1:not([disabled]):focus.md-accent .md-select-value{border-bottom-color:rgb(227,242,253)}md-select-menu.md-default-theme.md-hue-1 md-content md-option[selected].md-accent, md-select-menu.md-hue-1 md-content md-option[selected].md-accent{color:rgb(227,242,253)}md-select-menu.md-default-theme.md-hue-1 md-content md-option[selected].md-accent:focus, md-select-menu.md-hue-1 md-content md-option[selected].md-accent:focus{color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-1 .md-focus-ring, md-slider.md-hue-1 .md-focus-ring{background-color:rgba(68,138,255,0.2)}md-slider.md-default-theme.md-hue-1 .md-track.md-track-fill, md-slider.md-hue-1 .md-track.md-track-fill{background-color:rgb(227,242,253)}md-slider.md-default-theme.md-hue-1 .md-thumb:after, md-slider.md-hue-1 .md-thumb:after{border-color:rgb(227,242,253);background-color:rgb(227,242,253)}md-slider.md-default-theme.md-hue-1 .md-sign, md-slider.md-hue-1 .md-sign{background-color:rgb(227,242,253)}md-slider.md-default-theme.md-hue-1 .md-sign:after, md-slider.md-hue-1 .md-sign:after{border-top-color:rgb(227,242,253)}md-slider.md-default-theme.md-hue-1[md-vertical] .md-sign:after, md-slider.md-hue-1[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(227,242,253)}md-slider.md-default-theme.md-hue-1 .md-thumb-text, md-slider.md-hue-1 .md-thumb-text{color:rgba(0,0,0,0.87)}.md-subheader.md-default-theme.md-hue-1.md-accent, .md-subheader.md-hue-1.md-accent{color:rgb(227,242,253)}md-switch.md-default-theme.md-hue-1.md-checked .md-ink-ripple, md-switch.md-hue-1.md-checked .md-ink-ripple{color:rgb(227,242,253)}md-switch.md-default-theme.md-hue-1.md-checked .md-thumb, md-switch.md-hue-1.md-checked .md-thumb{background-color:rgb(227,242,253)}md-switch.md-default-theme.md-hue-1.md-checked .md-bar, md-switch.md-hue-1.md-checked .md-bar{background-color:rgba(227,242,253,0.5)}md-switch.md-default-theme.md-hue-1.md-checked.md-focused .md-thumb:before, md-switch.md-hue-1.md-checked.md-focused .md-thumb:before{background-color:rgba(227,242,253,0.26)}md-tabs.md-default-theme.md-hue-1 md-ink-bar, md-tabs.md-hue-1 md-ink-bar{color:rgb(227,242,253);background:rgb(227,242,253)}md-tabs.md-default-theme.md-hue-1 .md-tab .md-ripple-container, md-tabs.md-hue-1 .md-tab .md-ripple-container{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper, md-tabs.md-hue-1.md-accent>md-tabs-wrapper{background-color:rgb(227,242,253)}md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-tabs.md-default-theme.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-tabs.md-hue-1.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper{background-color:rgb(227,242,253)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-toolbar.md-accent>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toast.md-default-theme.md-hue-1 .md-toast-content .md-button.md-highlight, md-toast.md-hue-1 .md-toast-content .md-button.md-highlight{color:rgb(227,242,253)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar).md-accent, md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent{background-color:rgb(227,242,253);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar).md-accent .md-ink-ripple, md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent .md-ink-ripple{color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar).md-accent md-icon, md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent md-icon{color:rgba(0,0,0,0.87);fill:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon, md-toolbar.md-hue-1:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon{color:rgba(0,0,0,0.26);fill:rgba(0,0,0,0.26)} -.md-button.md-default-theme.md-hue-2.md-fab md-icon, .md-button.md-hue-2.md-fab md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2.md-fab, .md-button.md-hue-2.md-fab{background-color:rgb(33,150,243);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2.md-fab:not([disabled]) .md-icon, .md-button.md-hue-2.md-fab:not([disabled]) .md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2.md-fab:not([disabled]).md-focused, .md-button.md-hue-2.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-fab:not([disabled]):hover, .md-button.md-hue-2.md-fab:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-2.md-accent, .md-button.md-hue-2.md-accent{color:rgb(33,150,243)}.md-button.md-default-theme.md-hue-2.md-accent.md-fab, .md-button.md-hue-2.md-accent.md-fab,.md-button.md-default-theme.md-hue-2.md-accent.md-raised, .md-button.md-hue-2.md-accent.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(33,150,243)}.md-button.md-default-theme.md-hue-2.md-accent.md-fab:not([disabled]) md-icon, .md-button.md-hue-2.md-accent.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-2.md-accent.md-raised:not([disabled]) md-icon, .md-button.md-hue-2.md-accent.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2.md-accent.md-fab:not([disabled]).md-focused, .md-button.md-hue-2.md-accent.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-accent.md-fab:not([disabled]):hover, .md-button.md-hue-2.md-accent.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-2.md-accent.md-raised:not([disabled]).md-focused, .md-button.md-hue-2.md-accent.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-accent.md-raised:not([disabled]):hover, .md-button.md-hue-2.md-accent.md-raised:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-2.md-accent:not([disabled]) md-icon, .md-button.md-hue-2.md-accent:not([disabled]) md-icon{color:rgb(33,150,243)}.md-button.md-default-theme.md-hue-2.md-accent[disabled], .md-button.md-hue-2.md-accent[disabled],.md-button.md-default-theme.md-hue-2.md-fab[disabled], .md-button.md-hue-2.md-fab[disabled],.md-button.md-default-theme.md-hue-2.md-raised[disabled], .md-button.md-hue-2.md-raised[disabled],.md-button.md-default-theme.md-hue-2.md-warn[disabled], .md-button.md-hue-2.md-warn[disabled],.md-button.md-default-theme.md-hue-2[disabled], .md-button.md-hue-2[disabled]{color:rgba(0,0,0,0.38);cursor:default}.md-button.md-default-theme.md-hue-2.md-accent[disabled] md-icon, .md-button.md-hue-2.md-accent[disabled] md-icon,.md-button.md-default-theme.md-hue-2.md-fab[disabled] md-icon, .md-button.md-hue-2.md-fab[disabled] md-icon,.md-button.md-default-theme.md-hue-2.md-raised[disabled] md-icon, .md-button.md-hue-2.md-raised[disabled] md-icon,.md-button.md-default-theme.md-hue-2.md-warn[disabled] md-icon, .md-button.md-hue-2.md-warn[disabled] md-icon,.md-button.md-default-theme.md-hue-2[disabled] md-icon, .md-button.md-hue-2[disabled] md-icon{color:rgba(0,0,0,0.38)}._md a.md-default-theme.md-hue-2:not(.md-button).md-accent, ._md a.md-hue-2:not(.md-button).md-accent{color:rgb(33,150,243)}._md a.md-default-theme.md-hue-2:not(.md-button).md-accent:hover, ._md a.md-hue-2:not(.md-button).md-accent:hover{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-2 .md-ripple, md-checkbox.md-hue-2 .md-ripple{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-2.md-checked.md-focused .md-container:before, md-checkbox.md-hue-2.md-checked.md-focused .md-container:before{background-color:rgba(33,150,243,0.26)}md-checkbox.md-default-theme.md-hue-2.md-checked .md-ink-ripple, md-checkbox.md-hue-2.md-checked .md-ink-ripple{color:rgba(33,150,243,0.87)}md-checkbox.md-default-theme.md-hue-2.md-checked .md-icon, md-checkbox.md-hue-2.md-checked .md-icon{background-color:rgba(33,150,243,0.87)}md-checkbox.md-default-theme.md-hue-2.md-checked .md-icon:after, md-checkbox.md-hue-2.md-checked .md-icon:after{border-color:rgba(0,0,0,0.87)}.md-accent .md-default-theme.md-hue-2 .md-datepicker-input-container.md-datepicker-focused, .md-accent .md-hue-2 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(33,150,243)}.md-accent .md-default-theme.md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon, .md-accent .md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon,.md-default-theme.md-hue-2 .md-datepicker-open.md-accent .md-datepicker-calendar-icon, .md-hue-2 .md-datepicker-open.md-accent .md-datepicker-calendar-icon{color:rgb(33,150,243)}md-icon.md-default-theme.md-hue-2.md-accent, md-icon.md-hue-2.md-accent{color:rgb(33,150,243)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent .md-input, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent .md-input{border-color:rgb(33,150,243)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent label, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent label,md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent md-icon, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-accent md-icon{color:rgb(33,150,243)}md-list.md-default-theme.md-hue-2 md-list-item>md-icon.md-highlight.md-accent, md-list.md-hue-2 md-list-item>md-icon.md-highlight.md-accent{color:rgb(33,150,243)}md-nav-bar.md-default-theme.md-hue-2 md-nav-ink-bar, md-nav-bar.md-hue-2 md-nav-ink-bar{color:rgb(33,150,243);background:rgb(33,150,243)}md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar, md-nav-bar.md-hue-2.md-accent>.md-nav-bar{background-color:rgb(33,150,243)}md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-nav-bar.md-default-theme.md-hue-2.md-accent>.md-nav-bar md-nav-ink-bar, md-nav-bar.md-hue-2.md-accent>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar{background-color:rgb(33,150,243)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar md-nav-ink-bar, md-toolbar.md-accent>md-nav-bar.md-hue-2>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-progress-circular.md-default-theme.md-hue-2.md-accent path, md-progress-circular.md-hue-2.md-accent path{stroke:rgb(33,150,243)}md-progress-linear.md-default-theme.md-hue-2.md-accent .md-container, md-progress-linear.md-hue-2.md-accent .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-2.md-accent .md-bar, md-progress-linear.md-hue-2.md-accent .md-bar{background-color:rgb(33,150,243)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-accent .md-bar1, md-progress-linear.md-hue-2[md-mode=buffer].md-accent .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-accent .md-dashed:before, md-progress-linear.md-hue-2[md-mode=buffer].md-accent .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-2 .md-on, md-radio-button.md-hue-2 .md-on{background-color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-2.md-checked .md-off, md-radio-button.md-hue-2.md-checked .md-off{border-color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-2.md-checked .md-ink-ripple, md-radio-button.md-hue-2.md-checked .md-ink-ripple{color:rgba(33,150,243,0.87)}md-radio-button.md-default-theme.md-hue-2 .md-container .md-ripple, md-radio-button.md-hue-2 .md-container .md-ripple{color:rgb(41,98,255)}md-radio-group.md-default-theme.md-hue-2 .md-checked .md-ink-ripple, md-radio-group.md-hue-2 .md-checked .md-ink-ripple{color:rgba(33,150,243,0.26)}md-radio-group.md-default-theme.md-hue-2.md-focused:not(:empty) .md-checked .md-container:before, md-radio-group.md-hue-2.md-focused:not(:empty) .md-checked .md-container:before{background-color:rgba(33,150,243,0.26)}md-select.md-default-theme.md-hue-2:not([disabled]):focus.md-accent .md-select-value, md-select.md-hue-2:not([disabled]):focus.md-accent .md-select-value{border-bottom-color:rgb(33,150,243)}md-select-menu.md-default-theme.md-hue-2 md-content md-option[selected].md-accent, md-select-menu.md-hue-2 md-content md-option[selected].md-accent{color:rgb(33,150,243)}md-select-menu.md-default-theme.md-hue-2 md-content md-option[selected].md-accent:focus, md-select-menu.md-hue-2 md-content md-option[selected].md-accent:focus{color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-2 .md-focus-ring, md-slider.md-hue-2 .md-focus-ring{background-color:rgba(68,138,255,0.2)}md-slider.md-default-theme.md-hue-2 .md-track.md-track-fill, md-slider.md-hue-2 .md-track.md-track-fill{background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-2 .md-thumb:after, md-slider.md-hue-2 .md-thumb:after{border-color:rgb(33,150,243);background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-2 .md-sign, md-slider.md-hue-2 .md-sign{background-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-2 .md-sign:after, md-slider.md-hue-2 .md-sign:after{border-top-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-2[md-vertical] .md-sign:after, md-slider.md-hue-2[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(33,150,243)}md-slider.md-default-theme.md-hue-2 .md-thumb-text, md-slider.md-hue-2 .md-thumb-text{color:rgba(0,0,0,0.87)}.md-subheader.md-default-theme.md-hue-2.md-accent, .md-subheader.md-hue-2.md-accent{color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-2.md-checked .md-ink-ripple, md-switch.md-hue-2.md-checked .md-ink-ripple{color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-2.md-checked .md-thumb, md-switch.md-hue-2.md-checked .md-thumb{background-color:rgb(33,150,243)}md-switch.md-default-theme.md-hue-2.md-checked .md-bar, md-switch.md-hue-2.md-checked .md-bar{background-color:rgba(33,150,243,0.5)}md-switch.md-default-theme.md-hue-2.md-checked.md-focused .md-thumb:before, md-switch.md-hue-2.md-checked.md-focused .md-thumb:before{background-color:rgba(33,150,243,0.26)}md-tabs.md-default-theme.md-hue-2 md-ink-bar, md-tabs.md-hue-2 md-ink-bar{color:rgb(33,150,243);background:rgb(33,150,243)}md-tabs.md-default-theme.md-hue-2 .md-tab .md-ripple-container, md-tabs.md-hue-2 .md-tab .md-ripple-container{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper, md-tabs.md-hue-2.md-accent>md-tabs-wrapper{background-color:rgb(33,150,243)}md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-tabs.md-default-theme.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-tabs.md-hue-2.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper{background-color:rgb(33,150,243)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-toolbar.md-accent>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toast.md-default-theme.md-hue-2 .md-toast-content .md-button.md-highlight, md-toast.md-hue-2 .md-toast-content .md-button.md-highlight{color:rgb(33,150,243)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar).md-accent, md-toolbar.md-hue-2:not(.md-menu-toolbar).md-accent{background-color:rgb(33,150,243);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar).md-accent .md-ink-ripple, md-toolbar.md-hue-2:not(.md-menu-toolbar).md-accent .md-ink-ripple{color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar).md-accent md-icon, md-toolbar.md-hue-2:not(.md-menu-toolbar).md-accent md-icon{color:rgba(0,0,0,0.87);fill:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon, md-toolbar.md-hue-2:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon{color:rgba(0,0,0,0.26);fill:rgba(0,0,0,0.26)} -.md-button.md-default-theme.md-hue-3.md-fab md-icon, .md-button.md-hue-3.md-fab md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-fab, .md-button.md-hue-3.md-fab{background-color:rgb(41,98,255);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-fab:not([disabled]) .md-icon, .md-button.md-hue-3.md-fab:not([disabled]) .md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-fab:not([disabled]).md-focused, .md-button.md-hue-3.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-fab:not([disabled]):hover, .md-button.md-hue-3.md-fab:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-3.md-accent, .md-button.md-hue-3.md-accent{color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-3.md-accent.md-fab, .md-button.md-hue-3.md-accent.md-fab,.md-button.md-default-theme.md-hue-3.md-accent.md-raised, .md-button.md-hue-3.md-accent.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-3.md-accent.md-fab:not([disabled]) md-icon, .md-button.md-hue-3.md-accent.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-3.md-accent.md-raised:not([disabled]) md-icon, .md-button.md-hue-3.md-accent.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-accent.md-fab:not([disabled]).md-focused, .md-button.md-hue-3.md-accent.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-accent.md-fab:not([disabled]):hover, .md-button.md-hue-3.md-accent.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-3.md-accent.md-raised:not([disabled]).md-focused, .md-button.md-hue-3.md-accent.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-accent.md-raised:not([disabled]):hover, .md-button.md-hue-3.md-accent.md-raised:not([disabled]):hover{background-color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-3.md-accent:not([disabled]) md-icon, .md-button.md-hue-3.md-accent:not([disabled]) md-icon{color:rgb(41,98,255)}.md-button.md-default-theme.md-hue-3.md-accent[disabled], .md-button.md-hue-3.md-accent[disabled],.md-button.md-default-theme.md-hue-3.md-fab[disabled], .md-button.md-hue-3.md-fab[disabled],.md-button.md-default-theme.md-hue-3.md-raised[disabled], .md-button.md-hue-3.md-raised[disabled],.md-button.md-default-theme.md-hue-3.md-warn[disabled], .md-button.md-hue-3.md-warn[disabled],.md-button.md-default-theme.md-hue-3[disabled], .md-button.md-hue-3[disabled]{color:rgba(0,0,0,0.38);cursor:default}.md-button.md-default-theme.md-hue-3.md-accent[disabled] md-icon, .md-button.md-hue-3.md-accent[disabled] md-icon,.md-button.md-default-theme.md-hue-3.md-fab[disabled] md-icon, .md-button.md-hue-3.md-fab[disabled] md-icon,.md-button.md-default-theme.md-hue-3.md-raised[disabled] md-icon, .md-button.md-hue-3.md-raised[disabled] md-icon,.md-button.md-default-theme.md-hue-3.md-warn[disabled] md-icon, .md-button.md-hue-3.md-warn[disabled] md-icon,.md-button.md-default-theme.md-hue-3[disabled] md-icon, .md-button.md-hue-3[disabled] md-icon{color:rgba(0,0,0,0.38)}._md a.md-default-theme.md-hue-3:not(.md-button).md-accent, ._md a.md-hue-3:not(.md-button).md-accent{color:rgb(41,98,255)}._md a.md-default-theme.md-hue-3:not(.md-button).md-accent:hover, ._md a.md-hue-3:not(.md-button).md-accent:hover{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-3 .md-ripple, md-checkbox.md-hue-3 .md-ripple{color:rgb(41,98,255)}md-checkbox.md-default-theme.md-hue-3.md-checked.md-focused .md-container:before, md-checkbox.md-hue-3.md-checked.md-focused .md-container:before{background-color:rgba(41,98,255,0.26)}md-checkbox.md-default-theme.md-hue-3.md-checked .md-ink-ripple, md-checkbox.md-hue-3.md-checked .md-ink-ripple{color:rgba(41,98,255,0.87)}md-checkbox.md-default-theme.md-hue-3.md-checked .md-icon, md-checkbox.md-hue-3.md-checked .md-icon{background-color:rgba(41,98,255,0.87)}md-checkbox.md-default-theme.md-hue-3.md-checked .md-icon:after, md-checkbox.md-hue-3.md-checked .md-icon:after{border-color:rgba(0,0,0,0.87)}.md-accent .md-default-theme.md-hue-3 .md-datepicker-input-container.md-datepicker-focused, .md-accent .md-hue-3 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(41,98,255)}.md-accent .md-default-theme.md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon, .md-accent .md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon,.md-default-theme.md-hue-3 .md-datepicker-open.md-accent .md-datepicker-calendar-icon, .md-hue-3 .md-datepicker-open.md-accent .md-datepicker-calendar-icon{color:rgb(41,98,255)}md-icon.md-default-theme.md-hue-3.md-accent, md-icon.md-hue-3.md-accent{color:rgb(41,98,255)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent .md-input, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent .md-input{border-color:rgb(41,98,255)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent label, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent label,md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent md-icon, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-accent md-icon{color:rgb(41,98,255)}md-list.md-default-theme.md-hue-3 md-list-item>md-icon.md-highlight.md-accent, md-list.md-hue-3 md-list-item>md-icon.md-highlight.md-accent{color:rgb(41,98,255)}md-nav-bar.md-default-theme.md-hue-3 md-nav-ink-bar, md-nav-bar.md-hue-3 md-nav-ink-bar{color:rgb(41,98,255);background:rgb(41,98,255)}md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar, md-nav-bar.md-hue-3.md-accent>.md-nav-bar{background-color:rgb(41,98,255)}md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-accent>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-nav-bar.md-default-theme.md-hue-3.md-accent>.md-nav-bar md-nav-ink-bar, md-nav-bar.md-hue-3.md-accent>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar{background-color:rgb(41,98,255)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button{color:rgb(130,177,255)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar md-nav-ink-bar, md-toolbar.md-accent>md-nav-bar.md-hue-3>.md-nav-bar md-nav-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-progress-circular.md-default-theme.md-hue-3.md-accent path, md-progress-circular.md-hue-3.md-accent path{stroke:rgb(41,98,255)}md-progress-linear.md-default-theme.md-hue-3.md-accent .md-container, md-progress-linear.md-hue-3.md-accent .md-container{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-3.md-accent .md-bar, md-progress-linear.md-hue-3.md-accent .md-bar{background-color:rgb(41,98,255)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-accent .md-bar1, md-progress-linear.md-hue-3[md-mode=buffer].md-accent .md-bar1{background-color:rgb(187,222,251)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-accent .md-dashed:before, md-progress-linear.md-hue-3[md-mode=buffer].md-accent .md-dashed:before{background:radial-gradient(rgb(187,222,251) 0,rgb(187,222,251) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-3 .md-on, md-radio-button.md-hue-3 .md-on{background-color:rgba(41,98,255,0.87)}md-radio-button.md-default-theme.md-hue-3.md-checked .md-off, md-radio-button.md-hue-3.md-checked .md-off{border-color:rgba(41,98,255,0.87)}md-radio-button.md-default-theme.md-hue-3.md-checked .md-ink-ripple, md-radio-button.md-hue-3.md-checked .md-ink-ripple{color:rgba(41,98,255,0.87)}md-radio-button.md-default-theme.md-hue-3 .md-container .md-ripple, md-radio-button.md-hue-3 .md-container .md-ripple{color:rgb(41,98,255)}md-radio-group.md-default-theme.md-hue-3 .md-checked .md-ink-ripple, md-radio-group.md-hue-3 .md-checked .md-ink-ripple{color:rgba(41,98,255,0.26)}md-radio-group.md-default-theme.md-hue-3.md-focused:not(:empty) .md-checked .md-container:before, md-radio-group.md-hue-3.md-focused:not(:empty) .md-checked .md-container:before{background-color:rgba(41,98,255,0.26)}md-select.md-default-theme.md-hue-3:not([disabled]):focus.md-accent .md-select-value, md-select.md-hue-3:not([disabled]):focus.md-accent .md-select-value{border-bottom-color:rgb(41,98,255)}md-select-menu.md-default-theme.md-hue-3 md-content md-option[selected].md-accent, md-select-menu.md-hue-3 md-content md-option[selected].md-accent{color:rgb(41,98,255)}md-select-menu.md-default-theme.md-hue-3 md-content md-option[selected].md-accent:focus, md-select-menu.md-hue-3 md-content md-option[selected].md-accent:focus{color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3 .md-focus-ring, md-slider.md-hue-3 .md-focus-ring{background-color:rgba(68,138,255,0.2)}md-slider.md-default-theme.md-hue-3 .md-track.md-track-fill, md-slider.md-hue-3 .md-track.md-track-fill{background-color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3 .md-thumb:after, md-slider.md-hue-3 .md-thumb:after{border-color:rgb(41,98,255);background-color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3 .md-sign, md-slider.md-hue-3 .md-sign{background-color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3 .md-sign:after, md-slider.md-hue-3 .md-sign:after{border-top-color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3[md-vertical] .md-sign:after, md-slider.md-hue-3[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(41,98,255)}md-slider.md-default-theme.md-hue-3 .md-thumb-text, md-slider.md-hue-3 .md-thumb-text{color:rgba(0,0,0,0.87)}.md-subheader.md-default-theme.md-hue-3.md-accent, .md-subheader.md-hue-3.md-accent{color:rgb(41,98,255)}md-switch.md-default-theme.md-hue-3.md-checked .md-ink-ripple, md-switch.md-hue-3.md-checked .md-ink-ripple{color:rgb(41,98,255)}md-switch.md-default-theme.md-hue-3.md-checked .md-thumb, md-switch.md-hue-3.md-checked .md-thumb{background-color:rgb(41,98,255)}md-switch.md-default-theme.md-hue-3.md-checked .md-bar, md-switch.md-hue-3.md-checked .md-bar{background-color:rgba(41,98,255,0.5)}md-switch.md-default-theme.md-hue-3.md-checked.md-focused .md-thumb:before, md-switch.md-hue-3.md-checked.md-focused .md-thumb:before{background-color:rgba(41,98,255,0.26)}md-tabs.md-default-theme.md-hue-3 md-ink-bar, md-tabs.md-hue-3 md-ink-bar{color:rgb(41,98,255);background:rgb(41,98,255)}md-tabs.md-default-theme.md-hue-3 .md-tab .md-ripple-container, md-tabs.md-hue-3 .md-tab .md-ripple-container{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper, md-tabs.md-hue-3.md-accent>md-tabs-wrapper{background-color:rgb(41,98,255)}md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-tabs.md-default-theme.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-tabs.md-hue-3.md-accent>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper{background-color:rgb(41,98,255)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(130,177,255)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-accent>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar, md-toolbar.md-accent>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-ink-bar{color:rgba(30,136,229,1);background:rgba(30,136,229,1)}md-toast.md-default-theme.md-hue-3 .md-toast-content .md-button.md-highlight, md-toast.md-hue-3 .md-toast-content .md-button.md-highlight{color:rgb(41,98,255)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar).md-accent, md-toolbar.md-hue-3:not(.md-menu-toolbar).md-accent{background-color:rgb(41,98,255);color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar).md-accent .md-ink-ripple, md-toolbar.md-hue-3:not(.md-menu-toolbar).md-accent .md-ink-ripple{color:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar).md-accent md-icon, md-toolbar.md-hue-3:not(.md-menu-toolbar).md-accent md-icon{color:rgba(0,0,0,0.87);fill:rgba(0,0,0,0.87)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon, md-toolbar.md-hue-3:not(.md-menu-toolbar).md-accent .md-button[disabled] md-icon{color:rgba(0,0,0,0.26);fill:rgba(0,0,0,0.26)} -.md-button.md-default-theme.md-warn, .md-button.md-warn{color:rgb(255,87,34)}.md-button.md-default-theme.md-warn.md-fab, .md-button.md-warn.md-fab,.md-button.md-default-theme.md-warn.md-raised, .md-button.md-warn.md-raised{color:rgb(255,255,255);background-color:rgb(255,87,34)}.md-button.md-default-theme.md-warn.md-fab:not([disabled]) md-icon, .md-button.md-warn.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-warn.md-raised:not([disabled]) md-icon, .md-button.md-warn.md-raised:not([disabled]) md-icon{color:rgb(255,255,255)}.md-button.md-default-theme.md-warn.md-fab:not([disabled]).md-focused, .md-button.md-warn.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-warn.md-fab:not([disabled]):hover, .md-button.md-warn.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-warn.md-raised:not([disabled]).md-focused, .md-button.md-warn.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-warn.md-raised:not([disabled]):hover, .md-button.md-warn.md-raised:not([disabled]):hover{background-color:rgb(244,81,30)}.md-button.md-default-theme.md-warn:not([disabled]) md-icon, .md-button.md-warn:not([disabled]) md-icon{color:rgb(255,87,34)}._md a.md-default-theme:not(.md-button).md-warn, ._md a:not(.md-button).md-warn{color:rgb(255,87,34)}._md a.md-default-theme:not(.md-button).md-warn:hover, ._md a:not(.md-button).md-warn:hover{color:rgb(230,74,25)}md-checkbox.md-default-theme:not([disabled]).md-warn .md-ripple, md-checkbox:not([disabled]).md-warn .md-ripple{color:rgb(244,81,30)}md-checkbox.md-default-theme:not([disabled]).md-warn .md-ink-ripple, md-checkbox:not([disabled]).md-warn .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not([disabled]).md-warn.md-checked .md-ink-ripple, md-checkbox:not([disabled]).md-warn.md-checked .md-ink-ripple{color:rgba(255,87,34,0.87)}md-checkbox.md-default-theme:not([disabled]).md-warn:not(.md-checked) .md-icon, md-checkbox:not([disabled]).md-warn:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme:not([disabled]).md-warn.md-checked .md-icon, md-checkbox:not([disabled]).md-warn.md-checked .md-icon{background-color:rgba(255,87,34,0.87)}md-checkbox.md-default-theme:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before, md-checkbox:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before{background-color:rgba(255,87,34,0.26)}md-checkbox.md-default-theme:not([disabled]).md-warn.md-checked .md-icon:after, md-checkbox:not([disabled]).md-warn.md-checked .md-icon:after{border-color:rgb(238,238,238)}.md-default-theme .md-datepicker-input-container.md-datepicker-invalid, .md-datepicker-input-container.md-datepicker-invalid,.md-warn .md-default-theme .md-datepicker-input-container.md-datepicker-focused, .md-warn .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(221,44,0)}.md-default-theme .md-datepicker-open.md-warn .md-datepicker-calendar-icon, .md-datepicker-open.md-warn .md-datepicker-calendar-icon,.md-warn .md-default-theme .md-datepicker-open .md-datepicker-calendar-icon, .md-warn .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(221,44,0)}md-icon.md-default-theme.md-warn, md-icon.md-warn{color:rgb(255,87,34)}md-input-container.md-default-theme label.md-required:after, md-input-container label.md-required:after{color:rgb(221,44,0)}md-input-container.md-default-theme .md-input-message-animation, md-input-container .md-input-message-animation,md-input-container.md-default-theme .md-input-messages-animation, md-input-container .md-input-messages-animation{color:rgb(221,44,0)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-warn .md-input, md-input-container:not(.md-input-invalid).md-input-focused.md-warn .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-warn label, md-input-container:not(.md-input-invalid).md-input-focused.md-warn label,md-input-container.md-default-theme:not(.md-input-invalid).md-input-focused.md-warn md-icon, md-input-container:not(.md-input-invalid).md-input-focused.md-warn md-icon{color:rgb(221,44,0)}md-input-container.md-default-theme.md-input-invalid .md-input, md-input-container.md-input-invalid .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-input-invalid .md-char-counter, md-input-container.md-input-invalid .md-char-counter,md-input-container.md-default-theme.md-input-invalid .md-input-message-animation, md-input-container.md-input-invalid .md-input-message-animation,md-input-container.md-default-theme.md-input-invalid label, md-input-container.md-input-invalid label{color:rgb(221,44,0)}md-nav-bar.md-default-theme.md-warn>.md-nav-bar, md-nav-bar.md-warn>.md-nav-bar{background-color:rgb(255,87,34)}md-nav-bar.md-default-theme.md-warn>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-warn>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-nav-bar.md-default-theme.md-warn>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-warn>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgb(255,255,255)}md-nav-bar.md-default-theme.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-warn>md-nav-bar.md-default-theme>.md-nav-bar, md-toolbar.md-warn>md-nav-bar>.md-nav-bar{background-color:rgb(255,87,34)}md-toolbar.md-warn>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-warn>md-nav-bar>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-toolbar.md-warn>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-warn>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-warn>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgb(255,255,255)}md-toolbar.md-warn>md-nav-bar.md-default-theme>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-progress-circular.md-default-theme.md-warn path, md-progress-circular.md-warn path{stroke:rgb(255,87,34)}md-progress-linear.md-default-theme.md-warn .md-container, md-progress-linear.md-warn .md-container{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-warn .md-bar, md-progress-linear.md-warn .md-bar{background-color:rgb(255,87,34)}md-progress-linear.md-default-theme[md-mode=buffer].md-warn .md-bar1, md-progress-linear[md-mode=buffer].md-warn .md-bar1{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme[md-mode=buffer].md-warn .md-dashed:before, md-progress-linear[md-mode=buffer].md-warn .md-dashed:before{background:radial-gradient(rgb(255,204,188) 0,rgb(255,204,188) 16%,transparent 42%)}md-radio-button.md-default-theme:not([disabled]).md-warn .md-on, md-radio-button:not([disabled]).md-warn .md-on,md-radio-button.md-default-theme:not([disabled]) .md-warn .md-on, md-radio-button:not([disabled]) .md-warn .md-on,md-radio-group.md-default-theme:not([disabled]).md-warn .md-on, md-radio-group:not([disabled]).md-warn .md-on,md-radio-group.md-default-theme:not([disabled]) .md-warn .md-on, md-radio-group:not([disabled]) .md-warn .md-on{background-color:rgba(255,87,34,0.87)}md-radio-button.md-default-theme:not([disabled]).md-warn.md-checked .md-off, md-radio-button:not([disabled]).md-warn.md-checked .md-off,md-radio-button.md-default-theme:not([disabled]) .md-warn.md-checked .md-off, md-radio-button:not([disabled]) .md-warn.md-checked .md-off,md-radio-button.md-default-theme:not([disabled]).md-warn .md-checked .md-off, md-radio-button:not([disabled]).md-warn .md-checked .md-off,md-radio-button.md-default-theme:not([disabled]) .md-warn .md-checked .md-off, md-radio-button:not([disabled]) .md-warn .md-checked .md-off,md-radio-group.md-default-theme:not([disabled]).md-warn.md-checked .md-off, md-radio-group:not([disabled]).md-warn.md-checked .md-off,md-radio-group.md-default-theme:not([disabled]) .md-warn.md-checked .md-off, md-radio-group:not([disabled]) .md-warn.md-checked .md-off,md-radio-group.md-default-theme:not([disabled]).md-warn .md-checked .md-off, md-radio-group:not([disabled]).md-warn .md-checked .md-off,md-radio-group.md-default-theme:not([disabled]) .md-warn .md-checked .md-off, md-radio-group:not([disabled]) .md-warn .md-checked .md-off{border-color:rgba(255,87,34,0.87)}md-radio-button.md-default-theme:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-button:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-button:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-button:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-button.md-default-theme:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-button:not([disabled]) .md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-group:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-group:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-group:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-group:not([disabled]) .md-warn .md-checked .md-ink-ripple{color:rgba(255,87,34,0.87)}md-radio-button.md-default-theme:not([disabled]).md-warn .md-container .md-ripple, md-radio-button:not([disabled]).md-warn .md-container .md-ripple,md-radio-button.md-default-theme:not([disabled]) .md-warn .md-container .md-ripple, md-radio-button:not([disabled]) .md-warn .md-container .md-ripple,md-radio-group.md-default-theme:not([disabled]).md-warn .md-container .md-ripple, md-radio-group:not([disabled]).md-warn .md-container .md-ripple,md-radio-group.md-default-theme:not([disabled]) .md-warn .md-container .md-ripple, md-radio-group:not([disabled]) .md-warn .md-container .md-ripple{color:rgb(244,81,30)}md-radio-group.md-default-theme.md-focused:not(:empty) .md-checked.md-warn .md-container:before, md-radio-group.md-focused:not(:empty) .md-checked.md-warn .md-container:before,md-radio-group.md-default-theme.md-focused:not(:empty).md-warn .md-checked .md-container:before, md-radio-group.md-focused:not(:empty).md-warn .md-checked .md-container:before{background-color:rgba(255,87,34,0.26)}md-input-container md-select.md-default-theme .md-select-value span:first-child:after, md-input-container md-select .md-select-value span:first-child:after{color:rgb(221,44,0)}md-input-container.md-input-invalid md-select.md-default-theme .md-select-value, md-input-container.md-input-invalid md-select .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme .md-select-value span:first-child:after, md-select .md-select-value span:first-child:after{color:rgb(221,44,0)}md-select.md-default-theme.ng-invalid.ng-touched .md-select-value, md-select.ng-invalid.ng-touched .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme:not([disabled]):focus.md-warn .md-select-value, md-select:not([disabled]):focus.md-warn .md-select-value{border-bottom-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn .md-focus-ring, md-slider.md-warn .md-focus-ring{background-color:rgba(255,171,145,0.38)}md-slider.md-default-theme.md-warn .md-track.md-track-fill, md-slider.md-warn .md-track.md-track-fill{background-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn .md-thumb:after, md-slider.md-warn .md-thumb:after{border-color:rgb(255,87,34);background-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn .md-sign, md-slider.md-warn .md-sign{background-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn .md-sign:after, md-slider.md-warn .md-sign:after{border-top-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn[md-vertical] .md-sign:after, md-slider.md-warn[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(255,87,34)}md-slider.md-default-theme.md-warn .md-thumb-text, md-slider.md-warn .md-thumb-text{color:rgb(255,255,255)}.md-subheader.md-default-theme.md-warn, .md-subheader.md-warn{color:rgb(255,87,34)}md-switch.md-default-theme.md-checked.md-warn .md-ink-ripple, md-switch.md-checked.md-warn .md-ink-ripple{color:rgb(255,87,34)}md-switch.md-default-theme.md-checked.md-warn .md-thumb, md-switch.md-checked.md-warn .md-thumb{background-color:rgb(255,87,34)}md-switch.md-default-theme.md-checked.md-warn .md-bar, md-switch.md-checked.md-warn .md-bar{background-color:rgba(255,87,34,0.5)}md-switch.md-default-theme.md-checked.md-warn.md-focused .md-thumb:before, md-switch.md-checked.md-warn.md-focused .md-thumb:before{background-color:rgba(255,87,34,0.26)}md-tabs.md-default-theme.md-warn>md-tabs-wrapper, md-tabs.md-warn>md-tabs-wrapper{background-color:rgb(255,87,34)}md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgb(255,255,255)}md-tabs.md-default-theme.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper, md-toolbar.md-warn>md-tabs>md-tabs-wrapper{background-color:rgb(255,87,34)}md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgb(255,255,255)}md-toolbar.md-warn>md-tabs.md-default-theme>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toast.md-default-theme .md-toast-content .md-button.md-highlight.md-warn, md-toast .md-toast-content .md-button.md-highlight.md-warn{color:rgb(255,87,34)}md-toolbar.md-default-theme:not(.md-menu-toolbar).md-warn, md-toolbar:not(.md-menu-toolbar).md-warn{background-color:rgb(255,87,34);color:rgb(255,255,255)} -.md-button.md-default-theme.md-hue-1.md-warn, .md-button.md-hue-1.md-warn{color:rgb(255,138,101)}.md-button.md-default-theme.md-hue-1.md-warn.md-fab, .md-button.md-hue-1.md-warn.md-fab,.md-button.md-default-theme.md-hue-1.md-warn.md-raised, .md-button.md-hue-1.md-warn.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(255,138,101)}.md-button.md-default-theme.md-hue-1.md-warn.md-fab:not([disabled]) md-icon, .md-button.md-hue-1.md-warn.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-1.md-warn.md-raised:not([disabled]) md-icon, .md-button.md-hue-1.md-warn.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1.md-warn.md-fab:not([disabled]).md-focused, .md-button.md-hue-1.md-warn.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-warn.md-fab:not([disabled]):hover, .md-button.md-hue-1.md-warn.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-1.md-warn.md-raised:not([disabled]).md-focused, .md-button.md-hue-1.md-warn.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1.md-warn.md-raised:not([disabled]):hover, .md-button.md-hue-1.md-warn.md-raised:not([disabled]):hover{background-color:rgb(244,81,30)}.md-button.md-default-theme.md-hue-1.md-warn:not([disabled]) md-icon, .md-button.md-hue-1.md-warn:not([disabled]) md-icon{color:rgb(255,138,101)}._md a.md-default-theme.md-hue-1:not(.md-button).md-warn, ._md a.md-hue-1:not(.md-button).md-warn{color:rgb(255,138,101)}._md a.md-default-theme.md-hue-1:not(.md-button).md-warn:hover, ._md a.md-hue-1:not(.md-button).md-warn:hover{color:rgb(230,74,25)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn .md-ripple, md-checkbox.md-hue-1:not([disabled]).md-warn .md-ripple{color:rgb(244,81,30)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn .md-ink-ripple, md-checkbox.md-hue-1:not([disabled]).md-warn .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple, md-checkbox.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple{color:rgba(255,138,101,0.87)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn:not(.md-checked) .md-icon, md-checkbox.md-hue-1:not([disabled]).md-warn:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-icon, md-checkbox.md-hue-1:not([disabled]).md-warn.md-checked .md-icon{background-color:rgba(255,138,101,0.87)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before, md-checkbox.md-hue-1:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before{background-color:rgba(255,138,101,0.26)}md-checkbox.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-icon:after, md-checkbox.md-hue-1:not([disabled]).md-warn.md-checked .md-icon:after{border-color:rgb(238,238,238)}.md-default-theme.md-hue-1 .md-datepicker-input-container.md-datepicker-invalid, .md-hue-1 .md-datepicker-input-container.md-datepicker-invalid,.md-warn .md-default-theme.md-hue-1 .md-datepicker-input-container.md-datepicker-focused, .md-warn .md-hue-1 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(221,44,0)}.md-default-theme.md-hue-1 .md-datepicker-open.md-warn .md-datepicker-calendar-icon, .md-hue-1 .md-datepicker-open.md-warn .md-datepicker-calendar-icon,.md-warn .md-default-theme.md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon, .md-warn .md-hue-1 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(221,44,0)}md-icon.md-default-theme.md-hue-1.md-warn, md-icon.md-hue-1.md-warn{color:rgb(255,138,101)}md-input-container.md-default-theme.md-hue-1 label.md-required:after, md-input-container.md-hue-1 label.md-required:after{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-1 .md-input-message-animation, md-input-container.md-hue-1 .md-input-message-animation,md-input-container.md-default-theme.md-hue-1 .md-input-messages-animation, md-input-container.md-hue-1 .md-input-messages-animation{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn .md-input, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn label, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn label,md-input-container.md-default-theme.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn md-icon, md-input-container.md-hue-1:not(.md-input-invalid).md-input-focused.md-warn md-icon{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-1.md-input-invalid .md-input, md-input-container.md-hue-1.md-input-invalid .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-1.md-input-invalid .md-char-counter, md-input-container.md-hue-1.md-input-invalid .md-char-counter,md-input-container.md-default-theme.md-hue-1.md-input-invalid .md-input-message-animation, md-input-container.md-hue-1.md-input-invalid .md-input-message-animation,md-input-container.md-default-theme.md-hue-1.md-input-invalid label, md-input-container.md-hue-1.md-input-invalid label{color:rgb(221,44,0)}md-nav-bar.md-default-theme.md-hue-1.md-warn>.md-nav-bar, md-nav-bar.md-hue-1.md-warn>.md-nav-bar{background-color:rgb(255,138,101)}md-nav-bar.md-default-theme.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-nav-bar.md-default-theme.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-1.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar, md-toolbar.md-warn>md-nav-bar.md-hue-1>.md-nav-bar{background-color:rgb(255,138,101)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-warn>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-warn>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-1>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-progress-circular.md-default-theme.md-hue-1.md-warn path, md-progress-circular.md-hue-1.md-warn path{stroke:rgb(255,138,101)}md-progress-linear.md-default-theme.md-hue-1.md-warn .md-container, md-progress-linear.md-hue-1.md-warn .md-container{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-1.md-warn .md-bar, md-progress-linear.md-hue-1.md-warn .md-bar{background-color:rgb(255,138,101)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-warn .md-bar1, md-progress-linear.md-hue-1[md-mode=buffer].md-warn .md-bar1{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-1[md-mode=buffer].md-warn .md-dashed:before, md-progress-linear.md-hue-1[md-mode=buffer].md-warn .md-dashed:before{background:radial-gradient(rgb(255,204,188) 0,rgb(255,204,188) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn .md-on, md-radio-button.md-hue-1:not([disabled]).md-warn .md-on,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-on, md-radio-button.md-hue-1:not([disabled]) .md-warn .md-on,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn .md-on, md-radio-group.md-hue-1:not([disabled]).md-warn .md-on,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-on, md-radio-group.md-hue-1:not([disabled]) .md-warn .md-on{background-color:rgba(255,138,101,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-off, md-radio-button.md-hue-1:not([disabled]).md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn.md-checked .md-off, md-radio-button.md-hue-1:not([disabled]) .md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn .md-checked .md-off, md-radio-button.md-hue-1:not([disabled]).md-warn .md-checked .md-off,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-checked .md-off, md-radio-button.md-hue-1:not([disabled]) .md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-off, md-radio-group.md-hue-1:not([disabled]).md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn.md-checked .md-off, md-radio-group.md-hue-1:not([disabled]) .md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn .md-checked .md-off, md-radio-group.md-hue-1:not([disabled]).md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-checked .md-off, md-radio-group.md-hue-1:not([disabled]) .md-warn .md-checked .md-off{border-color:rgba(255,138,101,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-1:not([disabled]) .md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-1:not([disabled]) .md-warn .md-checked .md-ink-ripple{color:rgba(255,138,101,0.87)}md-radio-button.md-default-theme.md-hue-1:not([disabled]).md-warn .md-container .md-ripple, md-radio-button.md-hue-1:not([disabled]).md-warn .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-container .md-ripple, md-radio-button.md-hue-1:not([disabled]) .md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]).md-warn .md-container .md-ripple, md-radio-group.md-hue-1:not([disabled]).md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-1:not([disabled]) .md-warn .md-container .md-ripple, md-radio-group.md-hue-1:not([disabled]) .md-warn .md-container .md-ripple{color:rgb(244,81,30)}md-radio-group.md-default-theme.md-hue-1.md-focused:not(:empty) .md-checked.md-warn .md-container:before, md-radio-group.md-hue-1.md-focused:not(:empty) .md-checked.md-warn .md-container:before,md-radio-group.md-default-theme.md-hue-1.md-focused:not(:empty).md-warn .md-checked .md-container:before, md-radio-group.md-hue-1.md-focused:not(:empty).md-warn .md-checked .md-container:before{background-color:rgba(255,138,101,0.26)}md-input-container md-select.md-default-theme.md-hue-1 .md-select-value span:first-child:after, md-input-container md-select.md-hue-1 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-1 .md-select-value, md-input-container.md-input-invalid md-select.md-hue-1 .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-1 .md-select-value span:first-child:after, md-select.md-hue-1 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-select.md-default-theme.md-hue-1.ng-invalid.ng-touched .md-select-value, md-select.md-hue-1.ng-invalid.ng-touched .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-1:not([disabled]):focus.md-warn .md-select-value, md-select.md-hue-1:not([disabled]):focus.md-warn .md-select-value{border-bottom-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn .md-focus-ring, md-slider.md-hue-1.md-warn .md-focus-ring{background-color:rgba(255,171,145,0.38)}md-slider.md-default-theme.md-hue-1.md-warn .md-track.md-track-fill, md-slider.md-hue-1.md-warn .md-track.md-track-fill{background-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn .md-thumb:after, md-slider.md-hue-1.md-warn .md-thumb:after{border-color:rgb(255,138,101);background-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn .md-sign, md-slider.md-hue-1.md-warn .md-sign{background-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn .md-sign:after, md-slider.md-hue-1.md-warn .md-sign:after{border-top-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn[md-vertical] .md-sign:after, md-slider.md-hue-1.md-warn[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(255,138,101)}md-slider.md-default-theme.md-hue-1.md-warn .md-thumb-text, md-slider.md-hue-1.md-warn .md-thumb-text{color:rgba(0,0,0,0.87)}.md-subheader.md-default-theme.md-hue-1.md-warn, .md-subheader.md-hue-1.md-warn{color:rgb(255,138,101)}md-switch.md-default-theme.md-hue-1.md-checked.md-warn .md-ink-ripple, md-switch.md-hue-1.md-checked.md-warn .md-ink-ripple{color:rgb(255,138,101)}md-switch.md-default-theme.md-hue-1.md-checked.md-warn .md-thumb, md-switch.md-hue-1.md-checked.md-warn .md-thumb{background-color:rgb(255,138,101)}md-switch.md-default-theme.md-hue-1.md-checked.md-warn .md-bar, md-switch.md-hue-1.md-checked.md-warn .md-bar{background-color:rgba(255,138,101,0.5)}md-switch.md-default-theme.md-hue-1.md-checked.md-warn.md-focused .md-thumb:before, md-switch.md-hue-1.md-checked.md-warn.md-focused .md-thumb:before{background-color:rgba(255,138,101,0.26)}md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper, md-tabs.md-hue-1.md-warn>md-tabs-wrapper{background-color:rgb(255,138,101)}md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-1.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper{background-color:rgb(255,138,101)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-1>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toast.md-default-theme.md-hue-1 .md-toast-content .md-button.md-highlight.md-warn, md-toast.md-hue-1 .md-toast-content .md-button.md-highlight.md-warn{color:rgb(255,138,101)}md-toolbar.md-default-theme.md-hue-1:not(.md-menu-toolbar).md-warn, md-toolbar.md-hue-1:not(.md-menu-toolbar).md-warn{background-color:rgb(255,138,101);color:rgba(0,0,0,0.87)} -.md-button.md-default-theme.md-hue-2.md-warn, .md-button.md-hue-2.md-warn{color:rgb(216,67,21)}.md-button.md-default-theme.md-hue-2.md-warn.md-fab, .md-button.md-hue-2.md-warn.md-fab,.md-button.md-default-theme.md-hue-2.md-warn.md-raised, .md-button.md-hue-2.md-warn.md-raised{color:rgb(255,255,255);background-color:rgb(216,67,21)}.md-button.md-default-theme.md-hue-2.md-warn.md-fab:not([disabled]) md-icon, .md-button.md-hue-2.md-warn.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-2.md-warn.md-raised:not([disabled]) md-icon, .md-button.md-hue-2.md-warn.md-raised:not([disabled]) md-icon{color:rgb(255,255,255)}.md-button.md-default-theme.md-hue-2.md-warn.md-fab:not([disabled]).md-focused, .md-button.md-hue-2.md-warn.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-warn.md-fab:not([disabled]):hover, .md-button.md-hue-2.md-warn.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-2.md-warn.md-raised:not([disabled]).md-focused, .md-button.md-hue-2.md-warn.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2.md-warn.md-raised:not([disabled]):hover, .md-button.md-hue-2.md-warn.md-raised:not([disabled]):hover{background-color:rgb(244,81,30)}.md-button.md-default-theme.md-hue-2.md-warn:not([disabled]) md-icon, .md-button.md-hue-2.md-warn:not([disabled]) md-icon{color:rgb(216,67,21)}._md a.md-default-theme.md-hue-2:not(.md-button).md-warn, ._md a.md-hue-2:not(.md-button).md-warn{color:rgb(216,67,21)}._md a.md-default-theme.md-hue-2:not(.md-button).md-warn:hover, ._md a.md-hue-2:not(.md-button).md-warn:hover{color:rgb(230,74,25)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn .md-ripple, md-checkbox.md-hue-2:not([disabled]).md-warn .md-ripple{color:rgb(244,81,30)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn .md-ink-ripple, md-checkbox.md-hue-2:not([disabled]).md-warn .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple, md-checkbox.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple{color:rgba(216,67,21,0.87)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn:not(.md-checked) .md-icon, md-checkbox.md-hue-2:not([disabled]).md-warn:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-icon, md-checkbox.md-hue-2:not([disabled]).md-warn.md-checked .md-icon{background-color:rgba(216,67,21,0.87)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before, md-checkbox.md-hue-2:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before{background-color:rgba(216,67,21,0.26)}md-checkbox.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-icon:after, md-checkbox.md-hue-2:not([disabled]).md-warn.md-checked .md-icon:after{border-color:rgb(238,238,238)}.md-default-theme.md-hue-2 .md-datepicker-input-container.md-datepicker-invalid, .md-hue-2 .md-datepicker-input-container.md-datepicker-invalid,.md-warn .md-default-theme.md-hue-2 .md-datepicker-input-container.md-datepicker-focused, .md-warn .md-hue-2 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(221,44,0)}.md-default-theme.md-hue-2 .md-datepicker-open.md-warn .md-datepicker-calendar-icon, .md-hue-2 .md-datepicker-open.md-warn .md-datepicker-calendar-icon,.md-warn .md-default-theme.md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon, .md-warn .md-hue-2 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(221,44,0)}md-icon.md-default-theme.md-hue-2.md-warn, md-icon.md-hue-2.md-warn{color:rgb(216,67,21)}md-input-container.md-default-theme.md-hue-2 label.md-required:after, md-input-container.md-hue-2 label.md-required:after{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-2 .md-input-message-animation, md-input-container.md-hue-2 .md-input-message-animation,md-input-container.md-default-theme.md-hue-2 .md-input-messages-animation, md-input-container.md-hue-2 .md-input-messages-animation{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn .md-input, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn label, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn label,md-input-container.md-default-theme.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn md-icon, md-input-container.md-hue-2:not(.md-input-invalid).md-input-focused.md-warn md-icon{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-2.md-input-invalid .md-input, md-input-container.md-hue-2.md-input-invalid .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-2.md-input-invalid .md-char-counter, md-input-container.md-hue-2.md-input-invalid .md-char-counter,md-input-container.md-default-theme.md-hue-2.md-input-invalid .md-input-message-animation, md-input-container.md-hue-2.md-input-invalid .md-input-message-animation,md-input-container.md-default-theme.md-hue-2.md-input-invalid label, md-input-container.md-hue-2.md-input-invalid label{color:rgb(221,44,0)}md-nav-bar.md-default-theme.md-hue-2.md-warn>.md-nav-bar, md-nav-bar.md-hue-2.md-warn>.md-nav-bar{background-color:rgb(216,67,21)}md-nav-bar.md-default-theme.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-nav-bar.md-default-theme.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgb(255,255,255)}md-nav-bar.md-default-theme.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-2.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar, md-toolbar.md-warn>md-nav-bar.md-hue-2>.md-nav-bar{background-color:rgb(216,67,21)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-warn>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-warn>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgb(255,255,255)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-2>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(255,255,255,0.1)}md-progress-circular.md-default-theme.md-hue-2.md-warn path, md-progress-circular.md-hue-2.md-warn path{stroke:rgb(216,67,21)}md-progress-linear.md-default-theme.md-hue-2.md-warn .md-container, md-progress-linear.md-hue-2.md-warn .md-container{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-2.md-warn .md-bar, md-progress-linear.md-hue-2.md-warn .md-bar{background-color:rgb(216,67,21)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-warn .md-bar1, md-progress-linear.md-hue-2[md-mode=buffer].md-warn .md-bar1{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-2[md-mode=buffer].md-warn .md-dashed:before, md-progress-linear.md-hue-2[md-mode=buffer].md-warn .md-dashed:before{background:radial-gradient(rgb(255,204,188) 0,rgb(255,204,188) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn .md-on, md-radio-button.md-hue-2:not([disabled]).md-warn .md-on,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-on, md-radio-button.md-hue-2:not([disabled]) .md-warn .md-on,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn .md-on, md-radio-group.md-hue-2:not([disabled]).md-warn .md-on,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-on, md-radio-group.md-hue-2:not([disabled]) .md-warn .md-on{background-color:rgba(216,67,21,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-off, md-radio-button.md-hue-2:not([disabled]).md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn.md-checked .md-off, md-radio-button.md-hue-2:not([disabled]) .md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn .md-checked .md-off, md-radio-button.md-hue-2:not([disabled]).md-warn .md-checked .md-off,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-checked .md-off, md-radio-button.md-hue-2:not([disabled]) .md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-off, md-radio-group.md-hue-2:not([disabled]).md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn.md-checked .md-off, md-radio-group.md-hue-2:not([disabled]) .md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn .md-checked .md-off, md-radio-group.md-hue-2:not([disabled]).md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-checked .md-off, md-radio-group.md-hue-2:not([disabled]) .md-warn .md-checked .md-off{border-color:rgba(216,67,21,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-2:not([disabled]) .md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-2:not([disabled]) .md-warn .md-checked .md-ink-ripple{color:rgba(216,67,21,0.87)}md-radio-button.md-default-theme.md-hue-2:not([disabled]).md-warn .md-container .md-ripple, md-radio-button.md-hue-2:not([disabled]).md-warn .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-container .md-ripple, md-radio-button.md-hue-2:not([disabled]) .md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]).md-warn .md-container .md-ripple, md-radio-group.md-hue-2:not([disabled]).md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-2:not([disabled]) .md-warn .md-container .md-ripple, md-radio-group.md-hue-2:not([disabled]) .md-warn .md-container .md-ripple{color:rgb(244,81,30)}md-radio-group.md-default-theme.md-hue-2.md-focused:not(:empty) .md-checked.md-warn .md-container:before, md-radio-group.md-hue-2.md-focused:not(:empty) .md-checked.md-warn .md-container:before,md-radio-group.md-default-theme.md-hue-2.md-focused:not(:empty).md-warn .md-checked .md-container:before, md-radio-group.md-hue-2.md-focused:not(:empty).md-warn .md-checked .md-container:before{background-color:rgba(216,67,21,0.26)}md-input-container md-select.md-default-theme.md-hue-2 .md-select-value span:first-child:after, md-input-container md-select.md-hue-2 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-2 .md-select-value, md-input-container.md-input-invalid md-select.md-hue-2 .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-2 .md-select-value span:first-child:after, md-select.md-hue-2 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-select.md-default-theme.md-hue-2.ng-invalid.ng-touched .md-select-value, md-select.md-hue-2.ng-invalid.ng-touched .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-2:not([disabled]):focus.md-warn .md-select-value, md-select.md-hue-2:not([disabled]):focus.md-warn .md-select-value{border-bottom-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn .md-focus-ring, md-slider.md-hue-2.md-warn .md-focus-ring{background-color:rgba(255,171,145,0.38)}md-slider.md-default-theme.md-hue-2.md-warn .md-track.md-track-fill, md-slider.md-hue-2.md-warn .md-track.md-track-fill{background-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn .md-thumb:after, md-slider.md-hue-2.md-warn .md-thumb:after{border-color:rgb(216,67,21);background-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn .md-sign, md-slider.md-hue-2.md-warn .md-sign{background-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn .md-sign:after, md-slider.md-hue-2.md-warn .md-sign:after{border-top-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn[md-vertical] .md-sign:after, md-slider.md-hue-2.md-warn[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(216,67,21)}md-slider.md-default-theme.md-hue-2.md-warn .md-thumb-text, md-slider.md-hue-2.md-warn .md-thumb-text{color:rgb(255,255,255)}.md-subheader.md-default-theme.md-hue-2.md-warn, .md-subheader.md-hue-2.md-warn{color:rgb(216,67,21)}md-switch.md-default-theme.md-hue-2.md-checked.md-warn .md-ink-ripple, md-switch.md-hue-2.md-checked.md-warn .md-ink-ripple{color:rgb(216,67,21)}md-switch.md-default-theme.md-hue-2.md-checked.md-warn .md-thumb, md-switch.md-hue-2.md-checked.md-warn .md-thumb{background-color:rgb(216,67,21)}md-switch.md-default-theme.md-hue-2.md-checked.md-warn .md-bar, md-switch.md-hue-2.md-checked.md-warn .md-bar{background-color:rgba(216,67,21,0.5)}md-switch.md-default-theme.md-hue-2.md-checked.md-warn.md-focused .md-thumb:before, md-switch.md-hue-2.md-checked.md-warn.md-focused .md-thumb:before{background-color:rgba(216,67,21,0.26)}md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper, md-tabs.md-hue-2.md-warn>md-tabs-wrapper{background-color:rgb(216,67,21)}md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgb(255,255,255)}md-tabs.md-default-theme.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-2.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper{background-color:rgb(216,67,21)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgb(255,255,255)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-2>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(255,255,255,0.1)}md-toast.md-default-theme.md-hue-2 .md-toast-content .md-button.md-highlight.md-warn, md-toast.md-hue-2 .md-toast-content .md-button.md-highlight.md-warn{color:rgb(216,67,21)}md-toolbar.md-default-theme.md-hue-2:not(.md-menu-toolbar).md-warn, md-toolbar.md-hue-2:not(.md-menu-toolbar).md-warn{background-color:rgb(216,67,21);color:rgb(255,255,255)} -.md-button.md-default-theme.md-hue-3.md-warn, .md-button.md-hue-3.md-warn{color:rgb(255,158,128)}.md-button.md-default-theme.md-hue-3.md-warn.md-fab, .md-button.md-hue-3.md-warn.md-fab,.md-button.md-default-theme.md-hue-3.md-warn.md-raised, .md-button.md-hue-3.md-warn.md-raised{color:rgba(0,0,0,0.87);background-color:rgb(255,158,128)}.md-button.md-default-theme.md-hue-3.md-warn.md-fab:not([disabled]) md-icon, .md-button.md-hue-3.md-warn.md-fab:not([disabled]) md-icon,.md-button.md-default-theme.md-hue-3.md-warn.md-raised:not([disabled]) md-icon, .md-button.md-hue-3.md-warn.md-raised:not([disabled]) md-icon{color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3.md-warn.md-fab:not([disabled]).md-focused, .md-button.md-hue-3.md-warn.md-fab:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-warn.md-fab:not([disabled]):hover, .md-button.md-hue-3.md-warn.md-fab:not([disabled]):hover,.md-button.md-default-theme.md-hue-3.md-warn.md-raised:not([disabled]).md-focused, .md-button.md-hue-3.md-warn.md-raised:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3.md-warn.md-raised:not([disabled]):hover, .md-button.md-hue-3.md-warn.md-raised:not([disabled]):hover{background-color:rgb(244,81,30)}.md-button.md-default-theme.md-hue-3.md-warn:not([disabled]) md-icon, .md-button.md-hue-3.md-warn:not([disabled]) md-icon{color:rgb(255,158,128)}._md a.md-default-theme.md-hue-3:not(.md-button).md-warn, ._md a.md-hue-3:not(.md-button).md-warn{color:rgb(255,158,128)}._md a.md-default-theme.md-hue-3:not(.md-button).md-warn:hover, ._md a.md-hue-3:not(.md-button).md-warn:hover{color:rgb(230,74,25)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn .md-ripple, md-checkbox.md-hue-3:not([disabled]).md-warn .md-ripple{color:rgb(244,81,30)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn .md-ink-ripple, md-checkbox.md-hue-3:not([disabled]).md-warn .md-ink-ripple{color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple, md-checkbox.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple{color:rgba(255,158,128,0.87)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn:not(.md-checked) .md-icon, md-checkbox.md-hue-3:not([disabled]).md-warn:not(.md-checked) .md-icon{border-color:rgba(0,0,0,0.54)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-icon, md-checkbox.md-hue-3:not([disabled]).md-warn.md-checked .md-icon{background-color:rgba(255,158,128,0.87)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before, md-checkbox.md-hue-3:not([disabled]).md-warn.md-checked.md-focused:not([disabled]) .md-container:before{background-color:rgba(255,158,128,0.26)}md-checkbox.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-icon:after, md-checkbox.md-hue-3:not([disabled]).md-warn.md-checked .md-icon:after{border-color:rgb(238,238,238)}.md-default-theme.md-hue-3 .md-datepicker-input-container.md-datepicker-invalid, .md-hue-3 .md-datepicker-input-container.md-datepicker-invalid,.md-warn .md-default-theme.md-hue-3 .md-datepicker-input-container.md-datepicker-focused, .md-warn .md-hue-3 .md-datepicker-input-container.md-datepicker-focused{border-bottom-color:rgb(221,44,0)}.md-default-theme.md-hue-3 .md-datepicker-open.md-warn .md-datepicker-calendar-icon, .md-hue-3 .md-datepicker-open.md-warn .md-datepicker-calendar-icon,.md-warn .md-default-theme.md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon, .md-warn .md-hue-3 .md-datepicker-open .md-datepicker-calendar-icon{color:rgb(221,44,0)}md-icon.md-default-theme.md-hue-3.md-warn, md-icon.md-hue-3.md-warn{color:rgb(255,158,128)}md-input-container.md-default-theme.md-hue-3 label.md-required:after, md-input-container.md-hue-3 label.md-required:after{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-3 .md-input-message-animation, md-input-container.md-hue-3 .md-input-message-animation,md-input-container.md-default-theme.md-hue-3 .md-input-messages-animation, md-input-container.md-hue-3 .md-input-messages-animation{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn .md-input, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn label, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn label,md-input-container.md-default-theme.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn md-icon, md-input-container.md-hue-3:not(.md-input-invalid).md-input-focused.md-warn md-icon{color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-3.md-input-invalid .md-input, md-input-container.md-hue-3.md-input-invalid .md-input{border-color:rgb(221,44,0)}md-input-container.md-default-theme.md-hue-3.md-input-invalid .md-char-counter, md-input-container.md-hue-3.md-input-invalid .md-char-counter,md-input-container.md-default-theme.md-hue-3.md-input-invalid .md-input-message-animation, md-input-container.md-hue-3.md-input-invalid .md-input-message-animation,md-input-container.md-default-theme.md-hue-3.md-input-invalid label, md-input-container.md-hue-3.md-input-invalid label{color:rgb(221,44,0)}md-nav-bar.md-default-theme.md-hue-3.md-warn>.md-nav-bar, md-nav-bar.md-hue-3.md-warn>.md-nav-bar{background-color:rgb(255,158,128)}md-nav-bar.md-default-theme.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button, md-nav-bar.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-nav-bar.md-default-theme.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-active, md-nav-bar.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-active,md-nav-bar.md-default-theme.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused, md-nav-bar.md-hue-3.md-warn>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar, md-toolbar.md-warn>md-nav-bar.md-hue-3>.md-nav-bar{background-color:rgb(255,158,128)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button, md-toolbar.md-warn>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button{color:rgb(255,204,188)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active, md-toolbar.md-warn>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-active,md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{color:rgba(0,0,0,0.87)}md-toolbar.md-warn>md-nav-bar.md-default-theme.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused, md-toolbar.md-warn>md-nav-bar.md-hue-3>.md-nav-bar .md-button._md-nav-button.md-focused{background:rgba(0,0,0,0.1)}md-progress-circular.md-default-theme.md-hue-3.md-warn path, md-progress-circular.md-hue-3.md-warn path{stroke:rgb(255,158,128)}md-progress-linear.md-default-theme.md-hue-3.md-warn .md-container, md-progress-linear.md-hue-3.md-warn .md-container{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-3.md-warn .md-bar, md-progress-linear.md-hue-3.md-warn .md-bar{background-color:rgb(255,158,128)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-warn .md-bar1, md-progress-linear.md-hue-3[md-mode=buffer].md-warn .md-bar1{background-color:rgb(255,204,188)}md-progress-linear.md-default-theme.md-hue-3[md-mode=buffer].md-warn .md-dashed:before, md-progress-linear.md-hue-3[md-mode=buffer].md-warn .md-dashed:before{background:radial-gradient(rgb(255,204,188) 0,rgb(255,204,188) 16%,transparent 42%)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn .md-on, md-radio-button.md-hue-3:not([disabled]).md-warn .md-on,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-on, md-radio-button.md-hue-3:not([disabled]) .md-warn .md-on,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn .md-on, md-radio-group.md-hue-3:not([disabled]).md-warn .md-on,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-on, md-radio-group.md-hue-3:not([disabled]) .md-warn .md-on{background-color:rgba(255,158,128,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-off, md-radio-button.md-hue-3:not([disabled]).md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn.md-checked .md-off, md-radio-button.md-hue-3:not([disabled]) .md-warn.md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn .md-checked .md-off, md-radio-button.md-hue-3:not([disabled]).md-warn .md-checked .md-off,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-checked .md-off, md-radio-button.md-hue-3:not([disabled]) .md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-off, md-radio-group.md-hue-3:not([disabled]).md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn.md-checked .md-off, md-radio-group.md-hue-3:not([disabled]) .md-warn.md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn .md-checked .md-off, md-radio-group.md-hue-3:not([disabled]).md-warn .md-checked .md-off,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-checked .md-off, md-radio-group.md-hue-3:not([disabled]) .md-warn .md-checked .md-off{border-color:rgba(255,158,128,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-button.md-hue-3:not([disabled]) .md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]).md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn.md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]) .md-warn.md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]).md-warn .md-checked .md-ink-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-checked .md-ink-ripple, md-radio-group.md-hue-3:not([disabled]) .md-warn .md-checked .md-ink-ripple{color:rgba(255,158,128,0.87)}md-radio-button.md-default-theme.md-hue-3:not([disabled]).md-warn .md-container .md-ripple, md-radio-button.md-hue-3:not([disabled]).md-warn .md-container .md-ripple,md-radio-button.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-container .md-ripple, md-radio-button.md-hue-3:not([disabled]) .md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]).md-warn .md-container .md-ripple, md-radio-group.md-hue-3:not([disabled]).md-warn .md-container .md-ripple,md-radio-group.md-default-theme.md-hue-3:not([disabled]) .md-warn .md-container .md-ripple, md-radio-group.md-hue-3:not([disabled]) .md-warn .md-container .md-ripple{color:rgb(244,81,30)}md-radio-group.md-default-theme.md-hue-3.md-focused:not(:empty) .md-checked.md-warn .md-container:before, md-radio-group.md-hue-3.md-focused:not(:empty) .md-checked.md-warn .md-container:before,md-radio-group.md-default-theme.md-hue-3.md-focused:not(:empty).md-warn .md-checked .md-container:before, md-radio-group.md-hue-3.md-focused:not(:empty).md-warn .md-checked .md-container:before{background-color:rgba(255,158,128,0.26)}md-input-container md-select.md-default-theme.md-hue-3 .md-select-value span:first-child:after, md-input-container md-select.md-hue-3 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-input-container.md-input-invalid md-select.md-default-theme.md-hue-3 .md-select-value, md-input-container.md-input-invalid md-select.md-hue-3 .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-3 .md-select-value span:first-child:after, md-select.md-hue-3 .md-select-value span:first-child:after{color:rgb(221,44,0)}md-select.md-default-theme.md-hue-3.ng-invalid.ng-touched .md-select-value, md-select.md-hue-3.ng-invalid.ng-touched .md-select-value{color:rgb(221,44,0)!important;border-bottom-color:rgb(221,44,0)!important}md-select.md-default-theme.md-hue-3:not([disabled]):focus.md-warn .md-select-value, md-select.md-hue-3:not([disabled]):focus.md-warn .md-select-value{border-bottom-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn .md-focus-ring, md-slider.md-hue-3.md-warn .md-focus-ring{background-color:rgba(255,171,145,0.38)}md-slider.md-default-theme.md-hue-3.md-warn .md-track.md-track-fill, md-slider.md-hue-3.md-warn .md-track.md-track-fill{background-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn .md-thumb:after, md-slider.md-hue-3.md-warn .md-thumb:after{border-color:rgb(255,158,128);background-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn .md-sign, md-slider.md-hue-3.md-warn .md-sign{background-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn .md-sign:after, md-slider.md-hue-3.md-warn .md-sign:after{border-top-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn[md-vertical] .md-sign:after, md-slider.md-hue-3.md-warn[md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(255,158,128)}md-slider.md-default-theme.md-hue-3.md-warn .md-thumb-text, md-slider.md-hue-3.md-warn .md-thumb-text{color:rgba(0,0,0,0.87)}.md-subheader.md-default-theme.md-hue-3.md-warn, .md-subheader.md-hue-3.md-warn{color:rgb(255,158,128)}md-switch.md-default-theme.md-hue-3.md-checked.md-warn .md-ink-ripple, md-switch.md-hue-3.md-checked.md-warn .md-ink-ripple{color:rgb(255,158,128)}md-switch.md-default-theme.md-hue-3.md-checked.md-warn .md-thumb, md-switch.md-hue-3.md-checked.md-warn .md-thumb{background-color:rgb(255,158,128)}md-switch.md-default-theme.md-hue-3.md-checked.md-warn .md-bar, md-switch.md-hue-3.md-checked.md-warn .md-bar{background-color:rgba(255,158,128,0.5)}md-switch.md-default-theme.md-hue-3.md-checked.md-warn.md-focused .md-thumb:before, md-switch.md-hue-3.md-checked.md-warn.md-focused .md-thumb:before{background-color:rgba(255,158,128,0.26)}md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper, md-tabs.md-hue-3.md-warn>md-tabs-wrapper{background-color:rgb(255,158,128)}md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-tabs.md-default-theme.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-tabs.md-hue-3.md-warn>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper{background-color:rgb(255,158,128)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]), md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]),md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]) md-icon{color:rgb(255,204,188)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-active md-icon,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused,md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused md-icon{color:rgba(0,0,0,0.87)}md-toolbar.md-warn>md-tabs.md-default-theme.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused, md-toolbar.md-warn>md-tabs.md-hue-3>md-tabs-wrapper>md-tabs-canvas>md-pagination-wrapper>md-tab-item:not([disabled]).md-focused{background:rgba(0,0,0,0.1)}md-toast.md-default-theme.md-hue-3 .md-toast-content .md-button.md-highlight.md-warn, md-toast.md-hue-3 .md-toast-content .md-button.md-highlight.md-warn{color:rgb(255,158,128)}md-toolbar.md-default-theme.md-hue-3:not(.md-menu-toolbar).md-warn, md-toolbar.md-hue-3:not(.md-menu-toolbar).md-warn{background-color:rgb(255,158,128);color:rgba(0,0,0,0.87)} -md-autocomplete.md-default-theme, md-autocomplete{background:rgb(245,245,245)}md-autocomplete.md-default-theme[disabled]:not([md-floating-label]), md-autocomplete[disabled]:not([md-floating-label]){background:rgb(238,238,238)}md-autocomplete.md-default-theme button md-icon path, md-autocomplete button md-icon path{fill:rgb(117,117,117)}md-autocomplete.md-default-theme button:after, md-autocomplete button:after{background:rgba(117,117,117,0.3)}.md-autocomplete-suggestions-container.md-default-theme, .md-autocomplete-suggestions-container{background:rgb(245,245,245)}.md-autocomplete-suggestions-container.md-default-theme li.selected, .md-autocomplete-suggestions-container li.selected,.md-autocomplete-suggestions-container.md-default-theme li:hover, .md-autocomplete-suggestions-container li:hover{background:rgba(158,158,158,0.18)}md-backdrop{background-color:rgba(33,33,33,0.0)}md-backdrop.md-opaque.md-default-theme, md-backdrop.md-opaque{background-color:rgba(33,33,33,1.0)}md-bottom-sheet.md-default-theme, md-bottom-sheet{background-color:rgb(250,250,250);border-top-color:rgb(224,224,224)}md-bottom-sheet.md-default-theme .md-subheader, md-bottom-sheet .md-subheader{background-color:rgb(250,250,250);color:rgba(0,0,0,0.87)}.md-button.md-default-theme:not([disabled]).md-focused, .md-button:not([disabled]).md-focused,.md-button.md-default-theme:not([disabled]):hover, .md-button:not([disabled]):hover{background-color:rgba(158,158,158,0.2)}.md-button.md-default-theme:not([disabled]).md-icon-button:hover, .md-button:not([disabled]).md-icon-button:hover{background-color:transparent}.md-button.md-default-theme.md-raised, .md-button.md-raised{color:rgb(33,33,33);background-color:rgb(250,250,250)}.md-button.md-default-theme.md-raised:not([disabled]) md-icon, .md-button.md-raised:not([disabled]) md-icon{color:rgb(33,33,33)}.md-button.md-default-theme.md-raised:not([disabled]):hover, .md-button.md-raised:not([disabled]):hover{background-color:rgb(250,250,250)}.md-button.md-default-theme.md-raised:not([disabled]).md-focused, .md-button.md-raised:not([disabled]).md-focused{background-color:rgb(238,238,238)}.md-button.md-default-theme.md-fab[disabled], .md-button.md-fab[disabled],.md-button.md-default-theme.md-raised[disabled], .md-button.md-raised[disabled]{background-color:rgba(0,0,0,0.12)}.md-button.md-default-theme[disabled], .md-button[disabled]{background-color:transparent}md-card.md-default-theme, md-card{color:rgba(0,0,0,0.87);background-color:rgb(245,245,245);border-radius:2px}md-card.md-default-theme md-card-header md-card-avatar md-icon, md-card md-card-header md-card-avatar md-icon{color:rgb(250,250,250);background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-checked .md-ripple, md-checkbox.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme[disabled].md-checked .md-icon, md-checkbox[disabled].md-checked .md-icon{background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme[disabled].md-checked .md-icon:after, md-checkbox[disabled].md-checked .md-icon:after{border-color:rgb(238,238,238)}md-chips.md-default-theme md-chip, md-chips md-chip{background:rgb(224,224,224);color:rgb(66,66,66)}md-chips.md-default-theme md-chip md-icon, md-chips md-chip md-icon{color:rgb(97,97,97)}md-chips.md-default-theme md-chip._md-chip-editing, md-chips md-chip._md-chip-editing{background:transparent;color:rgb(66,66,66)}md-chips.md-default-theme md-chip-remove .md-button md-icon path, md-chips md-chip-remove .md-button md-icon path{fill:rgb(158,158,158)}.md-contact-suggestion span.md-contact-email{color:rgb(189,189,189)}md-content.md-default-theme, md-content{color:rgba(0,0,0,0.87);background-color:rgb(250,250,250)}.md-default-theme .md-calendar, .md-calendar{background:rgb(245,245,245);color:rgba(0,0,0,0.87)}.md-default-theme .md-calendar tr:last-child td, .md-calendar tr:last-child td{border-bottom-color:rgb(238,238,238)}.md-default-theme .md-calendar-day-header, .md-calendar-day-header{background:rgba(158,158,158,0.32);color:rgba(0,0,0,0.87)}.md-calendar-date.md-focus .md-default-theme .md-calendar-date-selection-indicator, .md-calendar-date.md-focus .md-calendar-date-selection-indicator,.md-default-theme .md-calendar-date-selection-indicator:hover, .md-calendar-date-selection-indicator:hover{background:rgba(158,158,158,0.32)}.md-default-theme .md-datepicker-calendar-pane, .md-datepicker-calendar-pane{border-color:rgb(245,245,245)}.md-default-theme .md-datepicker-calendar, .md-datepicker-calendar{background:rgb(245,245,245)}.md-default-theme .md-datepicker-input-mask-opaque, .md-datepicker-input-mask-opaque{box-shadow:0 0 0 9999px rgb(245,245,245)}.md-default-theme .md-datepicker-open .md-datepicker-input-container, .md-datepicker-open .md-datepicker-input-container{background:rgb(245,245,245)}md-dialog.md-default-theme, md-dialog{border-radius:4px;background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}[disabled] md-input-container.md-default-theme .md-input, [disabled] md-input-container .md-input,md-input-container.md-default-theme .md-input[disabled], md-input-container .md-input[disabled]{border-bottom-color:transparent;color:rgba(0,0,0,0.38);background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-list.md-default-theme .md-proxy-focus.md-focused div.md-no-style, md-list .md-proxy-focus.md-focused div.md-no-style{background-color:rgb(245,245,245)}md-list.md-default-theme md-list-item .md-avatar-icon, md-list md-list-item .md-avatar-icon{background-color:rgba(0,0,0,0.38);color:rgb(250,250,250)}md-menu-content.md-default-theme, md-menu-content{background-color:rgb(245,245,245)}md-menu-content.md-default-theme md-menu-divider, md-menu-content md-menu-divider{background-color:rgba(0,0,0,0.12)}md-menu-bar.md-default-theme md-menu.md-open>button, md-menu-bar md-menu.md-open>button,md-menu-bar.md-default-theme md-menu>button:focus, md-menu-bar md-menu>button:focus{outline:none;background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-open:not(.md-keyboard-mode) md-menu:hover>button, md-menu-bar.md-open:not(.md-keyboard-mode) md-menu:hover>button{background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme:not(.md-keyboard-mode):not(.md-open) md-menu button:focus, md-menu-bar:not(.md-keyboard-mode):not(.md-open) md-menu button:focus,md-menu-bar.md-default-theme:not(.md-keyboard-mode):not(.md-open) md-menu button:hover, md-menu-bar:not(.md-keyboard-mode):not(.md-open) md-menu button:hover{background:transparent}md-menu-content.md-default-theme .md-menu.md-open>.md-button, md-menu-content .md-menu.md-open>.md-button{background-color:rgba(158,158,158,0.18)}md-toolbar.md-default-theme.md-menu-toolbar, md-toolbar.md-menu-toolbar{background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme .md-nav-bar, md-nav-bar .md-nav-bar{background-color:transparent;border-color:rgba(0,0,0,0.12)}._md-panel-backdrop.md-default-theme, ._md-panel-backdrop{background-color:rgba(33,33,33,1.0)}md-select.md-default-theme[disabled] .md-select-value, md-select[disabled] .md-select-value{border-bottom-color:transparent;background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-select-menu.md-default-theme md-content, md-select-menu md-content{background-color:rgb(245,245,245)}md-select-menu.md-default-theme md-content md-option:not([disabled]):focus, md-select-menu md-content md-option:not([disabled]):focus,md-select-menu.md-default-theme md-content md-option:not([disabled]):hover, md-select-menu md-content md-option:not([disabled]):hover{background-color:rgba(158,158,158,0.18)}.md-checkbox-enabled.md-default-theme[selected] .md-ripple, .md-checkbox-enabled[selected] .md-ripple{color:rgb(117,117,117)}md-sidenav.md-default-theme, md-sidenav,md-sidenav.md-default-theme md-content, md-sidenav md-content{background-color:rgb(245,245,245)}md-slider.md-default-theme .md-track, md-slider .md-track{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme .md-track-ticks, md-slider .md-track-ticks{color:rgba(0,0,0,0.87)}md-slider.md-default-theme .md-disabled-thumb, md-slider .md-disabled-thumb{border-color:rgb(250,250,250);background-color:rgb(250,250,250)}md-slider.md-default-theme.md-min .md-thumb:after, md-slider.md-min .md-thumb:after{background-color:rgb(250,250,250);border-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-min .md-focus-ring, md-slider.md-min .md-focus-ring{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-min[md-discrete] .md-thumb:after, md-slider.md-min[md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.87);border-color:transparent}md-slider.md-default-theme.md-min[md-discrete] .md-sign, md-slider.md-min[md-discrete] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-min[md-discrete] .md-sign:after, md-slider.md-min[md-discrete] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-min[md-discrete][md-vertical] .md-sign:after, md-slider.md-min[md-discrete][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme[disabled]:not(.md-min) .md-thumb:after, md-slider[disabled]:not(.md-min) .md-thumb:after,md-slider.md-default-theme[disabled][md-discrete] .md-thumb:after, md-slider[disabled][md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.38);border-color:transparent}md-slider.md-default-theme[disabled][readonly] .md-sign, md-slider[disabled][readonly] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme[disabled][readonly] .md-sign:after, md-slider[disabled][readonly] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme[disabled][readonly][md-vertical] .md-sign:after, md-slider[disabled][readonly][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme[disabled][readonly] .md-disabled-thumb, md-slider[disabled][readonly] .md-disabled-thumb{border-color:transparent;background-color:transparent}.md-subheader.md-default-theme, .md-subheader{color:rgba(0,0,0,0.54);background-color:rgb(250,250,250)}md-switch.md-default-theme .md-ink-ripple, md-switch .md-ink-ripple{color:rgb(158,158,158)}md-switch.md-default-theme .md-thumb, md-switch .md-thumb{background-color:rgb(250,250,250)}md-switch.md-default-theme .md-bar, md-switch .md-bar{background-color:rgb(158,158,158)}md-switch.md-default-theme[disabled] .md-thumb, md-switch[disabled] .md-thumb{background-color:rgb(189,189,189)}md-switch.md-default-theme[disabled] .md-bar, md-switch[disabled] .md-bar{background-color:rgba(0,0,0,0.12)}md-tabs.md-default-theme md-tabs-wrapper, md-tabs md-tabs-wrapper{background-color:transparent;border-color:rgba(0,0,0,0.12)}md-toast.md-default-theme .md-toast-content, md-toast .md-toast-content{background-color:#323232;color:rgb(250,250,250)}md-toast.md-default-theme .md-toast-content .md-button, md-toast .md-toast-content .md-button{color:rgb(250,250,250)}.md-panel.md-tooltip.md-default-theme, .md-panel.md-tooltip{color:rgba(255,255,255,0.87);background-color:rgb(97,97,97)}body.md-default-theme, body,html.md-default-theme, html{color:rgba(0,0,0,0.87);background-color:rgb(250,250,250)} -md-autocomplete.md-default-theme.md-hue-1, md-autocomplete.md-hue-1{background:rgb(245,245,245)}md-autocomplete.md-default-theme.md-hue-1[disabled]:not([md-floating-label]), md-autocomplete.md-hue-1[disabled]:not([md-floating-label]){background:rgb(238,238,238)}md-autocomplete.md-default-theme.md-hue-1 button md-icon path, md-autocomplete.md-hue-1 button md-icon path{fill:rgb(117,117,117)}md-autocomplete.md-default-theme.md-hue-1 button:after, md-autocomplete.md-hue-1 button:after{background:rgba(117,117,117,0.3)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-1, .md-autocomplete-suggestions-container.md-hue-1{background:rgb(245,245,245)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-1 li.selected, .md-autocomplete-suggestions-container.md-hue-1 li.selected,.md-autocomplete-suggestions-container.md-default-theme.md-hue-1 li:hover, .md-autocomplete-suggestions-container.md-hue-1 li:hover{background:rgba(158,158,158,0.18)}md-backdrop{background-color:rgba(33,33,33,0.0)}md-backdrop.md-opaque.md-default-theme.md-hue-1, md-backdrop.md-opaque.md-hue-1{background-color:rgba(33,33,33,1.0)}md-bottom-sheet.md-default-theme.md-hue-1, md-bottom-sheet.md-hue-1{background-color:rgb(250,250,250);border-top-color:rgb(224,224,224)}md-bottom-sheet.md-default-theme.md-hue-1 .md-subheader, md-bottom-sheet.md-hue-1 .md-subheader{background-color:rgb(250,250,250);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-1:not([disabled]).md-focused, .md-button.md-hue-1:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-1:not([disabled]):hover, .md-button.md-hue-1:not([disabled]):hover{background-color:rgba(158,158,158,0.2)}.md-button.md-default-theme.md-hue-1:not([disabled]).md-icon-button:hover, .md-button.md-hue-1:not([disabled]).md-icon-button:hover{background-color:transparent}.md-button.md-default-theme.md-hue-1.md-raised, .md-button.md-hue-1.md-raised{color:rgb(33,33,33);background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-1.md-raised:not([disabled]) md-icon, .md-button.md-hue-1.md-raised:not([disabled]) md-icon{color:rgb(33,33,33)}.md-button.md-default-theme.md-hue-1.md-raised:not([disabled]):hover, .md-button.md-hue-1.md-raised:not([disabled]):hover{background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-1.md-raised:not([disabled]).md-focused, .md-button.md-hue-1.md-raised:not([disabled]).md-focused{background-color:rgb(238,238,238)}.md-button.md-default-theme.md-hue-1.md-fab[disabled], .md-button.md-hue-1.md-fab[disabled],.md-button.md-default-theme.md-hue-1.md-raised[disabled], .md-button.md-hue-1.md-raised[disabled]{background-color:rgba(0,0,0,0.12)}.md-button.md-default-theme.md-hue-1[disabled], .md-button.md-hue-1[disabled]{background-color:transparent}md-card.md-default-theme.md-hue-1, md-card.md-hue-1{color:rgba(0,0,0,0.87);background-color:rgb(245,245,245);border-radius:2px}md-card.md-default-theme.md-hue-1 md-card-header md-card-avatar md-icon, md-card.md-hue-1 md-card-header md-card-avatar md-icon{color:rgb(245,245,245);background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-1.md-checked .md-ripple, md-checkbox.md-hue-1.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-1[disabled].md-checked .md-icon, md-checkbox.md-hue-1[disabled].md-checked .md-icon{background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-1[disabled].md-checked .md-icon:after, md-checkbox.md-hue-1[disabled].md-checked .md-icon:after{border-color:rgb(238,238,238)}md-chips.md-default-theme.md-hue-1 md-chip, md-chips.md-hue-1 md-chip{background:rgb(224,224,224);color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-1 md-chip md-icon, md-chips.md-hue-1 md-chip md-icon{color:rgb(97,97,97)}md-chips.md-default-theme.md-hue-1 md-chip._md-chip-editing, md-chips.md-hue-1 md-chip._md-chip-editing{background:transparent;color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-1 md-chip-remove .md-button md-icon path, md-chips.md-hue-1 md-chip-remove .md-button md-icon path{fill:rgb(158,158,158)}.md-contact-suggestion span.md-contact-email{color:rgb(189,189,189)}md-content.md-default-theme.md-hue-1, md-content.md-hue-1{color:rgba(0,0,0,0.87);background-color:rgb(250,250,250)}.md-default-theme.md-hue-1 .md-calendar, .md-hue-1 .md-calendar{background:rgb(245,245,245);color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-1 .md-calendar tr:last-child td, .md-hue-1 .md-calendar tr:last-child td{border-bottom-color:rgb(238,238,238)}.md-default-theme.md-hue-1 .md-calendar-day-header, .md-hue-1 .md-calendar-day-header{background:rgba(158,158,158,0.32);color:rgba(0,0,0,0.87)}.md-calendar-date.md-focus .md-default-theme.md-hue-1 .md-calendar-date-selection-indicator, .md-calendar-date.md-focus .md-hue-1 .md-calendar-date-selection-indicator,.md-default-theme.md-hue-1 .md-calendar-date-selection-indicator:hover, .md-hue-1 .md-calendar-date-selection-indicator:hover{background:rgba(158,158,158,0.32)}.md-default-theme.md-hue-1 .md-datepicker-calendar-pane, .md-hue-1 .md-datepicker-calendar-pane{border-color:rgb(245,245,245)}.md-default-theme.md-hue-1 .md-datepicker-calendar, .md-hue-1 .md-datepicker-calendar{background:rgb(245,245,245)}.md-default-theme.md-hue-1 .md-datepicker-input-mask-opaque, .md-hue-1 .md-datepicker-input-mask-opaque{box-shadow:0 0 0 9999px rgb(245,245,245)}.md-default-theme.md-hue-1 .md-datepicker-open .md-datepicker-input-container, .md-hue-1 .md-datepicker-open .md-datepicker-input-container{background:rgb(245,245,245)}md-dialog.md-default-theme.md-hue-1, md-dialog.md-hue-1{border-radius:4px;background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}[disabled] md-input-container.md-default-theme.md-hue-1 .md-input, [disabled] md-input-container.md-hue-1 .md-input,md-input-container.md-default-theme.md-hue-1 .md-input[disabled], md-input-container.md-hue-1 .md-input[disabled]{border-bottom-color:transparent;color:rgba(0,0,0,0.38);background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-list.md-default-theme.md-hue-1 .md-proxy-focus.md-focused div.md-no-style, md-list.md-hue-1 .md-proxy-focus.md-focused div.md-no-style{background-color:rgb(245,245,245)}md-list.md-default-theme.md-hue-1 md-list-item .md-avatar-icon, md-list.md-hue-1 md-list-item .md-avatar-icon{background-color:rgba(0,0,0,0.38);color:rgb(245,245,245)}md-menu-content.md-default-theme.md-hue-1, md-menu-content.md-hue-1{background-color:rgb(245,245,245)}md-menu-content.md-default-theme.md-hue-1 md-menu-divider, md-menu-content.md-hue-1 md-menu-divider{background-color:rgba(0,0,0,0.12)}md-menu-bar.md-default-theme.md-hue-1 md-menu.md-open>button, md-menu-bar.md-hue-1 md-menu.md-open>button,md-menu-bar.md-default-theme.md-hue-1 md-menu>button:focus, md-menu-bar.md-hue-1 md-menu>button:focus{outline:none;background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-1.md-open:not(.md-keyboard-mode) md-menu:hover>button, md-menu-bar.md-hue-1.md-open:not(.md-keyboard-mode) md-menu:hover>button{background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-1:not(.md-keyboard-mode):not(.md-open) md-menu button:focus, md-menu-bar.md-hue-1:not(.md-keyboard-mode):not(.md-open) md-menu button:focus,md-menu-bar.md-default-theme.md-hue-1:not(.md-keyboard-mode):not(.md-open) md-menu button:hover, md-menu-bar.md-hue-1:not(.md-keyboard-mode):not(.md-open) md-menu button:hover{background:transparent}md-menu-content.md-default-theme.md-hue-1 .md-menu.md-open>.md-button, md-menu-content.md-hue-1 .md-menu.md-open>.md-button{background-color:rgba(158,158,158,0.18)}md-toolbar.md-default-theme.md-hue-1.md-menu-toolbar, md-toolbar.md-hue-1.md-menu-toolbar{background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-1 .md-nav-bar, md-nav-bar.md-hue-1 .md-nav-bar{background-color:transparent;border-color:rgba(0,0,0,0.12)}._md-panel-backdrop.md-default-theme.md-hue-1, ._md-panel-backdrop.md-hue-1{background-color:rgba(33,33,33,1.0)}md-select.md-default-theme.md-hue-1[disabled] .md-select-value, md-select.md-hue-1[disabled] .md-select-value{border-bottom-color:transparent;background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-select-menu.md-default-theme.md-hue-1 md-content, md-select-menu.md-hue-1 md-content{background-color:rgb(245,245,245)}md-select-menu.md-default-theme.md-hue-1 md-content md-option:not([disabled]):focus, md-select-menu.md-hue-1 md-content md-option:not([disabled]):focus,md-select-menu.md-default-theme.md-hue-1 md-content md-option:not([disabled]):hover, md-select-menu.md-hue-1 md-content md-option:not([disabled]):hover{background-color:rgba(158,158,158,0.18)}.md-checkbox-enabled.md-default-theme.md-hue-1[selected] .md-ripple, .md-checkbox-enabled.md-hue-1[selected] .md-ripple{color:rgb(117,117,117)}md-sidenav.md-default-theme.md-hue-1, md-sidenav.md-hue-1,md-sidenav.md-default-theme.md-hue-1 md-content, md-sidenav.md-hue-1 md-content{background-color:rgb(245,245,245)}md-slider.md-default-theme.md-hue-1 .md-track, md-slider.md-hue-1 .md-track{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-1 .md-track-ticks, md-slider.md-hue-1 .md-track-ticks{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-1 .md-disabled-thumb, md-slider.md-hue-1 .md-disabled-thumb{border-color:rgb(245,245,245);background-color:rgb(245,245,245)}md-slider.md-default-theme.md-hue-1.md-min .md-thumb:after, md-slider.md-hue-1.md-min .md-thumb:after{background-color:rgb(245,245,245);border-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-1.md-min .md-focus-ring, md-slider.md-hue-1.md-min .md-focus-ring{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-1.md-min[md-discrete] .md-thumb:after, md-slider.md-hue-1.md-min[md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.87);border-color:transparent}md-slider.md-default-theme.md-hue-1.md-min[md-discrete] .md-sign, md-slider.md-hue-1.md-min[md-discrete] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1.md-min[md-discrete] .md-sign:after, md-slider.md-hue-1.md-min[md-discrete] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1.md-min[md-discrete][md-vertical] .md-sign:after, md-slider.md-hue-1.md-min[md-discrete][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1[disabled]:not(.md-min) .md-thumb:after, md-slider.md-hue-1[disabled]:not(.md-min) .md-thumb:after,md-slider.md-default-theme.md-hue-1[disabled][md-discrete] .md-thumb:after, md-slider.md-hue-1[disabled][md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.38);border-color:transparent}md-slider.md-default-theme.md-hue-1[disabled][readonly] .md-sign, md-slider.md-hue-1[disabled][readonly] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1[disabled][readonly] .md-sign:after, md-slider.md-hue-1[disabled][readonly] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1[disabled][readonly][md-vertical] .md-sign:after, md-slider.md-hue-1[disabled][readonly][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-1[disabled][readonly] .md-disabled-thumb, md-slider.md-hue-1[disabled][readonly] .md-disabled-thumb{border-color:transparent;background-color:transparent}.md-subheader.md-default-theme.md-hue-1, .md-subheader.md-hue-1{color:rgba(0,0,0,0.54);background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-1 .md-ink-ripple, md-switch.md-hue-1 .md-ink-ripple{color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-1 .md-thumb, md-switch.md-hue-1 .md-thumb{background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-1 .md-bar, md-switch.md-hue-1 .md-bar{background-color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-1[disabled] .md-thumb, md-switch.md-hue-1[disabled] .md-thumb{background-color:rgb(189,189,189)}md-switch.md-default-theme.md-hue-1[disabled] .md-bar, md-switch.md-hue-1[disabled] .md-bar{background-color:rgba(0,0,0,0.12)}md-tabs.md-default-theme.md-hue-1 md-tabs-wrapper, md-tabs.md-hue-1 md-tabs-wrapper{background-color:transparent;border-color:rgba(0,0,0,0.12)}md-toast.md-default-theme.md-hue-1 .md-toast-content, md-toast.md-hue-1 .md-toast-content{background-color:#323232;color:rgb(250,250,250)}md-toast.md-default-theme.md-hue-1 .md-toast-content .md-button, md-toast.md-hue-1 .md-toast-content .md-button{color:rgb(250,250,250)}.md-panel.md-tooltip.md-default-theme.md-hue-1, .md-panel.md-tooltip.md-hue-1{color:rgba(255,255,255,0.87);background-color:rgb(97,97,97)}body.md-default-theme.md-hue-1, body.md-hue-1,html.md-default-theme.md-hue-1, html.md-hue-1{color:rgba(0,0,0,0.87);background-color:rgb(245,245,245)} -md-autocomplete.md-default-theme.md-hue-2, md-autocomplete.md-hue-2{background:rgb(245,245,245)}md-autocomplete.md-default-theme.md-hue-2[disabled]:not([md-floating-label]), md-autocomplete.md-hue-2[disabled]:not([md-floating-label]){background:rgb(238,238,238)}md-autocomplete.md-default-theme.md-hue-2 button md-icon path, md-autocomplete.md-hue-2 button md-icon path{fill:rgb(117,117,117)}md-autocomplete.md-default-theme.md-hue-2 button:after, md-autocomplete.md-hue-2 button:after{background:rgba(117,117,117,0.3)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-2, .md-autocomplete-suggestions-container.md-hue-2{background:rgb(245,245,245)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-2 li.selected, .md-autocomplete-suggestions-container.md-hue-2 li.selected,.md-autocomplete-suggestions-container.md-default-theme.md-hue-2 li:hover, .md-autocomplete-suggestions-container.md-hue-2 li:hover{background:rgba(158,158,158,0.18)}md-backdrop{background-color:rgba(33,33,33,0.0)}md-backdrop.md-opaque.md-default-theme.md-hue-2, md-backdrop.md-opaque.md-hue-2{background-color:rgba(33,33,33,1.0)}md-bottom-sheet.md-default-theme.md-hue-2, md-bottom-sheet.md-hue-2{background-color:rgb(250,250,250);border-top-color:rgb(224,224,224)}md-bottom-sheet.md-default-theme.md-hue-2 .md-subheader, md-bottom-sheet.md-hue-2 .md-subheader{background-color:rgb(250,250,250);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-2:not([disabled]).md-focused, .md-button.md-hue-2:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-2:not([disabled]):hover, .md-button.md-hue-2:not([disabled]):hover{background-color:rgba(158,158,158,0.2)}.md-button.md-default-theme.md-hue-2:not([disabled]).md-icon-button:hover, .md-button.md-hue-2:not([disabled]).md-icon-button:hover{background-color:transparent}.md-button.md-default-theme.md-hue-2.md-raised, .md-button.md-hue-2.md-raised{color:rgb(33,33,33);background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-2.md-raised:not([disabled]) md-icon, .md-button.md-hue-2.md-raised:not([disabled]) md-icon{color:rgb(33,33,33)}.md-button.md-default-theme.md-hue-2.md-raised:not([disabled]):hover, .md-button.md-hue-2.md-raised:not([disabled]):hover{background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-2.md-raised:not([disabled]).md-focused, .md-button.md-hue-2.md-raised:not([disabled]).md-focused{background-color:rgb(238,238,238)}.md-button.md-default-theme.md-hue-2.md-fab[disabled], .md-button.md-hue-2.md-fab[disabled],.md-button.md-default-theme.md-hue-2.md-raised[disabled], .md-button.md-hue-2.md-raised[disabled]{background-color:rgba(0,0,0,0.12)}.md-button.md-default-theme.md-hue-2[disabled], .md-button.md-hue-2[disabled]{background-color:transparent}md-card.md-default-theme.md-hue-2, md-card.md-hue-2{color:rgba(0,0,0,0.87);background-color:rgb(245,245,245);border-radius:2px}md-card.md-default-theme.md-hue-2 md-card-header md-card-avatar md-icon, md-card.md-hue-2 md-card-header md-card-avatar md-icon{color:rgb(238,238,238);background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-2.md-checked .md-ripple, md-checkbox.md-hue-2.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-2[disabled].md-checked .md-icon, md-checkbox.md-hue-2[disabled].md-checked .md-icon{background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-2[disabled].md-checked .md-icon:after, md-checkbox.md-hue-2[disabled].md-checked .md-icon:after{border-color:rgb(238,238,238)}md-chips.md-default-theme.md-hue-2 md-chip, md-chips.md-hue-2 md-chip{background:rgb(224,224,224);color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-2 md-chip md-icon, md-chips.md-hue-2 md-chip md-icon{color:rgb(97,97,97)}md-chips.md-default-theme.md-hue-2 md-chip._md-chip-editing, md-chips.md-hue-2 md-chip._md-chip-editing{background:transparent;color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-2 md-chip-remove .md-button md-icon path, md-chips.md-hue-2 md-chip-remove .md-button md-icon path{fill:rgb(158,158,158)}.md-contact-suggestion span.md-contact-email{color:rgb(189,189,189)}md-content.md-default-theme.md-hue-2, md-content.md-hue-2{color:rgba(0,0,0,0.87);background-color:rgb(250,250,250)}.md-default-theme.md-hue-2 .md-calendar, .md-hue-2 .md-calendar{background:rgb(245,245,245);color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-2 .md-calendar tr:last-child td, .md-hue-2 .md-calendar tr:last-child td{border-bottom-color:rgb(238,238,238)}.md-default-theme.md-hue-2 .md-calendar-day-header, .md-hue-2 .md-calendar-day-header{background:rgba(158,158,158,0.32);color:rgba(0,0,0,0.87)}.md-calendar-date.md-focus .md-default-theme.md-hue-2 .md-calendar-date-selection-indicator, .md-calendar-date.md-focus .md-hue-2 .md-calendar-date-selection-indicator,.md-default-theme.md-hue-2 .md-calendar-date-selection-indicator:hover, .md-hue-2 .md-calendar-date-selection-indicator:hover{background:rgba(158,158,158,0.32)}.md-default-theme.md-hue-2 .md-datepicker-calendar-pane, .md-hue-2 .md-datepicker-calendar-pane{border-color:rgb(245,245,245)}.md-default-theme.md-hue-2 .md-datepicker-calendar, .md-hue-2 .md-datepicker-calendar{background:rgb(245,245,245)}.md-default-theme.md-hue-2 .md-datepicker-input-mask-opaque, .md-hue-2 .md-datepicker-input-mask-opaque{box-shadow:0 0 0 9999px rgb(245,245,245)}.md-default-theme.md-hue-2 .md-datepicker-open .md-datepicker-input-container, .md-hue-2 .md-datepicker-open .md-datepicker-input-container{background:rgb(245,245,245)}md-dialog.md-default-theme.md-hue-2, md-dialog.md-hue-2{border-radius:4px;background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}[disabled] md-input-container.md-default-theme.md-hue-2 .md-input, [disabled] md-input-container.md-hue-2 .md-input,md-input-container.md-default-theme.md-hue-2 .md-input[disabled], md-input-container.md-hue-2 .md-input[disabled]{border-bottom-color:transparent;color:rgba(0,0,0,0.38);background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-list.md-default-theme.md-hue-2 .md-proxy-focus.md-focused div.md-no-style, md-list.md-hue-2 .md-proxy-focus.md-focused div.md-no-style{background-color:rgb(245,245,245)}md-list.md-default-theme.md-hue-2 md-list-item .md-avatar-icon, md-list.md-hue-2 md-list-item .md-avatar-icon{background-color:rgba(0,0,0,0.38);color:rgb(238,238,238)}md-menu-content.md-default-theme.md-hue-2, md-menu-content.md-hue-2{background-color:rgb(245,245,245)}md-menu-content.md-default-theme.md-hue-2 md-menu-divider, md-menu-content.md-hue-2 md-menu-divider{background-color:rgba(0,0,0,0.12)}md-menu-bar.md-default-theme.md-hue-2 md-menu.md-open>button, md-menu-bar.md-hue-2 md-menu.md-open>button,md-menu-bar.md-default-theme.md-hue-2 md-menu>button:focus, md-menu-bar.md-hue-2 md-menu>button:focus{outline:none;background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-2.md-open:not(.md-keyboard-mode) md-menu:hover>button, md-menu-bar.md-hue-2.md-open:not(.md-keyboard-mode) md-menu:hover>button{background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-2:not(.md-keyboard-mode):not(.md-open) md-menu button:focus, md-menu-bar.md-hue-2:not(.md-keyboard-mode):not(.md-open) md-menu button:focus,md-menu-bar.md-default-theme.md-hue-2:not(.md-keyboard-mode):not(.md-open) md-menu button:hover, md-menu-bar.md-hue-2:not(.md-keyboard-mode):not(.md-open) md-menu button:hover{background:transparent}md-menu-content.md-default-theme.md-hue-2 .md-menu.md-open>.md-button, md-menu-content.md-hue-2 .md-menu.md-open>.md-button{background-color:rgba(158,158,158,0.18)}md-toolbar.md-default-theme.md-hue-2.md-menu-toolbar, md-toolbar.md-hue-2.md-menu-toolbar{background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-2 .md-nav-bar, md-nav-bar.md-hue-2 .md-nav-bar{background-color:transparent;border-color:rgba(0,0,0,0.12)}._md-panel-backdrop.md-default-theme.md-hue-2, ._md-panel-backdrop.md-hue-2{background-color:rgba(33,33,33,1.0)}md-select.md-default-theme.md-hue-2[disabled] .md-select-value, md-select.md-hue-2[disabled] .md-select-value{border-bottom-color:transparent;background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-select-menu.md-default-theme.md-hue-2 md-content, md-select-menu.md-hue-2 md-content{background-color:rgb(245,245,245)}md-select-menu.md-default-theme.md-hue-2 md-content md-option:not([disabled]):focus, md-select-menu.md-hue-2 md-content md-option:not([disabled]):focus,md-select-menu.md-default-theme.md-hue-2 md-content md-option:not([disabled]):hover, md-select-menu.md-hue-2 md-content md-option:not([disabled]):hover{background-color:rgba(158,158,158,0.18)}.md-checkbox-enabled.md-default-theme.md-hue-2[selected] .md-ripple, .md-checkbox-enabled.md-hue-2[selected] .md-ripple{color:rgb(117,117,117)}md-sidenav.md-default-theme.md-hue-2, md-sidenav.md-hue-2,md-sidenav.md-default-theme.md-hue-2 md-content, md-sidenav.md-hue-2 md-content{background-color:rgb(245,245,245)}md-slider.md-default-theme.md-hue-2 .md-track, md-slider.md-hue-2 .md-track{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-2 .md-track-ticks, md-slider.md-hue-2 .md-track-ticks{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-2 .md-disabled-thumb, md-slider.md-hue-2 .md-disabled-thumb{border-color:rgb(238,238,238);background-color:rgb(238,238,238)}md-slider.md-default-theme.md-hue-2.md-min .md-thumb:after, md-slider.md-hue-2.md-min .md-thumb:after{background-color:rgb(238,238,238);border-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-2.md-min .md-focus-ring, md-slider.md-hue-2.md-min .md-focus-ring{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-2.md-min[md-discrete] .md-thumb:after, md-slider.md-hue-2.md-min[md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.87);border-color:transparent}md-slider.md-default-theme.md-hue-2.md-min[md-discrete] .md-sign, md-slider.md-hue-2.md-min[md-discrete] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2.md-min[md-discrete] .md-sign:after, md-slider.md-hue-2.md-min[md-discrete] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2.md-min[md-discrete][md-vertical] .md-sign:after, md-slider.md-hue-2.md-min[md-discrete][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2[disabled]:not(.md-min) .md-thumb:after, md-slider.md-hue-2[disabled]:not(.md-min) .md-thumb:after,md-slider.md-default-theme.md-hue-2[disabled][md-discrete] .md-thumb:after, md-slider.md-hue-2[disabled][md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.38);border-color:transparent}md-slider.md-default-theme.md-hue-2[disabled][readonly] .md-sign, md-slider.md-hue-2[disabled][readonly] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2[disabled][readonly] .md-sign:after, md-slider.md-hue-2[disabled][readonly] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2[disabled][readonly][md-vertical] .md-sign:after, md-slider.md-hue-2[disabled][readonly][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-2[disabled][readonly] .md-disabled-thumb, md-slider.md-hue-2[disabled][readonly] .md-disabled-thumb{border-color:transparent;background-color:transparent}.md-subheader.md-default-theme.md-hue-2, .md-subheader.md-hue-2{color:rgba(0,0,0,0.54);background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-2 .md-ink-ripple, md-switch.md-hue-2 .md-ink-ripple{color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-2 .md-thumb, md-switch.md-hue-2 .md-thumb{background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-2 .md-bar, md-switch.md-hue-2 .md-bar{background-color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-2[disabled] .md-thumb, md-switch.md-hue-2[disabled] .md-thumb{background-color:rgb(189,189,189)}md-switch.md-default-theme.md-hue-2[disabled] .md-bar, md-switch.md-hue-2[disabled] .md-bar{background-color:rgba(0,0,0,0.12)}md-tabs.md-default-theme.md-hue-2 md-tabs-wrapper, md-tabs.md-hue-2 md-tabs-wrapper{background-color:transparent;border-color:rgba(0,0,0,0.12)}md-toast.md-default-theme.md-hue-2 .md-toast-content, md-toast.md-hue-2 .md-toast-content{background-color:#323232;color:rgb(250,250,250)}md-toast.md-default-theme.md-hue-2 .md-toast-content .md-button, md-toast.md-hue-2 .md-toast-content .md-button{color:rgb(250,250,250)}.md-panel.md-tooltip.md-default-theme.md-hue-2, .md-panel.md-tooltip.md-hue-2{color:rgba(255,255,255,0.87);background-color:rgb(97,97,97)}body.md-default-theme.md-hue-2, body.md-hue-2,html.md-default-theme.md-hue-2, html.md-hue-2{color:rgba(0,0,0,0.87);background-color:rgb(238,238,238)} -md-autocomplete.md-default-theme.md-hue-3, md-autocomplete.md-hue-3{background:rgb(245,245,245)}md-autocomplete.md-default-theme.md-hue-3[disabled]:not([md-floating-label]), md-autocomplete.md-hue-3[disabled]:not([md-floating-label]){background:rgb(238,238,238)}md-autocomplete.md-default-theme.md-hue-3 button md-icon path, md-autocomplete.md-hue-3 button md-icon path{fill:rgb(117,117,117)}md-autocomplete.md-default-theme.md-hue-3 button:after, md-autocomplete.md-hue-3 button:after{background:rgba(117,117,117,0.3)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-3, .md-autocomplete-suggestions-container.md-hue-3{background:rgb(245,245,245)}.md-autocomplete-suggestions-container.md-default-theme.md-hue-3 li.selected, .md-autocomplete-suggestions-container.md-hue-3 li.selected,.md-autocomplete-suggestions-container.md-default-theme.md-hue-3 li:hover, .md-autocomplete-suggestions-container.md-hue-3 li:hover{background:rgba(158,158,158,0.18)}md-backdrop{background-color:rgba(33,33,33,0.0)}md-backdrop.md-opaque.md-default-theme.md-hue-3, md-backdrop.md-opaque.md-hue-3{background-color:rgba(33,33,33,1.0)}md-bottom-sheet.md-default-theme.md-hue-3, md-bottom-sheet.md-hue-3{background-color:rgb(250,250,250);border-top-color:rgb(224,224,224)}md-bottom-sheet.md-default-theme.md-hue-3 .md-subheader, md-bottom-sheet.md-hue-3 .md-subheader{background-color:rgb(250,250,250);color:rgba(0,0,0,0.87)}.md-button.md-default-theme.md-hue-3:not([disabled]).md-focused, .md-button.md-hue-3:not([disabled]).md-focused,.md-button.md-default-theme.md-hue-3:not([disabled]):hover, .md-button.md-hue-3:not([disabled]):hover{background-color:rgba(158,158,158,0.2)}.md-button.md-default-theme.md-hue-3:not([disabled]).md-icon-button:hover, .md-button.md-hue-3:not([disabled]).md-icon-button:hover{background-color:transparent}.md-button.md-default-theme.md-hue-3.md-raised, .md-button.md-hue-3.md-raised{color:rgb(33,33,33);background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-3.md-raised:not([disabled]) md-icon, .md-button.md-hue-3.md-raised:not([disabled]) md-icon{color:rgb(33,33,33)}.md-button.md-default-theme.md-hue-3.md-raised:not([disabled]):hover, .md-button.md-hue-3.md-raised:not([disabled]):hover{background-color:rgb(250,250,250)}.md-button.md-default-theme.md-hue-3.md-raised:not([disabled]).md-focused, .md-button.md-hue-3.md-raised:not([disabled]).md-focused{background-color:rgb(238,238,238)}.md-button.md-default-theme.md-hue-3.md-fab[disabled], .md-button.md-hue-3.md-fab[disabled],.md-button.md-default-theme.md-hue-3.md-raised[disabled], .md-button.md-hue-3.md-raised[disabled]{background-color:rgba(0,0,0,0.12)}.md-button.md-default-theme.md-hue-3[disabled], .md-button.md-hue-3[disabled]{background-color:transparent}md-card.md-default-theme.md-hue-3, md-card.md-hue-3{color:rgba(0,0,0,0.87);background-color:rgb(245,245,245);border-radius:2px}md-card.md-default-theme.md-hue-3 md-card-header md-card-avatar md-icon, md-card.md-hue-3 md-card-header md-card-avatar md-icon{color:rgb(224,224,224);background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-3.md-checked .md-ripple, md-checkbox.md-hue-3.md-checked .md-ripple{color:rgb(117,117,117)}md-checkbox.md-default-theme.md-hue-3[disabled].md-checked .md-icon, md-checkbox.md-hue-3[disabled].md-checked .md-icon{background-color:rgba(0,0,0,0.38)}md-checkbox.md-default-theme.md-hue-3[disabled].md-checked .md-icon:after, md-checkbox.md-hue-3[disabled].md-checked .md-icon:after{border-color:rgb(238,238,238)}md-chips.md-default-theme.md-hue-3 md-chip, md-chips.md-hue-3 md-chip{background:rgb(224,224,224);color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-3 md-chip md-icon, md-chips.md-hue-3 md-chip md-icon{color:rgb(97,97,97)}md-chips.md-default-theme.md-hue-3 md-chip._md-chip-editing, md-chips.md-hue-3 md-chip._md-chip-editing{background:transparent;color:rgb(66,66,66)}md-chips.md-default-theme.md-hue-3 md-chip-remove .md-button md-icon path, md-chips.md-hue-3 md-chip-remove .md-button md-icon path{fill:rgb(158,158,158)}.md-contact-suggestion span.md-contact-email{color:rgb(189,189,189)}md-content.md-default-theme.md-hue-3, md-content.md-hue-3{color:rgba(0,0,0,0.87);background-color:rgb(250,250,250)}.md-default-theme.md-hue-3 .md-calendar, .md-hue-3 .md-calendar{background:rgb(245,245,245);color:rgba(0,0,0,0.87)}.md-default-theme.md-hue-3 .md-calendar tr:last-child td, .md-hue-3 .md-calendar tr:last-child td{border-bottom-color:rgb(238,238,238)}.md-default-theme.md-hue-3 .md-calendar-day-header, .md-hue-3 .md-calendar-day-header{background:rgba(158,158,158,0.32);color:rgba(0,0,0,0.87)}.md-calendar-date.md-focus .md-default-theme.md-hue-3 .md-calendar-date-selection-indicator, .md-calendar-date.md-focus .md-hue-3 .md-calendar-date-selection-indicator,.md-default-theme.md-hue-3 .md-calendar-date-selection-indicator:hover, .md-hue-3 .md-calendar-date-selection-indicator:hover{background:rgba(158,158,158,0.32)}.md-default-theme.md-hue-3 .md-datepicker-calendar-pane, .md-hue-3 .md-datepicker-calendar-pane{border-color:rgb(245,245,245)}.md-default-theme.md-hue-3 .md-datepicker-calendar, .md-hue-3 .md-datepicker-calendar{background:rgb(245,245,245)}.md-default-theme.md-hue-3 .md-datepicker-input-mask-opaque, .md-hue-3 .md-datepicker-input-mask-opaque{box-shadow:0 0 0 9999px rgb(245,245,245)}.md-default-theme.md-hue-3 .md-datepicker-open .md-datepicker-input-container, .md-hue-3 .md-datepicker-open .md-datepicker-input-container{background:rgb(245,245,245)}md-dialog.md-default-theme.md-hue-3, md-dialog.md-hue-3{border-radius:4px;background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}[disabled] md-input-container.md-default-theme.md-hue-3 .md-input, [disabled] md-input-container.md-hue-3 .md-input,md-input-container.md-default-theme.md-hue-3 .md-input[disabled], md-input-container.md-hue-3 .md-input[disabled]{border-bottom-color:transparent;color:rgba(0,0,0,0.38);background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-list.md-default-theme.md-hue-3 .md-proxy-focus.md-focused div.md-no-style, md-list.md-hue-3 .md-proxy-focus.md-focused div.md-no-style{background-color:rgb(245,245,245)}md-list.md-default-theme.md-hue-3 md-list-item .md-avatar-icon, md-list.md-hue-3 md-list-item .md-avatar-icon{background-color:rgba(0,0,0,0.38);color:rgb(224,224,224)}md-menu-content.md-default-theme.md-hue-3, md-menu-content.md-hue-3{background-color:rgb(245,245,245)}md-menu-content.md-default-theme.md-hue-3 md-menu-divider, md-menu-content.md-hue-3 md-menu-divider{background-color:rgba(0,0,0,0.12)}md-menu-bar.md-default-theme.md-hue-3 md-menu.md-open>button, md-menu-bar.md-hue-3 md-menu.md-open>button,md-menu-bar.md-default-theme.md-hue-3 md-menu>button:focus, md-menu-bar.md-hue-3 md-menu>button:focus{outline:none;background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-3.md-open:not(.md-keyboard-mode) md-menu:hover>button, md-menu-bar.md-hue-3.md-open:not(.md-keyboard-mode) md-menu:hover>button{background-color:rgba(158,158,158,0.18)}md-menu-bar.md-default-theme.md-hue-3:not(.md-keyboard-mode):not(.md-open) md-menu button:focus, md-menu-bar.md-hue-3:not(.md-keyboard-mode):not(.md-open) md-menu button:focus,md-menu-bar.md-default-theme.md-hue-3:not(.md-keyboard-mode):not(.md-open) md-menu button:hover, md-menu-bar.md-hue-3:not(.md-keyboard-mode):not(.md-open) md-menu button:hover{background:transparent}md-menu-content.md-default-theme.md-hue-3 .md-menu.md-open>.md-button, md-menu-content.md-hue-3 .md-menu.md-open>.md-button{background-color:rgba(158,158,158,0.18)}md-toolbar.md-default-theme.md-hue-3.md-menu-toolbar, md-toolbar.md-hue-3.md-menu-toolbar{background-color:rgb(245,245,245);color:rgba(0,0,0,0.87)}md-nav-bar.md-default-theme.md-hue-3 .md-nav-bar, md-nav-bar.md-hue-3 .md-nav-bar{background-color:transparent;border-color:rgba(0,0,0,0.12)}._md-panel-backdrop.md-default-theme.md-hue-3, ._md-panel-backdrop.md-hue-3{background-color:rgba(33,33,33,1.0)}md-select.md-default-theme.md-hue-3[disabled] .md-select-value, md-select.md-hue-3[disabled] .md-select-value{border-bottom-color:transparent;background-image:linear-gradient(90deg,rgba(0,0,0,0.38) 0,rgba(0,0,0,0.38) 33%,transparent 0);background-image:-ms-linear-gradient(left,transparent 0,rgba(0,0,0,0.38) 100%)}md-select-menu.md-default-theme.md-hue-3 md-content, md-select-menu.md-hue-3 md-content{background-color:rgb(245,245,245)}md-select-menu.md-default-theme.md-hue-3 md-content md-option:not([disabled]):focus, md-select-menu.md-hue-3 md-content md-option:not([disabled]):focus,md-select-menu.md-default-theme.md-hue-3 md-content md-option:not([disabled]):hover, md-select-menu.md-hue-3 md-content md-option:not([disabled]):hover{background-color:rgba(158,158,158,0.18)}.md-checkbox-enabled.md-default-theme.md-hue-3[selected] .md-ripple, .md-checkbox-enabled.md-hue-3[selected] .md-ripple{color:rgb(117,117,117)}md-sidenav.md-default-theme.md-hue-3, md-sidenav.md-hue-3,md-sidenav.md-default-theme.md-hue-3 md-content, md-sidenav.md-hue-3 md-content{background-color:rgb(245,245,245)}md-slider.md-default-theme.md-hue-3 .md-track, md-slider.md-hue-3 .md-track{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-3 .md-track-ticks, md-slider.md-hue-3 .md-track-ticks{color:rgba(0,0,0,0.87)}md-slider.md-default-theme.md-hue-3 .md-disabled-thumb, md-slider.md-hue-3 .md-disabled-thumb{border-color:rgb(224,224,224);background-color:rgb(224,224,224)}md-slider.md-default-theme.md-hue-3.md-min .md-thumb:after, md-slider.md-hue-3.md-min .md-thumb:after{background-color:rgb(224,224,224);border-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-3.md-min .md-focus-ring, md-slider.md-hue-3.md-min .md-focus-ring{background-color:rgba(0,0,0,0.38)}md-slider.md-default-theme.md-hue-3.md-min[md-discrete] .md-thumb:after, md-slider.md-hue-3.md-min[md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.87);border-color:transparent}md-slider.md-default-theme.md-hue-3.md-min[md-discrete] .md-sign, md-slider.md-hue-3.md-min[md-discrete] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3.md-min[md-discrete] .md-sign:after, md-slider.md-hue-3.md-min[md-discrete] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3.md-min[md-discrete][md-vertical] .md-sign:after, md-slider.md-hue-3.md-min[md-discrete][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3[disabled]:not(.md-min) .md-thumb:after, md-slider.md-hue-3[disabled]:not(.md-min) .md-thumb:after,md-slider.md-default-theme.md-hue-3[disabled][md-discrete] .md-thumb:after, md-slider.md-hue-3[disabled][md-discrete] .md-thumb:after{background-color:rgba(0,0,0,0.38);border-color:transparent}md-slider.md-default-theme.md-hue-3[disabled][readonly] .md-sign, md-slider.md-hue-3[disabled][readonly] .md-sign{background-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3[disabled][readonly] .md-sign:after, md-slider.md-hue-3[disabled][readonly] .md-sign:after{border-top-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3[disabled][readonly][md-vertical] .md-sign:after, md-slider.md-hue-3[disabled][readonly][md-vertical] .md-sign:after{border-top-color:transparent;border-left-color:rgb(189,189,189)}md-slider.md-default-theme.md-hue-3[disabled][readonly] .md-disabled-thumb, md-slider.md-hue-3[disabled][readonly] .md-disabled-thumb{border-color:transparent;background-color:transparent}.md-subheader.md-default-theme.md-hue-3, .md-subheader.md-hue-3{color:rgba(0,0,0,0.54);background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-3 .md-ink-ripple, md-switch.md-hue-3 .md-ink-ripple{color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-3 .md-thumb, md-switch.md-hue-3 .md-thumb{background-color:rgb(250,250,250)}md-switch.md-default-theme.md-hue-3 .md-bar, md-switch.md-hue-3 .md-bar{background-color:rgb(158,158,158)}md-switch.md-default-theme.md-hue-3[disabled] .md-thumb, md-switch.md-hue-3[disabled] .md-thumb{background-color:rgb(189,189,189)}md-switch.md-default-theme.md-hue-3[disabled] .md-bar, md-switch.md-hue-3[disabled] .md-bar{background-color:rgba(0,0,0,0.12)}md-tabs.md-default-theme.md-hue-3 md-tabs-wrapper, md-tabs.md-hue-3 md-tabs-wrapper{background-color:transparent;border-color:rgba(0,0,0,0.12)}md-toast.md-default-theme.md-hue-3 .md-toast-content, md-toast.md-hue-3 .md-toast-content{background-color:#323232;color:rgb(250,250,250)}md-toast.md-default-theme.md-hue-3 .md-toast-content .md-button, md-toast.md-hue-3 .md-toast-content .md-button{color:rgb(250,250,250)}.md-panel.md-tooltip.md-default-theme.md-hue-3, .md-panel.md-tooltip.md-hue-3{color:rgba(255,255,255,0.87);background-color:rgb(97,97,97)}body.md-default-theme.md-hue-3, body.md-hue-3,html.md-default-theme.md-hue-3, html.md-hue-3{color:rgba(0,0,0,0.87);background-color:rgb(224,224,224)} \ No newline at end of file diff --git a/data/Dockerfiles/sogo/theme-blue.js b/data/Dockerfiles/sogo/theme-blue.js deleted file mode 100644 index 865443f9..00000000 --- a/data/Dockerfiles/sogo/theme-blue.js +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - -(function() { - 'use strict'; - - angular.module('SOGo.Common') - .config(configure) - - /** - * @ngInject - */ - configure.$inject = ['$mdThemingProvider']; - function configure($mdThemingProvider) { - - // Overwrite values to prevent flipping colors on login screen - $mdThemingProvider.definePalette('mailcow-blue', { - '50': 'E3F2FD', - '100': 'BBDEFB', - '200': '90CAF9', - '300': '64B5F6', - '400': '42A5F5', - '500': '2196F3', - '600': '1E88E5', - '700': '1976D2', - '800': '1565C0', - '900': '0D47A1', - '1000': '0D47A1', - 'A100': '82B1FF', - 'A200': '448AFF', - 'A400': '2979ff', - 'A700': '2962ff', - 'contrastDefaultColor': 'dark', - 'contrastLightColors': ['700', '800', '900'], - 'contrastDarkColors': undefined - }); - - $mdThemingProvider.definePalette('sogo-green', { - '50': 'E3F2FD', - '100': 'BBDEFB', - '200': '90CAF9', - '300': '64B5F6', - '400': '42A5F5', - '500': '2196F3', - '600': '1E88E5', - '700': '1976D2', - '800': '1565C0', - '900': '0D47A1', - '1000': '0D47A1', - 'A100': '82B1FF', - 'A200': '448AFF', - 'A400': '2979ff', - 'A700': '2962ff', - 'contrastDefaultColor': 'dark', - 'contrastLightColors': ['700', '800', '900'], - 'contrastDarkColors': undefined - }); - - $mdThemingProvider.definePalette('default', { - '50': 'E3F2FD', - '100': 'BBDEFB', - '200': '90CAF9', - '300': '64B5F6', - '400': '42A5F5', - '500': '2196F3', - '600': '1E88E5', - '700': '1976D2', - '800': '1565C0', - '900': '0D47A1', - '1000': '0D47A1', - 'A100': '82B1FF', - 'A200': '448AFF', - 'A400': '2979ff', - 'A700': '2962ff', - 'contrastDefaultColor': 'dark', - 'contrastLightColors': ['700', '800', '900'], - 'contrastDarkColors': undefined - }); - - $mdThemingProvider.theme('default') - .primaryPalette('mailcow-blue', { - 'default': '700', // top toolbar - 'hue-1': '500', - 'hue-2': '700', // sidebar toolbar - 'hue-3': 'A200' - }) - .accentPalette('mailcow-blue', { - 'default': '800', // fab buttons - 'hue-1': '50', // center list toolbar - 'hue-2': '500', - 'hue-3': 'A700' - }) - .backgroundPalette('grey', { - 'default': '50', // center list background - 'hue-1': '100', - 'hue-2': '200', - 'hue-3': '300' - }); - - $mdThemingProvider.setDefaultTheme('default'); - $mdThemingProvider.generateThemesOnDemand(false); - $mdThemingProvider.alwaysWatchTheme(true); - } -})(); diff --git a/data/Dockerfiles/solr/Dockerfile b/data/Dockerfiles/solr/Dockerfile new file mode 100644 index 00000000..eae8f55a --- /dev/null +++ b/data/Dockerfiles/solr/Dockerfile @@ -0,0 +1,13 @@ +FROM solr:7.7-alpine +USER root +COPY docker-entrypoint.sh / +COPY solr-config-7.7.0.xml / +COPY solr-schema-7.7.0.xml / + + +RUN apk --no-cache add su-exec curl tzdata \ + && chmod +x /docker-entrypoint.sh \ + && sync \ + && bash /docker-entrypoint.sh --bootstrap + +ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/data/Dockerfiles/solr/docker-entrypoint.sh b/data/Dockerfiles/solr/docker-entrypoint.sh new file mode 100755 index 00000000..5a33620d --- /dev/null +++ b/data/Dockerfiles/solr/docker-entrypoint.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + echo "SKIP_SOLR=y, skipping Solr..." + sleep 365d + exit 0 +fi + +MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo) + +if [[ "${1}" != "--bootstrap" ]]; then + if [ ${MEM_TOTAL} -lt "2097152" ]; then + echo "System memory less than 2 GB, skipping Solr..." + sleep 365d + exit 0 + fi +fi + +set -e + +# run the optional initdb +. /opt/docker-solr/scripts/run-initdb + +# fixing volume permission +[[ -d /opt/solr/server/solr/dovecot-fts/data ]] && chown -R solr:solr /opt/solr/server/solr/dovecot-fts/data +if [[ "${1}" != "--bootstrap" ]]; then + sed -i '/SOLR_HEAP=/c\SOLR_HEAP="'${SOLR_HEAP:-1024}'m"' /opt/solr/bin/solr.in.sh +else + sed -i '/SOLR_HEAP=/c\SOLR_HEAP="256m"' /opt/solr/bin/solr.in.sh +fi + +if [[ "${1}" == "--bootstrap" ]]; then + echo "Creating initial configuration" + echo "Modifying default config set" + cp /solr-config-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml + cp /solr-schema-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/schema.xml + rm /opt/solr/server/solr/configsets/_default/conf/managed-schema + + echo "Starting local Solr instance to setup configuration" + su-exec solr start-local-solr + + echo "Creating core \"dovecot-fts\"" + su-exec solr /opt/solr/bin/solr create -c "dovecot-fts" + + # See https://github.com/docker-solr/docker-solr/issues/27 + echo "Checking core" + while ! wget -O - 'http://localhost:8983/solr/admin/cores?action=STATUS' | grep -q instanceDir; do + echo "Could not find any cores, waiting..." + sleep 3 + done + + echo "Created core \"dovecot-fts\"" + + echo "Stopping local Solr" + su-exec solr stop-local-solr + + exit 0 +fi + +exec su-exec solr solr-foreground + diff --git a/data/Dockerfiles/solr/solr-config-7.7.0.xml b/data/Dockerfiles/solr/solr-config-7.7.0.xml new file mode 100644 index 00000000..3661874d --- /dev/null +++ b/data/Dockerfiles/solr/solr-config-7.7.0.xml @@ -0,0 +1,289 @@ + + + + + + + 7.7.0 + + + + + + + + + + + + + + + + ${solr.data.dir:} + + + + + + + ${solr.ulog.dir:} + ${solr.ulog.numVersionBuckets:65536} + + + + + ${solr.autoCommit.maxTime:15000} + false + + + + + ${solr.autoSoftCommit.maxTime:-1} + + + + + + + + + + + + + + + + + + + + + + + + true + + + 20 + + + 200 + + + false + + + + + + + + + + + + + + + explicit + 10 + + + + + + _text_ + + + + + + diff --git a/data/Dockerfiles/solr/solr-schema-7.7.0.xml b/data/Dockerfiles/solr/solr-schema-7.7.0.xml new file mode 100644 index 00000000..2c2e6343 --- /dev/null +++ b/data/Dockerfiles/solr/solr-schema-7.7.0.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile index 72e86bc0..7658a8f8 100644 --- a/data/Dockerfiles/unbound/Dockerfile +++ b/data/Dockerfiles/unbound/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.6 +FROM alpine:3.9 LABEL maintainer "Andre Peters " @@ -8,8 +8,10 @@ RUN apk add --update --no-cache \ bash \ openssl \ drill \ + tzdata \ && curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \ && chown root:unbound /etc/unbound \ + && adduser unbound tty \ && chmod 775 /etc/unbound EXPOSE 53/udp 53/tcp diff --git a/data/Dockerfiles/unbound/docker-entrypoint.sh b/data/Dockerfiles/unbound/docker-entrypoint.sh index b458cd8a..d179eaca 100755 --- a/data/Dockerfiles/unbound/docker-entrypoint.sh +++ b/data/Dockerfiles/unbound/docker-entrypoint.sh @@ -1,8 +1,11 @@ #!/bin/bash +echo "Setting console permissions..." +chown root:tty /dev/console +chmod g+rw /dev/console echo "Receiving anchor key..." /usr/sbin/unbound-anchor -a /etc/unbound/trusted-key.key echo "Receiving root hints..." curl -#o /etc/unbound/root.hints https://www.internic.net/domain/named.cache - +/usr/sbin/unbound-control-setup exec "$@" diff --git a/data/Dockerfiles/watchdog/Dockerfile b/data/Dockerfiles/watchdog/Dockerfile index 46130e5f..7ab29b68 100644 --- a/data/Dockerfiles/watchdog/Dockerfile +++ b/data/Dockerfiles/watchdog/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.6 +FROM alpine:3.9 LABEL maintainer "Andrรฉ Peters " # Installation @@ -9,6 +9,7 @@ RUN apk add --update \ nagios-plugins-ping \ curl \ bash \ + coreutils \ jq \ fcgi \ nagios-plugins-mysql \ diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index c06abbc2..f56d3c4c 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -5,6 +5,8 @@ trap "kill 0" EXIT # Prepare BACKGROUND_TASKS=() +echo "Waiting for containers to settle..." +sleep 10 if [[ "${USE_WATCHDOG}" =~ ^([nN][oO]|[nN])+$ ]]; then echo -e "$(date) - USE_WATCHDOG=n, skipping watchdog..." @@ -30,65 +32,84 @@ progress() { PERCENT=$(( 200 * ${CURRENT} / ${TOTAL} % 2 + 100 * ${CURRENT} / ${TOTAL} )) redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"service\":\"${SERVICE}\",\"lvl\":\"${PERCENT}\",\"hpnow\":\"${CURRENT}\",\"hptotal\":\"${TOTAL}\",\"hpdiff\":\"${DIFF}\"}" > /dev/null log_msg "${SERVICE} health level: ${PERCENT}% (${CURRENT}/${TOTAL}), health trend: ${DIFF}" no_redis + # Return 10 to indicate a dead service + [ ${CURRENT} -le 0 ] && return 10 } log_msg() { if [[ ${2} != "no_redis" ]]; then redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}" | \ - tr '%&;$"_[]{}-\r\n' ' ')\"}" > /dev/null + tr '\r\n%&;$"_[]{}-' ' ')\"}" > /dev/null fi echo $(date) $(printf '%s\n' "${1}") } function mail_error() { [[ -z ${1} ]] && return 1 - [[ -z ${2} ]] && return 2 - RCPT_DOMAIN=$(echo ${1} | awk -F @ {'print $NF'}) - RCPT_MX=$(dig +short ${RCPT_DOMAIN} mx | sort -n | awk '{print $2; exit}') - if [[ -z ${RCPT_MX} ]]; then - log_msg "Cannot determine MX for ${1}, skipping email notification..." - return 1 - fi - ./smtp-cli --missing-modules-ok \ - --subject="Watchdog: ${2} service hit the error rate limit" \ - --body-plain="Service was restarted, please check your mailcow installation." \ - --to=${1} \ - --from="watchdog@${MAILCOW_HOSTNAME}" \ - --server="${RCPT_MX}" \ - --hello-host=${MAILCOW_HOSTNAME} - log_msg "Sent notification email to ${1}" + [[ -z ${2} ]] && BODY="Service was restarted on $(date), please check your mailcow installation." || BODY="$(date) - ${2}" + WATCHDOG_NOTIFY_EMAIL=$(echo "${WATCHDOG_NOTIFY_EMAIL}" | sed 's/"//;s|"$||') + IFS=',' read -r -a MAIL_RCPTS <<< "${WATCHDOG_NOTIFY_EMAIL}" + for rcpt in "${MAIL_RCPTS[@]}"; do + RCPT_DOMAIN= + RCPT_MX= + RCPT_DOMAIN=$(echo ${rcpt} | awk -F @ {'print $NF'}) + RCPT_MX=$(dig +short ${RCPT_DOMAIN} mx | sort -n | awk '{print $2; exit}') + if [[ -z ${RCPT_MX} ]]; then + log_msg "Cannot determine MX for ${rcpt}, skipping email notification..." + return 1 + fi + [ -f "/tmp/${1}" ] && ATTACH="--attach /tmp/${1}@text/plain" || ATTACH= + ./smtp-cli --missing-modules-ok \ + --subject="Watchdog: ${1} hit the error rate limit" \ + --body-plain="${BODY}" \ + --to=${rcpt} \ + --from="watchdog@${MAILCOW_HOSTNAME}" \ + --server="${RCPT_MX}" \ + --hello-host=${MAILCOW_HOSTNAME} \ + ${ATTACH} + log_msg "Sent notification email to ${rcpt}" + done } - get_container_ip() { # ${1} is container CONTAINER_ID=() + CONTAINER_IPS=() CONTAINER_IP= LOOP_C=1 until [[ ${CONTAINER_IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ ${LOOP_C} -gt 5 ]]; do - sleep 0.5 - # get long container id for exact match - CONTAINER_ID=($(curl --silent http://dockerapi:8080/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | .id")) - # returned id can have multiple elements (if scaled), shuffle for random test - CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) - if [[ ! -z ${CONTAINER_ID} ]]; then - for matched_container in "${CONTAINER_ID[@]}"; do - CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress') - # grep will do nothing if one of these vars is empty - [[ -z ${CONTAINER_IP} ]] && continue - [[ -z ${IPV4_NETWORK} ]] && continue - # only return ips that are part of our network - if ! grep -q ${IPV4_NETWORK} <(echo ${CONTAINER_IP}); then - CONTAINER_IP= - fi - done + if [ ${IP_BY_DOCKER_API} -eq 0 ]; then + CONTAINER_IP=$(dig a "${1}" +short) + else + sleep 0.5 + # get long container id for exact match + CONTAINER_ID=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | .id")) + # returned id can have multiple elements (if scaled), shuffle for random test + CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) + if [[ ! -z ${CONTAINER_ID} ]]; then + for matched_container in "${CONTAINER_ID[@]}"; do + CONTAINER_IPS=($(curl --silent --insecure https://dockerapi/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')) + for ip_match in "${CONTAINER_IPS[@]}"; do + # grep will do nothing if one of these vars is empty + [[ -z ${ip_match} ]] && continue + [[ -z ${IPV4_NETWORK} ]] && continue + # only return ips that are part of our network + if ! grep -q ${IPV4_NETWORK} <(echo ${ip_match}); then + continue + else + CONTAINER_IP=${ip_match} + break + fi + done + [[ ! -z ${CONTAINER_IP} ]] && break + done + fi fi LOOP_C=$((LOOP_C + 1)) done [[ ${LOOP_C} -gt 5 ]] && echo 240.0.0.0 || echo ${CONTAINER_IP} } -# Check functions nginx_checks() { err_count=0 diff_c=0 @@ -96,15 +117,52 @@ nginx_checks() { # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/nginx-mailcow; echo "$(tail -50 /tmp/nginx-mailcow)" > /tmp/nginx-mailcow host_ip=$(get_container_ip nginx-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_ping -4 -H ${host_ip} -w 2000,10% -c 4000,100% -p2 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u / -p 8081 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u / -p 8081 2>> /tmp/nginx-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "Nginx" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi + done + return 1 +} + +unbound_checks() { + err_count=0 + diff_c=0 + THRESHOLD=8 + # Reduce error count by 2 after restarting an unhealthy container + trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 + while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/unbound-mailcow; echo "$(tail -50 /tmp/unbound-mailcow)" > /tmp/unbound-mailcow + host_ip=$(get_container_ip unbound-mailcow) + err_c_cur=${err_count} + /usr/lib/nagios/plugins/check_dns -s ${host_ip} -H stackoverflow.com 2>> /tmp/unbound-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + DNSSEC=$(dig com +dnssec | egrep 'flags:.+ad') + if [[ -z ${DNSSEC} ]]; then + echo "DNSSEC failure" 2>> /tmp/unbound-mailcow 1>&2 + err_count=$(( ${err_count} + 1)) + else + echo "DNSSEC check succeeded" 2>> /tmp/unbound-mailcow 1>&2 + fi + [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 + [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) + progress "Unbound" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi done return 1 } @@ -116,15 +174,21 @@ mysql_checks() { # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/mysql-mailcow; echo "$(tail -50 /tmp/mysql-mailcow)" > /tmp/mysql-mailcow host_ip=$(get_container_ip mysql-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_mysql -H ${host_ip} -P 3306 -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_mysql_query -H ${host_ip} -P 3306 -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} -q "SELECT COUNT(*) FROM information_schema.tables" 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_mysql -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 2>> /tmp/mysql-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_mysql_query -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} -q "SELECT COUNT(*) FROM information_schema.tables" 2>> /tmp/mysql-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "MySQL/MariaDB" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi done return 1 } @@ -132,19 +196,24 @@ mysql_checks() { sogo_checks() { err_count=0 diff_c=0 - THRESHOLD=20 + THRESHOLD=10 # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/sogo-mailcow; echo "$(tail -50 /tmp/sogo-mailcow)" > /tmp/sogo-mailcow host_ip=$(get_container_ip sogo-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /WebServerResources/css/theme-default.css -p 9192 -R md-default-theme 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 2>> /tmp/sogo-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "SOGo" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi done return 1 } @@ -152,19 +221,50 @@ sogo_checks() { postfix_checks() { err_count=0 diff_c=0 - THRESHOLD=16 + THRESHOLD=8 # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do - host_ip=$(get_container_ip postfix-mailcow) + touch /tmp/postfix-mailcow; echo "$(tail -50 /tmp/postfix-mailcow)" > /tmp/postfix-mailcow + host_ip=$(get_container_ip postfix-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -f "watchdog@invalid" -C "RCPT TO:null@localhost" -C DATA -C . -R 250 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -S 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -f "watchdog@invalid" -C "RCPT TO:null@localhost" -C DATA -C . -R 250 2>> /tmp/postfix-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -S 2>> /tmp/postfix-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "Postfix" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi + done + return 1 +} + +clamd_checks() { + err_count=0 + diff_c=0 + THRESHOLD=15 + # Reduce error count by 2 after restarting an unhealthy container + trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 + while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/clamd-mailcow; echo "$(tail -50 /tmp/clamd-mailcow)" > /tmp/clamd-mailcow + host_ip=$(get_container_ip clamd-mailcow) + err_c_cur=${err_count} + /usr/lib/nagios/plugins/check_clamd -4 -H ${host_ip} 2>> /tmp/clamd-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 + [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) + progress "Clamd" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 30 )) + fi done return 1 } @@ -172,22 +272,28 @@ postfix_checks() { dovecot_checks() { err_count=0 diff_c=0 - THRESHOLD=24 + THRESHOLD=20 # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/dovecot-mailcow; echo "$(tail -50 /tmp/dovecot-mailcow)" > /tmp/dovecot-mailcow host_ip=$(get_container_ip dovecot-mailcow) err_c_cur=${err_count} - /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 24 -f "watchdog@invalid" -C "RCPT TO:" -L -R "User doesn't exist" 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_imap -4 -H ${host_ip} -p 993 -S -e "OK " 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_imap -4 -H ${host_ip} -p 143 -e "OK " 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_tcp -4 -H ${host_ip} -p 10001 -e "VERSION" 1>&2; err_count=$(( ${err_count} + $? )) - /usr/lib/nagios/plugins/check_tcp -4 -H ${host_ip} -p 4190 -e "Dovecot ready" 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 24 -f "watchdog@invalid" -C "RCPT TO:" -L -R "User doesn't exist" 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_imap -4 -H ${host_ip} -p 993 -S -e "OK " 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_imap -4 -H ${host_ip} -p 143 -e "OK " 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_tcp -4 -H ${host_ip} -p 10001 -e "VERSION" 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_tcp -4 -H ${host_ip} -p 4190 -e "Dovecot ready" 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "Dovecot" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi done return 1 } @@ -195,46 +301,143 @@ dovecot_checks() { phpfpm_checks() { err_count=0 diff_c=0 - THRESHOLD=10 + THRESHOLD=5 # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/php-fpm-mailcow; echo "$(tail -50 /tmp/php-fpm-mailcow)" > /tmp/php-fpm-mailcow host_ip=$(get_container_ip php-fpm-mailcow) err_c_cur=${err_count} - nc -z ${host_ip} 9001 ; err_count=$(( ${err_count} + ($? * 2))) - nc -z ${host_ip} 9002 ; err_count=$(( ${err_count} + ($? * 2))) - /usr/lib/nagios/plugins/check_ping -4 -H ${host_ip} -w 2000,10% -c 4000,100% -p2 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_tcp -H ${host_ip} -p 9001 2>> /tmp/php-fpm-mailcow 1>&2; err_count=$(( ${err_count} + $? )) + /usr/lib/nagios/plugins/check_tcp -H ${host_ip} -p 9002 2>> /tmp/php-fpm-mailcow 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "PHP-FPM" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} - diff_c=0 - sleep $(( ( RANDOM % 30 ) + 10 )) + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi done return 1 } -rspamd_checks() { +ratelimit_checks() { err_count=0 diff_c=0 - THRESHOLD=10 + THRESHOLD=1 + RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid) # Reduce error count by 2 after restarting an unhealthy container trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 while [ ${err_count} -lt ${THRESHOLD} ]; do + err_c_cur=${err_count} + RL_LOG_STATUS_PREV=${RL_LOG_STATUS} + RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid) + if [[ ${RL_LOG_STATUS_PREV} != ${RL_LOG_STATUS} ]]; then + err_count=$(( ${err_count} + 1 )) + fi + [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 + [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) + progress "Ratelimit" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi + done + return 1 +} + +acme_checks() { + err_count=0 + diff_c=0 + THRESHOLD=1 + ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME) + if [[ -z "${ACME_LOG_STATUS}" ]]; then + redis-cli -h redis SET ACME_FAIL_TIME 0 + ACME_LOG_STATUS=0 + fi + # Reduce error count by 2 after restarting an unhealthy container + trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 + while [ ${err_count} -lt ${THRESHOLD} ]; do + err_c_cur=${err_count} + ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS} + ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME) + if [[ ${ACME_LOG_STATUS_PREV} != ${ACME_LOG_STATUS} ]]; then + err_count=$(( ${err_count} + 1 )) + fi + [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 + [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) + progress "ACME" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep $(( ( RANDOM % 30 ) + 10 )) + fi + done + return 1 +} + +ipv6nat_checks() { + err_count=0 + diff_c=0 + THRESHOLD=1 + # Reduce error count by 2 after restarting an unhealthy container + trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 + while [ ${err_count} -lt ${THRESHOLD} ]; do + err_c_cur=${err_count} + CONTAINERS=$(curl --silent --insecure https://dockerapi/containers/json) + IPV6NAT_CONTAINER_ID=$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\")) | .id") + if [[ ! -z ${IPV6NAT_CONTAINER_ID} ]]; then + LATEST_STARTED="$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\") | not)" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)" + LATEST_IPV6NAT="$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\"))" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)" + DIFFERENCE_START_TIME=$(expr ${LATEST_IPV6NAT} - ${LATEST_STARTED} 2>/dev/null) + if [[ "${DIFFERENCE_START_TIME}" -lt 30 ]]; then + err_count=$(( ${err_count} + 1 )) + fi + fi + [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 + [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) + progress "IPv6 NAT" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} + if [[ $? == 10 ]]; then + diff_c=0 + sleep 1 + else + diff_c=0 + sleep 300 + fi + done + return 1 +} + + +rspamd_checks() { + err_count=0 + diff_c=0 + THRESHOLD=5 + # Reduce error count by 2 after restarting an unhealthy container + trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 + while [ ${err_count} -lt ${THRESHOLD} ]; do + touch /tmp/rspamd-mailcow; echo "$(tail -50 /tmp/rspamd-mailcow)" > /tmp/rspamd-mailcow host_ip=$(get_container_ip rspamd-mailcow) err_c_cur=${err_count} - SCORE=$(/usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/scan -d ' -To: null@localhost + SCORE=$(echo 'To: null@localhost From: watchdog@localhost Empty -' | jq -rc .required_score) +' | usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan | jq -rc .required_score) if [[ ${SCORE} != "9999" ]]; then - echo "Rspamd settings check failed" 1>&2 + echo "Rspamd settings check failed" 2>> /tmp/rspamd-mailcow 1>&2 err_count=$(( ${err_count} + 1)) else - echo "Rspamd settings check succeeded" 1>&2 + echo "Rspamd settings check succeeded" 2>> /tmp/rspamd-mailcow 1>&2 fi - /usr/lib/nagios/plugins/check_ping -4 -H ${host_ip} -w 2000,10% -c 4000,100% -p2 1>&2; err_count=$(( ${err_count} + $? )) [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) progress "Rspamd" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} @@ -249,7 +452,6 @@ Empty while true; do if ! nginx_checks; then log_msg "Nginx hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "nginx-mailcow" echo nginx-mailcow > /tmp/com_pipe fi done @@ -260,7 +462,6 @@ BACKGROUND_TASKS+=($!) while true; do if ! mysql_checks; then log_msg "MySQL hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "mysql-mailcow" echo mysql-mailcow > /tmp/com_pipe fi done @@ -271,7 +472,6 @@ BACKGROUND_TASKS+=($!) while true; do if ! phpfpm_checks; then log_msg "PHP-FPM hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "php-fpm-mailcow" echo php-fpm-mailcow > /tmp/com_pipe fi done @@ -282,18 +482,40 @@ BACKGROUND_TASKS+=($!) while true; do if ! sogo_checks; then log_msg "SOGo hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "sogo-mailcow" echo sogo-mailcow > /tmp/com_pipe fi done ) & BACKGROUND_TASKS+=($!) +if [ ${CHECK_UNBOUND} -eq 1 ]; then +( +while true; do + if ! unbound_checks; then + log_msg "Unbound hit error limit" + echo unbound-mailcow > /tmp/com_pipe + fi +done +) & +BACKGROUND_TASKS+=($!) +fi + +if [[ "${SKIP_CLAMD}" =~ ^([nN][oO]|[nN])+$ ]]; then +( +while true; do + if ! clamd_checks; then + log_msg "Clamd hit error limit" + echo clamd-mailcow > /tmp/com_pipe + fi +done +) & +BACKGROUND_TASKS+=($!) +fi + ( while true; do if ! postfix_checks; then log_msg "Postfix hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "postfix-mailcow" echo postfix-mailcow > /tmp/com_pipe fi done @@ -304,7 +526,6 @@ BACKGROUND_TASKS+=($!) while true; do if ! dovecot_checks; then log_msg "Dovecot hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "dovecot-mailcow" echo dovecot-mailcow > /tmp/com_pipe fi done @@ -315,13 +536,42 @@ BACKGROUND_TASKS+=($!) while true; do if ! rspamd_checks; then log_msg "Rspamd hit error limit" - [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "rspamd-mailcow" echo rspamd-mailcow > /tmp/com_pipe fi done ) & BACKGROUND_TASKS+=($!) +( +while true; do + if ! ratelimit_checks; then + log_msg "Ratelimit hit error limit" + echo ratelimit > /tmp/com_pipe + fi +done +) & +BACKGROUND_TASKS+=($!) + +( +while true; do + if ! acme_checks; then + log_msg "ACME client hit error limit" + echo acme-tiny > /tmp/com_pipe + fi +done +) & +BACKGROUND_TASKS+=($!) + +( +while true; do + if ! ipv6nat_checks; then + log_msg "IPv6 NAT warning: ipv6nat-mailcow container was not started at least 30s after siblings (not an error)" + echo ipv6nat-mailcow > /tmp/com_pipe + fi +done +) & +BACKGROUND_TASKS+=($!) + # Monitor watchdog agents, stop script when agents fails and wait for respawn by Docker (restart:always:n) ( while true; do @@ -338,12 +588,12 @@ done # Monitor dockerapi ( while true; do - while nc -z dockerapi 8080; do + while nc -z dockerapi 443; do sleep 3 done log_msg "Cannot find dockerapi-mailcow, waiting to recover..." kill -STOP ${BACKGROUND_TASKS[*]} - until nc -z dockerapi 8080; do + until nc -z dockerapi 443; do sleep 3 done kill -CONT ${BACKGROUND_TASKS[*]} @@ -354,17 +604,41 @@ done # Restart container when threshold limit reached while true; do CONTAINER_ID= + HAS_INITDB= read com_pipe_answer &2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +_check_config() { + toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) + if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then + cat >&2 <<-EOM + + ERROR: mysqld failed while attempting to check config + command was: "${toRun[*]}" + + $errors + EOM + exit 1 + fi +} + +# Fetch value from server config +# We use mysqld --verbose --help instead of my_print_defaults because the +# latter only show values present in config files, and not server defaults +_get_config() { + local conf="$1"; shift + "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# allow the container to be started with `--user` +if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then + _check_config "$@" + DATADIR="$(_get_config 'datadir' "$@")" + mkdir -p "$DATADIR" + chown -R mysql:mysql "$DATADIR" + exec gosu mysql "$BASH_SOURCE" "$@" +fi + +if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then + # still need to check config, container may have started with --user + _check_config "$@" + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + file_env 'MYSQL_ROOT_PASSWORD' + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 'error: database is uninitialized and password option is not specified ' + echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD' + exit 1 + fi + + mkdir -p "$DATADIR" + + echo 'Initializing database' + # "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here) + mysql_install_db --datadir="$DATADIR" --rpm "${@:2}" + echo 'Database initialized' + + SOCKET="$(_get_config 'socket' "$@")" + "$@" --skip-networking --socket="${SOCKET}" & + pid="$!" + + mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" ) + + for i in {30..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi + echo 'MySQL init process in progress...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then + # sed is for https://bugs.mysql.com/bug.php?id=20545 + mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql + fi + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)" + echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + + rootCreate= + # default root to listen for connections from anywhere + file_env 'MYSQL_ROOT_HOST' '%' + if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then + # no, we don't care if read finds a terminating character in this heredoc + # https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151 + read -r -d '' rootCreate <<-EOSQL || true + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; + EOSQL + fi + + "${mysql[@]}" <<-EOSQL + -- What's done in this file shouldn't be replicated + -- or products like mysql-fabric won't work + SET @@SESSION.SQL_LOG_BIN=0; + + DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ; + SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ; + GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ; + ${rootCreate} + DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; + EOSQL + + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) + fi + + file_env 'MYSQL_DATABASE' + if [ "$MYSQL_DATABASE" ]; then + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) + fi + + file_env 'MYSQL_USER' + file_env 'MYSQL_PASSWORD' + if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then + echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" + + if [ "$MYSQL_DATABASE" ]; then + echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" + fi + fi + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + echo + echo 'MySQL init process done. Ready for start up.' + echo + fi +fi + +exec "$@" diff --git a/data/assets/nextcloud/nextcloud.conf b/data/assets/nextcloud/nextcloud.conf index 72f30240..cf90a32b 100644 --- a/data/assets/nextcloud/nextcloud.conf +++ b/data/assets/nextcloud/nextcloud.conf @@ -5,11 +5,11 @@ map $http_x_forwarded_proto $client_req_scheme_nc { server { include /etc/nginx/conf.d/listen_ssl.active; + include /etc/nginx/conf.d/listen_plain.active; include /etc/nginx/mime.types; charset utf-8; override_charset on; - ssl on; ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; ssl_protocols TLSv1.2; @@ -24,7 +24,8 @@ server { add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Permitted-Cross-Domain-Policies none; - add_header X-Frame-Options "SAMEORIGIN"; + #add_header X-Frame-Options "SAMEORIGIN"; + add_header Referrer-Policy "no-referrer"; server_name NC_SUBD; diff --git a/data/assets/templates/quarantine.tpl b/data/assets/templates/quarantine.tpl new file mode 100644 index 00000000..3af0e121 --- /dev/null +++ b/data/assets/templates/quarantine.tpl @@ -0,0 +1,49 @@ + + + + + +

Hi!
+ {% if counter == 1 %} + There is 1 new message waiting in quarantine:
+ {% else %} + There are {{counter}} new messages waiting in quarantine:
+ {% endif %} + + {% if quarantine_acl == 1 %}{% endif %} + {% for line in meta %} + + + + + + {% if quarantine_acl == 1 %} + + {% endif %} + + {% endfor %} +
SubjectSenderScoreArrived onActions
{{ line.subject|e }}{{ line.sender|e }}{{ line.score }}{{ line.created }}release | delete
+

+ + diff --git a/data/assets/templates/quota.tpl b/data/assets/templates/quota.tpl new file mode 100644 index 00000000..eef5c92a --- /dev/null +++ b/data/assets/templates/quota.tpl @@ -0,0 +1,29 @@ + + + + + +

Hi {{username}}!

+ Your mailbox is now {{percent}}% full, please consider deleting old messages to still be able to receive new mails in the future.
+

+
+
+

+ + diff --git a/data/conf/clamav/clamd.conf b/data/conf/clamav/clamd.conf index f09510bd..0fe92e72 100644 --- a/data/conf/clamav/clamd.conf +++ b/data/conf/clamav/clamd.conf @@ -1,4 +1,5 @@ -LogFile /dev/console +#Debug true +#LogFile /dev/null LogTime yes LogClean yes ExtendedDetectionInfo yes @@ -23,9 +24,9 @@ DetectPUA yes #IncludePUA Spy #IncludePUA Scanner #IncludePUA RAT -AlgorithmicDetection yes +HeuristicAlerts yes ScanOLE2 yes -OLE2BlockMacros yes +AlertOLE2Macros no ScanPDF yes ScanSWF yes ScanXMLDOCS yes diff --git a/data/conf/clamav/freshclam.conf b/data/conf/clamav/freshclam.conf index f4fff582..50eae031 100644 --- a/data/conf/clamav/freshclam.conf +++ b/data/conf/clamav/freshclam.conf @@ -1,8 +1,7 @@ -UpdateLogFile /var/log/clamav/freshclam.log +#UpdateLogFile /dev/console LogTime yes PidFile /run/clamav/freshclam.pid DatabaseOwner clamav -AllowSupplementaryGroups yes DNSDatabaseInfo current.cvd.clamav.net DatabaseMirror database.clamav.net MaxAttempts 4 diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index dd8db8a3..cef0a19a 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -1,6 +1,12 @@ # -------------------------------------------------------------------------- # Please create a file "extra.conf" for persistent overrides to dovecot.conf # -------------------------------------------------------------------------- +# LDAP example: +#passdb { +# args = /usr/local/etc/dovecot/ldap/passdb.conf +# driver = ldap +#} + auth_mechanisms = plain login #mail_debug = yes #auth_debug = yes @@ -14,7 +20,10 @@ disable_plaintext_auth = yes login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k" mail_home = /var/vmail/%d/%n mail_location = maildir:~/ -mail_plugins = quota acl zlib listescape #mail_crypt +mail_plugins = /dev/null; then + echo 'auth_request /sogo-auth-verify; +auth_request_set $user $upstream_http_x_user; +auth_request_set $auth $upstream_http_x_auth; +auth_request_set $auth_type $upstream_http_x_auth_type; +proxy_set_header x-webobjects-remote-user "$user"; +proxy_set_header Authorization "$auth"; +proxy_set_header x-webobjects-auth-type "$auth_type"; +' +fi diff --git a/data/conf/phpfpm/php-conf.d/other.ini b/data/conf/phpfpm/php-conf.d/other.ini index 2d05a5b7..4a90901d 100644 --- a/data/conf/phpfpm/php-conf.d/other.ini +++ b/data/conf/phpfpm/php-conf.d/other.ini @@ -1,2 +1,4 @@ session.save_handler = redis session.save_path = "tcp://redis:6379" +max_execution_time = 1200 +max_input_time = 1200 diff --git a/data/conf/phpfpm/php-fpm.d/pools.conf b/data/conf/phpfpm/php-fpm.d/pools.conf index 0667c2bc..77145a74 100644 --- a/data/conf/phpfpm/php-fpm.d/pools.conf +++ b/data/conf/phpfpm/php-fpm.d/pools.conf @@ -11,8 +11,7 @@ access.log = /proc/self/fd/2 clear_env = no catch_workers_output = yes php_admin_value[memory_limit] = 256M -php_admin_value[max_execution_time] = 1200 -php_admin_value[max_input_time] = 1200 +php_admin_value[disable_functions] = show_source, highlight_file, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, virtual, dl, disk_total_space, posix_getpwnam, posix_getpwuid, posix_mkfifo, posix_mknod, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_nice, openlog, syslog, pfsockopen, system, shell_exec, passthru, popen, proc_open, exec, ini_alter, pcntl_exec, proc_close, proc_get_status, proc_terminate, symlink [web-worker] user = www-data @@ -26,7 +25,5 @@ listen = [::]:9002 access.log = /proc/self/fd/2 clear_env = no catch_workers_output = yes -php_admin_value[memory_limit] = 256M -php_admin_value[max_execution_time] = 1200 -php_admin_value[max_input_time] = 1200 - +php_admin_value[memory_limit] = 512M +php_admin_value[disable_functions] = show_source, highlight_file, apache_child_terminate, apache_get_modules, apache_note, apache_setenv, virtual, dl, disk_total_space, posix_getpwnam, posix_getpwuid, posix_mkfifo, posix_mknod, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_nice, openlog, syslog, pfsockopen, system, shell_exec, passthru, popen, proc_open, exec, ini_alter, pcntl_exec, proc_close, proc_get_status, proc_terminate, symlink diff --git a/data/conf/phpfpm/sogo-sso/.gitkeep b/data/conf/phpfpm/sogo-sso/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/data/conf/postfix/allow_mailcow_local.regexp b/data/conf/postfix/allow_mailcow_local.regexp new file mode 100644 index 00000000..0da4593c --- /dev/null +++ b/data/conf/postfix/allow_mailcow_local.regexp @@ -0,0 +1 @@ +/^(.+)@mailcow.local/ OK diff --git a/data/conf/postfix/anonymize_headers.pcre b/data/conf/postfix/anonymize_headers.pcre new file mode 100644 index 00000000..099094d9 --- /dev/null +++ b/data/conf/postfix/anonymize_headers.pcre @@ -0,0 +1,8 @@ +if /^\s*Received:.*Authenticated sender.*\(Postcow\)/ +/^\s*Received:.*Authenticated sender:(.+)/ + REPLACE Received: from localhost (localhost [127.0.0.1]) (Authenticated sender:$1 +endif +/^\s*X-Enigmail/ IGNORE +/^\s*X-Mailer/ IGNORE +/^\s*X-Originating-IP/ IGNORE +/^\s*X-Forward/ IGNORE diff --git a/data/conf/postfix/local_transport b/data/conf/postfix/local_transport new file mode 100644 index 00000000..5d10028c --- /dev/null +++ b/data/conf/postfix/local_transport @@ -0,0 +1 @@ +/localhost$/ local: diff --git a/data/conf/postfix/main.cf b/data/conf/postfix/main.cf index dc49e75e..88d905e7 100644 --- a/data/conf/postfix/main.cf +++ b/data/conf/postfix/main.cf @@ -20,7 +20,7 @@ broken_sasl_auth_clients = yes disable_vrfy_command = yes maximal_backoff_time = 1800s maximal_queue_lifetime = 1d -message_size_limit = 26214400 +message_size_limit = 104857600 milter_default_action = accept milter_protocol = 6 minimal_backoff_time = 300s @@ -41,8 +41,11 @@ postscreen_greet_wait = 3s postscreen_non_smtp_command_enable = no postscreen_pipelining_enable = no proxy_read_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_sender_acl.cf, + proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf, - proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf, + proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf, + proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf, + proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_transport_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf, @@ -91,13 +94,18 @@ smtpd_tls_dh1024_param_file = /etc/ssl/mail/dhparams.pem smtpd_tls_eecdh_grade = auto smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL, DES-CBC3-SHA, ECDHE-RSA-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA smtpd_tls_loglevel = 1 -smtp_tls_mandatory_protocols = !SSLv2, !SSLv3 + +smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_protocols = !SSLv2, !SSLv3 -lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3 -lmtp_tls_protocols = !SSLv2, !SSLv2, !SSLv3 -smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 + +lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 +lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 + +smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_protocols = !SSLv2, !SSLv3 + smtpd_tls_security_level = may +tls_preempt_cipherlist = yes tls_ssl_options = NO_COMPRESSION smtpd_tls_mandatory_ciphers = high virtual_alias_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_maps.cf, @@ -124,6 +132,11 @@ mydestination = localhost.localdomain, localhost smtp_address_preference = ipv4 smtp_sender_dependent_authentication = yes smtp_sasl_auth_enable = yes -smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf +smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf smtp_sasl_security_options = smtp_sasl_mechanism_filter = plain, login +smtp_tls_policy_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf +smtp_header_checks = pcre:/opt/postfix/conf/anonymize_headers.pcre +mail_name = Postcow +transport_maps = pcre:/opt/postfix/conf/local_transport, proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf +smtp_sasl_auth_soft_bounce = no diff --git a/data/conf/postfix/master.cf b/data/conf/postfix/master.cf index 4911271e..fcc99717 100644 --- a/data/conf/postfix/master.cf +++ b/data/conf/postfix/master.cf @@ -1,17 +1,23 @@ smtp inet n - n - 1 postscreen smtpd pass - - n - - smtpd -o smtpd_helo_restrictions=permit_mynetworks,reject_non_fqdn_helo_hostname + -o smtpd_sasl_auth_enable=no + -o smtpd_sender_restrictions=permit_mynetworks,reject_unlisted_sender,reject_unknown_sender_domain smtps inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject + -o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 + -o tls_preempt_cipherlist=yes submission inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject -o smtpd_enforce_tls=yes -o smtpd_tls_security_level=encrypt + -o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 -o tls_preempt_cipherlist=yes 588 inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject -o smtpd_tls_auth_only=no + -o smtpd_sender_restrictions=check_sasl_access,regexp:/opt/postfix/conf/allow_mailcow_local.regexp,reject_authenticated_sender_login_mismatch,permit_mynetworks,permit_sasl_authenticated,reject_unlisted_sender,reject_unknown_sender_domain 590 inet n - n - - smtpd -o smtpd_client_restrictions=permit_mynetworks,reject -o smtpd_tls_auth_only=no @@ -21,6 +27,8 @@ smtp_enforced_tls unix - - n - - smtp -o smtp_tls_security_level=encrypt -o syslog_name=enforced-tls-smtp -o smtp_delivery_status_filter=pcre:/opt/postfix/conf/smtp_dsn_filter +smtp_via_transport_maps unix - - n - - smtp + -o smtp_sasl_password_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_transport_maps.cf tlsproxy unix - - n - 0 tlsproxy dnsblog unix - - n - 0 dnsblog diff --git a/data/conf/rspamd/custom/bad_asn.map b/data/conf/rspamd/custom/bad_asn.map index 8b7a4407..ffd9af0f 100644 --- a/data/conf/rspamd/custom/bad_asn.map +++ b/data/conf/rspamd/custom/bad_asn.map @@ -1,11 +1,12 @@ # High spam networks, disabled by default +# ASN:SCORE DESC +# Remove comment to enable score #201942:5 #Soltia Consulting SL - ipinfo.io -#16276:5 #OVH -#12876:5 #ONLINE S.A.S -#31034:5 -#12874:5 -#30823:5 -#197071:5 +#16276:2 #OVH +#12876:2 #ONLINE S.A.S +#31034:5 #ARUBA-ASN, IT +#12874:5 #FASTWEB, IT +#30823:3 #PKV spam #42831:5 #UK Dedicated Servers Ltd #29119:5 #Aire Networks del Mediterraneo S.L.U. #13335:5 #Cloudflare @@ -17,7 +18,7 @@ #14061:4 #Digitalocean #55293:4 #A2 Hosting #63018:4 #US Dedicated -#197518:2 +#197518:2 #RACKMARKT #44493:2 #46606:2 #49505:2 @@ -25,3 +26,5 @@ #197695:2 #198068:2 #43146:2 +#49100:4 +#39364:4 diff --git a/data/conf/rspamd/custom/global_mime_from_blacklist.map b/data/conf/rspamd/custom/global_mime_from_blacklist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_mime_from_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/custom/global_mime_from_whitelist.map b/data/conf/rspamd/custom/global_mime_from_whitelist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_mime_from_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/custom/global_rcpt_blacklist.map b/data/conf/rspamd/custom/global_rcpt_blacklist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_rcpt_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/custom/global_rcpt_whitelist.map b/data/conf/rspamd/custom/global_rcpt_whitelist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_rcpt_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/custom/global_smtp_from_blacklist.map b/data/conf/rspamd/custom/global_smtp_from_blacklist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_smtp_from_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/custom/global_smtp_from_whitelist.map b/data/conf/rspamd/custom/global_smtp_from_whitelist.map new file mode 100644 index 00000000..3c872889 --- /dev/null +++ b/data/conf/rspamd/custom/global_smtp_from_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/data/conf/rspamd/dynmaps/settings.php b/data/conf/rspamd/dynmaps/settings.php index 5f83da81..a2be8ceb 100644 --- a/data/conf/rspamd/dynmaps/settings.php +++ b/data/conf/rspamd/dynmaps/settings.php @@ -6,10 +6,13 @@ then any of these will trigger the rule. If a rule is triggered then no more rul */ header('Content-Type: text/plain'); require_once "vars.inc.php"; +// Getting headers sent by the client. +//$headers = apache_request_headers(); ini_set('error_reporting', 0); -$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name; +//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name; +$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, @@ -24,14 +27,50 @@ catch (PDOException $e) { exit; } +// Check if db changed and return header +/*$stmt = $pdo->prepare("SELECT UNIX_TIMESTAMP(UPDATE_TIME) AS `db_update_time` FROM information_schema.tables + WHERE `TABLE_NAME` = 'filterconf' + AND TABLE_SCHEMA = :dbname;"); +$stmt->execute(array( + ':dbname' => $database_name +)); +$db_update_time = $stmt->fetch(PDO::FETCH_ASSOC)['db_update_time']; + +if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $db_update_time)) { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 304); + exit; +} else { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 200); +} +*/ + function parse_email($email) { - if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; $a = strrpos($email, '@'); return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a)); } +function wl_by_sogo() { + global $pdo; + $rcpt = array(); + $stmt = $pdo->query("SELECT DISTINCT(`sogo_folder_info`.`c_path2`) AS `user`, GROUP_CONCAT(`sogo_quick_contact`.`c_mail`) AS `contacts` FROM `sogo_folder_info` + INNER JOIN `sogo_quick_contact` ON `sogo_quick_contact`.`c_folder_id` = `sogo_folder_info`.`c_folder_id` + GROUP BY `c_path2`"); + $sogo_contacts = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($sogo_contacts)) { + foreach (explode(',', $row['contacts']) as $contact) { + if (!filter_var($contact, FILTER_VALIDATE_EMAIL)) { + continue; + } + $rcpt[$row['user']][] = '/^' . str_replace('/', '\/', $contact) . '$/i'; + } + } + return $rcpt; +} + function ucl_rcpts($object, $type) { global $pdo; + $rcpt = array(); if ($type == 'mailbox') { // Standard aliases $stmt = $pdo->prepare("SELECT `address` FROM `alias` @@ -81,17 +120,14 @@ function ucl_rcpts($object, $type) { $rcpt[] = '/.*@' . $row['alias_domain'] . '/i'; } } - if (!empty($rcpt)) { - return $rcpt; - } - return false; + return $rcpt; } ?> settings { watchdog { priority = 10; - rcpt = "/null@localhost/i"; - from = "/watchdog@localhost/i"; + rcpt_mime = "/null@localhost/i"; + from_mime = "/watchdog@localhost/i"; apply "default" { actions { reject = 9999.0; @@ -137,6 +173,40 @@ while ($row = array_shift($rows)) { $contacts) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $user); +?> + whitelist_sogo_ { + + from = ; + + priority = 4; + + rcpt = ; + + apply "default" { + SOGO_CONTACT = -99.0; + } + symbols [ + "SOGO_CONTACT" + ] + } + whitelist_ { prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('^', `value`, '$'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf` + $list_items = array(); + $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object`= :object AND `option` = 'whitelist_from'"); $stmt->execute(array(':object' => $row['object'])); - $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN); - $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0]))); + $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($list_items as $item) { ?> - from = "/()/i"; + from = "//i"; priority = 5; @@ -185,19 +257,13 @@ while ($row = array_shift($rows)) { "MAILCOW_WHITE" ] } - whitelist_header_ { + whitelist_mime_ { prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('\<', `value`, '\>'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf` - WHERE `object`= :object - AND `option` = 'whitelist_from'"); - $stmt->execute(array(':object' => $row['object'])); - $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN); - $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0]))); + foreach ($list_items as $item) { ?> - header = { - "From" = "/()/i"; - } + from_mime = "//i"; priority = 5; @@ -240,15 +306,17 @@ while ($row = array_shift($rows)) { ?> blacklist_ { prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('^', `value`, '$'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf` + $list_items = array(); + $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object`= :object AND `option` = 'blacklist_from'"); $stmt->execute(array(':object' => $row['object'])); - $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN); - $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0]))); + $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($list_items as $item) { ?> - from = "/()/i"; + from = "//i"; priority = 5; @@ -279,17 +347,11 @@ while ($row = array_shift($rows)) { } blacklist_header_ { prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('\<', `value`, '\>'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf` - WHERE `object`= :object - AND `option` = 'blacklist_from'"); - $stmt->execute(array(':object' => $row['object'])); - $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN); - $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0]))); + foreach ($list_items as $item) { ?> - header = { - "From" = "/()/i"; - } + from_mime = "//i"; priority = 5; @@ -342,7 +404,6 @@ while ($row = array_shift($rows)) { priority = 9; want_spam = yes; } - + } + } diff --git a/data/conf/rspamd/local.d/antivirus.conf b/data/conf/rspamd/local.d/antivirus.conf index 157c3cb9..c8d31d1e 100644 --- a/data/conf/rspamd/local.d/antivirus.conf +++ b/data/conf/rspamd/local.d/antivirus.conf @@ -1,7 +1,11 @@ clamav { - attachments_only = true; + # Scan whole message + scan_mime_parts = false; + #scan_text_mime = true; + #scan_image_mime = true; symbol = "CLAM_VIRUS"; type = "clamav"; log_clean = true; servers = "clamd:3310"; + max_size = 20971520; } diff --git a/data/conf/rspamd/local.d/composites.conf b/data/conf/rspamd/local.d/composites.conf index dd47be35..d775c4f6 100644 --- a/data/conf/rspamd/local.d/composites.conf +++ b/data/conf/rspamd/local.d/composites.conf @@ -1,5 +1,5 @@ MX_IMPLICIT { - expression = "MX_GOOD and MX_MISSING"; + expression = "MX_GOOD & MX_MISSING"; score = -0.01; } VIRUS_FOUND { @@ -10,3 +10,9 @@ SPF_FAIL_NO_DKIM { expression = "R_SPF_FAIL & R_DKIM_NA & !MAILCOW_WHITE"; score = 10; } +SOGO_CONTACT_EXCLUDE_FWD_HOST { + expression = "WHITELISTED_FWD_HOST & ~SOGO_CONTACT"; +} +SOGO_CONTACT_SPOOFED { + expression = "(R_SPF_PERMFAIL | R_SPF_SOFTFAIL | R_SPF_FAIL) & ~SOGO_CONTACT"; +} diff --git a/data/conf/rspamd/local.d/fuzzy_group.conf b/data/conf/rspamd/local.d/fuzzy_group.conf index 6b3390c6..f3effe4e 100644 --- a/data/conf/rspamd/local.d/fuzzy_group.conf +++ b/data/conf/rspamd/local.d/fuzzy_group.conf @@ -3,9 +3,9 @@ symbols = { weight = 2.0; } "LOCAL_FUZZY_DENIED" { - weight = 10.0; + weight = 15.0; } "LOCAL_FUZZY_WHITE" { - weight = -3.4; + weight = -10.0; } } diff --git a/data/conf/rspamd/local.d/history_redis.conf b/data/conf/rspamd/local.d/history_redis.conf new file mode 100644 index 00000000..68a59b0c --- /dev/null +++ b/data/conf/rspamd/local.d/history_redis.conf @@ -0,0 +1 @@ +nrows = 1000; diff --git a/data/conf/rspamd/local.d/metadata_exporter.conf b/data/conf/rspamd/local.d/metadata_exporter.conf index f1600708..afe5c7e1 100644 --- a/data/conf/rspamd/local.d/metadata_exporter.conf +++ b/data/conf/rspamd/local.d/metadata_exporter.conf @@ -1,10 +1,26 @@ rules { - QUARANTINE { - backend = "http"; - url = "http://nginx:9081/pipe.php"; - selector = "is_reject"; - formatter = "default"; - meta_headers = true; - } + QUARANTINE { + backend = "http"; + url = "http://nginx:9081/pipe.php"; + selector = "is_reject"; + formatter = "default"; + meta_headers = true; + } + RLINFO { + backend = "http"; + url = "http://nginx:9081/pipe_rl.php"; + selector = "ratelimited"; + formatter = "json"; + } +} +custom_select { + ratelimited = <Get('Q_MAX_SIZE')) { - if (!empty($max_size) && ($max_size * 1048576) < $raw_size) { - error_log(sprintf("Message too large: %d exceeds %d", $raw_size, ($max_size * 1048576))); - http_response_code(505); - exit; - } + $max_size = (int)$redis->Get('Q_MAX_SIZE'); + if (($max_size * 1048576) < $raw_size) { + error_log(sprintf("QUARANTINE: Message too large: %d b exceeds %d b", $raw_size, ($max_size * 1048576))); + http_response_code(505); + exit; } if ($exclude_domains = $redis->Get('Q_EXCLUDE_DOMAINS')) { $exclude_domains = json_decode($exclude_domains, true); @@ -73,7 +75,7 @@ try { $retention_size = (int)$redis->Get('Q_RETENTION_SIZE'); } catch (RedisException $e) { - error_log($e); + error_log("QUARANTINE: " . $e); http_response_code(504); exit; } @@ -82,6 +84,9 @@ $rcpt_final_mailboxes = array(); // Loop through all rcpts foreach (json_decode($rcpts, true) as $rcpt) { + // Remove tag + $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); + // Break rcpt into local part and domain part $parsed_rcpt = parse_email($rcpt); @@ -92,14 +97,14 @@ foreach (json_decode($rcpts, true) as $rcpt) { } } catch (RedisException $e) { - error_log($e); + error_log("QUARANTINE: " . $e); http_response_code(504); exit; } // Skip if domain is excluded if (in_array($parsed_rcpt['domain'], $exclude_domains)) { - error_log(sprintf("Skipped domain %s", $parsed_rcpt['domain'])); + error_log(sprintf("QUARANTINE: Skipped domain %s", $parsed_rcpt['domain'])); continue; } @@ -134,12 +139,12 @@ foreach (json_decode($rcpts, true) as $rcpt) { // Loop through all found gotos foreach ($gotos_array as $index => &$goto) { - error_log("quarantine pipe: query " . $goto . " as username from mailbox"); + error_log("QUARANTINE: quarantine pipe: query " . $goto . " as username from mailbox"); $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND `active`= '1';"); $stmt->execute(array(':goto' => $goto)); $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; if (!empty($username)) { - error_log("quarantine pipe: mailbox found: " . $username); + error_log("QUARANTINE: quarantine pipe: mailbox found: " . $username); // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate if (!in_array($username, $rcpt_final_mailboxes)) { $rcpt_final_mailboxes[] = $username; @@ -148,13 +153,13 @@ foreach (json_decode($rcpts, true) as $rcpt) { else { $parsed_goto = parse_email($goto); if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { - error_log($goto . " is not a mailcow handled mailbox or alias address"); + error_log("QUARANTINE:" . $goto . " is not a mailcow handled mailbox or alias address"); } else { $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); $stmt->execute(array(':goto' => $goto)); $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - error_log("quarantine pipe: goto address " . $goto . " is a alias branch for " . $goto_branch); + error_log("QUARANTINE: quarantine pipe: goto address " . $goto . " is a alias branch for " . $goto_branch); $goto_branch_array = explode(',', $goto_branch); } } @@ -174,23 +179,24 @@ foreach (json_decode($rcpts, true) as $rcpt) { // Force exit if loop cannot be solved // Postfix does not allow for alias loops, so this should never happen. $loop_c++; - error_log("quarantine pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array)); + error_log("QUARANTINE: quarantine pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array)); } } catch (PDOException $e) { - error_log($e->getMessage()); + error_log("QUARANTINE: " . $e->getMessage()); http_response_code(502); exit; } } foreach ($rcpt_final_mailboxes as $rcpt) { - error_log("quarantine pipe: processing quarantine message for rcpt " . $rcpt); + error_log("QUARANTINE: quarantine pipe: processing quarantine message for rcpt " . $rcpt); try { - $stmt = $pdo->prepare("INSERT INTO `quarantine` (`qid`, `score`, `sender`, `rcpt`, `symbols`, `user`, `ip`, `msg`, `action`) - VALUES (:qid, :score, :sender, :rcpt, :symbols, :user, :ip, :msg, :action)"); + $stmt = $pdo->prepare("INSERT INTO `quarantine` (`qid`, `subject`, `score`, `sender`, `rcpt`, `symbols`, `user`, `ip`, `msg`, `action`) + VALUES (:qid, :subject, :score, :sender, :rcpt, :symbols, :user, :ip, :msg, :action)"); $stmt->execute(array( ':qid' => $qid, + ':subject' => $subject, ':score' => $score, ':sender' => $sender, ':rcpt' => $rcpt, @@ -217,7 +223,7 @@ foreach ($rcpt_final_mailboxes as $rcpt) { )); } catch (PDOException $e) { - error_log($e->getMessage()); + error_log("QUARANTINE: " . $e->getMessage()); http_response_code(503); exit; } diff --git a/data/conf/rspamd/meta_exporter/pipe_rl.php b/data/conf/rspamd/meta_exporter/pipe_rl.php new file mode 100644 index 00000000..036bf881 --- /dev/null +++ b/data/conf/rspamd/meta_exporter/pipe_rl.php @@ -0,0 +1,38 @@ +connect('redis-mailcow', 6379); + +$raw_data_content = file_get_contents('php://input'); +$raw_data_decoded = json_decode($raw_data_content, true); + +$data['time'] = time(); +$data['rcpt'] = implode(', ', $raw_data_decoded['rcpt']); +$data['from'] = $raw_data_decoded['from']; +$data['user'] = $raw_data_decoded['user']; +$symbol_rl_key = array_search('RATELIMITED', array_column($raw_data_decoded['symbols'], 'name')); +$data['rl_info'] = implode($raw_data_decoded['symbols'][$symbol_rl_key]['options']); +preg_match('/(.+)\((.+)\)/i', $data['rl_info'], $rl_matches); +if (!empty($rl_matches[1]) && !empty($rl_matches[2])) { + $data['rl_name'] = $rl_matches[1]; + $data['rl_hash'] = $rl_matches[2]; +} +else { + $data['rl_name'] = 'err'; + $data['rl_hash'] = 'err'; +} +$data['qid'] = $raw_data_decoded['qid']; +$data['ip'] = $raw_data_decoded['ip']; +$data['message_id'] = $raw_data_decoded['message_id']; +$data['header_subject'] = implode(' ', $raw_data_decoded['header_subject']); +$data['header_from'] = implode(', ', $raw_data_decoded['header_from']); + +$redis->lpush('RL_LOG', json_encode($data)); +exit; + diff --git a/data/conf/rspamd/override.d/logging.inc b/data/conf/rspamd/override.d/logging.inc index 23a9f3cf..7765bb34 100644 --- a/data/conf/rspamd/override.d/logging.inc +++ b/data/conf/rspamd/override.d/logging.inc @@ -1,4 +1,5 @@ type = "console"; systemd = false; +level = "silent"; .include "$CONFDIR/logging.inc" .include(try=true; priority=20) "$CONFDIR/override.d/logging.custom.inc" diff --git a/data/conf/rspamd/override.d/ratelimit.conf b/data/conf/rspamd/override.d/ratelimit.conf index 3150d0e5..ccd083d4 100644 --- a/data/conf/rspamd/override.d/ratelimit.conf +++ b/data/conf/rspamd/override.d/ratelimit.conf @@ -1,11 +1,12 @@ rates { # Format: "1 / 1h" or "20 / 1m" etc. - global ratelimits are disabled by default - to = "100 / 1s"; - to_ip = "100 / 1s"; - to_ip_from = "100 / 1s"; + to = "45 / 1m"; + to_ip = "360 / 1m"; + to_ip_from = "180 / 1m"; bounce_to = "100 / 1s"; bounce_to_ip = "100 / 1s"; } whitelisted_rcpts = "postmaster,mailer-daemon"; max_rcpt = 5; custom_keywords = "/etc/rspamd/lua/ratelimit.lua"; +info_symbol = "RATELIMITED"; diff --git a/data/conf/rspamd/override.d/worker-controller.inc b/data/conf/rspamd/override.d/worker-controller.inc index 60338e15..4d4ffe6f 100644 --- a/data/conf/rspamd/override.d/worker-controller.inc +++ b/data/conf/rspamd/override.d/worker-controller.inc @@ -1,7 +1,7 @@ bind_socket = "*:11334"; -count = 2; +count = 1; secure_ip = "127.0.0.1"; secure_ip = "::1"; -bind_socket = "/rspamd-sock/rspamd.sock mode=0666 owner=nobody"; +bind_socket = "/var/lib/rspamd/rspamd.sock mode=0666 owner=nobody"; .include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc" .include(try=true; priority=20) "$CONFDIR/override.d/worker-controller.custom.inc" diff --git a/data/conf/rspamd/override.d/worker-fuzzy.inc b/data/conf/rspamd/override.d/worker-fuzzy.inc new file mode 100644 index 00000000..09b39c93 --- /dev/null +++ b/data/conf/rspamd/override.d/worker-fuzzy.inc @@ -0,0 +1,12 @@ +# Socket to listen on (UDP and TCP from rspamd 1.3) +bind_socket = "*:11445"; +allow_update = ["127.0.0.1", "::1"]; +# Number of processes to serve this storage (useful for read scaling) +count = 2; +# Backend ("sqlite" or "redis" - default "sqlite") +backend = "redis"; +# Hashes storage time (3 months) +expire = 90d; +# Synchronize updates to the storage each minute +sync = 1min; + diff --git a/data/conf/rspamd/override.d/worker-proxy.inc b/data/conf/rspamd/override.d/worker-proxy.inc index 0df926a7..92527f2b 100644 --- a/data/conf/rspamd/override.d/worker-proxy.inc +++ b/data/conf/rspamd/override.d/worker-proxy.inc @@ -1,6 +1,6 @@ bind_socket = "rspamd:9900"; milter = true; -upstream { +upstream "local" { name = "localhost"; default = true; hosts = "rspamd:11333" diff --git a/data/conf/sogo/custom-sogo.js b/data/conf/sogo/custom-sogo.js new file mode 100644 index 00000000..9ee6daba --- /dev/null +++ b/data/conf/sogo/custom-sogo.js @@ -0,0 +1,7 @@ +// Custom SOGo JS + +// Change the visible font-size in the editor, this does not change the font of a html message by default +CKEDITOR.addCss("body {font-size: 16px !important}"); + +// Enable scayt by default +//CKEDITOR.config.scayt_autoStartup = true; diff --git a/data/conf/sogo/plist_ldap b/data/conf/sogo/plist_ldap new file mode 100644 index 00000000..d585a494 --- /dev/null +++ b/data/conf/sogo/plist_ldap @@ -0,0 +1,28 @@ + diff --git a/data/conf/sogo/sogo-full.svg b/data/conf/sogo/sogo-full.svg new file mode 100644 index 00000000..98ff2fc3 --- /dev/null +++ b/data/conf/sogo/sogo-full.svg @@ -0,0 +1,44 @@ + + + +]> + + + diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf index 23fd8240..f9e9e077 100644 --- a/data/conf/sogo/sogo.conf +++ b/data/conf/sogo/sogo.conf @@ -11,10 +11,11 @@ SOGoDraftsFolderName = "Drafts"; SOGoJunkFolderName= "Junk"; SOGoMailDomain = "sogo.local"; - SOGoEnableEMailAlarms = NO; + SOGoEnableEMailAlarms = YES; SOGoFoldersSendEMailNotifications = YES; SOGoForwardEnabled = YES; - SOGoUIAdditionalJSFiles = (js/theme-blue.js); + SOGoUIAdditionalJSFiles = (js/custom-sogo.js); + SOGoEnablePublicAccess = YES; // Multi-domain setup // Domains are isolated, you can define visibility options here. @@ -25,7 +26,6 @@ // (domain3.tld, domain2.tld) // ); - SOGoIMAPServer = "imap://dovecot:143/?tls=YES"; SOGoSieveServer = "sieve://dovecot:4190/?tls=YES"; SOGoSMTPServer = "postfix:588"; WOPort = "0.0.0.0:20000"; @@ -39,17 +39,17 @@ SxVMemLimit = 384; - SOGoMaximumPingInterval = 354; + SOGoMaximumPingInterval = 3540; - SOGoInternalSyncInterval = 30; - SOGoMaximumSyncInterval = 354; + SOGoInternalSyncInterval = 45; + SOGoMaximumSyncInterval = 3540; // 100 seems to break some Android clients - //SOGoMaximumSyncWindowSize = 100; + //SOGoMaximumSyncWindowSize = 99; // This should do the trick for Outlook 2016 - SOGoMaximumSyncResponseSize = 2048; + SOGoMaximumSyncResponseSize = 512; - WOWatchDogRequestTimeout = 10; + WOWatchDogRequestTimeout = 20; WOListenQueueSize = 300; WONoDetach = YES; diff --git a/data/conf/unbound/unbound.conf b/data/conf/unbound/unbound.conf index b3c77671..e2e3e9eb 100644 --- a/data/conf/unbound/unbound.conf +++ b/data/conf/unbound/unbound.conf @@ -2,28 +2,42 @@ server: verbosity: 1 interface: 0.0.0.0 interface: ::0 - logfile: /dev/stdout + logfile: /dev/console do-ip4: yes do-ip6: yes do-udp: yes do-tcp: yes do-daemonize: no + #access-control: 0.0.0.0/0 allow access-control: 10.0.0.0/8 allow access-control: 172.16.0.0/12 allow access-control: 192.168.0.0/16 allow access-control: fc00::/7 allow access-control: fe80::/10 allow + #access-control: ::0/0 allow directory: "/etc/unbound" username: unbound auto-trust-anchor-file: trusted-key.key - private-address: 10.0.0.0/8 - private-address: 172.16.0.0/12 - private-address: 192.168.0.0/16 - private-address: 169.254.0.0/16 - private-address: fc00::/7 - private-address: fe80::/10 + #private-address: 10.0.0.0/8 + #private-address: 172.16.0.0/12 + #private-address: 192.168.0.0/16 + #private-address: 169.254.0.0/16 + #private-address: fc00::/7 + #private-address: fe80::/10 + # cache-min-ttl needs to be less or equal to cache-max-negative-ttl + cache-min-ttl: 5 + cache-max-negative-ttl: 60 root-hints: "/etc/unbound/root.hints" hide-identity: yes hide-version: yes max-udp-size: 4096 msg-buffer-size: 65552 + +remote-control: + control-enable: yes + control-interface: 127.0.0.1 + control-port: 8953 + server-key-file: "/etc/unbound/unbound_server.key" + server-cert-file: "/etc/unbound/unbound_server.pem" + control-key-file: "/etc/unbound/unbound_control.key" + control-cert-file: "/etc/unbound/unbound_control.pem" diff --git a/data/web/admin.php b/data/web/admin.php index d2734431..6826fec5 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -1,50 +1,50 @@
+ +
+
-
- -
- -
- - ↳ a-z A-Z - _ . -
+
+
+
+
+
+ + + +
-
- -
- -
-
-
- -
- -
-
-
-
- -
-
- -
+
+ + + +
:
@@ -68,7 +68,7 @@ $tfa_data = get_tfa();
:
- @@ -76,29 +76,30 @@ $tfa_data = get_tfa();
-
-
- -
@@ -118,19 +120,19 @@ $tfa_data = get_tfa();
-
+
@@ -156,13 +158,13 @@ $tfa_data = get_tfa();
- +
- +
@@ -180,6 +182,99 @@ $tfa_data = get_tfa();
+
+
+
+
+

+
+
+
+
+
+ + + +
+
+ +

+
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+ +
+
+
+

+
+
+
+
+
+ + + +
+
+ +

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+

+ +
+
+
+
+
+
+
@@ -202,7 +297,7 @@ $tfa_data = get_tfa();
- +
-

Domain: +

:

-

Selector ''

+

''

bit

-

โ†ช Private key

+

โ†ช


@@ -233,7 +328,7 @@ $tfa_data = get_tfa();
-

Domain:

+

:

-

@@ -284,7 +379,7 @@ $tfa_data = get_tfa();
-

Domain: +

:

Selector ''

bit

@@ -309,8 +404,8 @@ $tfa_data = get_tfa(); โ†ช
- - + +
- + - - + +
- - + +
- - + +
- +
- +
- - + +
@@ -384,7 +479,7 @@ $tfa_data = get_tfa();
- +
@@ -404,10 +499,10 @@ $tfa_data = get_tfa();
@@ -416,7 +511,7 @@ $tfa_data = get_tfa();
- +
- +
@@ -439,41 +534,41 @@ $tfa_data = get_tfa();
- +
- +
- +
/ - +
/ - +

- +
- +
- +
@@ -485,73 +580,37 @@ $tfa_data = get_tfa(); -

() - - - [] - [whitelist] - [blacklist] +

() - + + [] + [whitelist] + [blacklist] + + + +

- +

+ +

-

- -

- -

- -
-
- - -
-
Relayhosts
-
-

-
-
-
-
-
- - - -
-
- -

-
-
- - -
-
- - -
-
- - -
- -
@@ -559,46 +618,135 @@ $tfa_data = get_tfa();
- +
- +
- +
-
-
- +
+
+
+ + +
+
+
+
+ + +
+
- +
+
+ + + +
+ +
+
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
+ +
+
+
+

+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+ + + +
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
-
Rspamd settings map
+
- Active settings map - -
+ + + +
+ +
+
@@ -649,19 +797,19 @@ $tfa_data = get_tfa();
- +
- +
- - + +

- +

- + + + +
-
-
- - -
-
- - -
-
- - -
-
- - -
- -
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ + +
+
+ + +
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+
+ + + + + +
+
+
+
+
+ + + + - - add('/web/js/site/admin.js'); require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; } else { header('Location: /'); diff --git a/data/web/autoconfig.php b/data/web/autoconfig.php index 58d6fec1..95952df0 100644 --- a/data/web/autoconfig.php +++ b/data/web/autoconfig.php @@ -1,5 +1,5 @@ PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, diff --git a/data/web/css/bootstrap-slider.min.css b/data/web/css/bootstrap-slider.min.css deleted file mode 100644 index e55300b2..00000000 --- a/data/web/css/bootstrap-slider.min.css +++ /dev/null @@ -1,41 +0,0 @@ -/*! ======================================================= - VERSION 9.7.2 -========================================================= */ -/*! ========================================================= - * bootstrap-slider.js - * - * Maintainers: - * Kyle Kemp - * - Twitter: @seiyria - * - Github: seiyria - * Rohit Kalkur - * - Twitter: @Rovolutionary - * - Github: rovolution - * - * ========================================================= - * - * bootstrap-slider is released under the MIT License - * Copyright (c) 2017 Kyle Kemp, Rohit Kalkur, and contributors - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{position:relative;top:50%;transform:translateY(-50%);border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#0480be;margin-top:0}.slider.slider-horizontal .slider-tick-container{white-space:nowrap;position:absolute;top:0;left:0;width:100%}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-horizontal.slider-rtl .slider-track{left:initial;right:0}.slider.slider-horizontal.slider-rtl .slider-tick,.slider.slider-horizontal.slider-rtl .slider-handle{margin-left:initial;margin-right:-10px}.slider.slider-horizontal.slider-rtl .slider-tick-container{left:initial;right:0}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;left:25%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#0480be;border-right-color:#0480be;margin-left:0;margin-right:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-vertical.slider-rtl .slider-track{left:initial;right:25%}.slider.slider-vertical.slider-rtl .slider-selection{left:initial;right:0}.slider.slider-vertical.slider-rtl .slider-tick.triangle,.slider.slider-vertical.slider-rtl .slider-handle.triangle{border-width:10px 10px 10px 0}.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label{padding-left:initial;padding-right:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;top:0;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:-o-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:linear-gradient(to bottom,#149bdf 0,#0480be 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0);opacity:1} \ No newline at end of file diff --git a/data/web/css/bootstrap.min.css b/data/web/css/bootstrap.min.css deleted file mode 100644 index ac7801f8..00000000 --- a/data/web/css/bootstrap.min.css +++ /dev/null @@ -1,10 +0,0 @@ - * bootswatch v3.3.7 - * Homepage: http://bootswatch.com - * Copyright 2012-2017 Thomas Park - * Licensed under MIT - * Based on Bootstrap -*//*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#158cba;text-decoration:none}a:hover,a:focus{color:#158cba;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:5px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:400;line-height:1.1;color:#333333}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#ff851b;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#158cba}a.text-primary:hover,a.text-primary:focus{color:#106a8c}.text-success{color:#ffffff}a.text-success:hover,a.text-success:focus{color:#e6e6e6}.text-info{color:#ffffff}a.text-info:hover,a.text-info:focus{color:#e6e6e6}.text-warning{color:#ffffff}a.text-warning:hover,a.text-warning:focus{color:#e6e6e6}.text-danger{color:#ffffff}a.text-danger:hover,a.text-danger:focus{color:#e6e6e6}.bg-primary{color:#fff;background-color:#158cba}a.bg-primary:hover,a.bg-primary:focus{background-color:#106a8c}.bg-success{background-color:#28b62c}a.bg-success:hover,a.bg-success:focus{background-color:#1f8c22}.bg-info{background-color:#75caeb}a.bg-info:hover,a.bg-info:focus{background-color:#48b9e5}.bg-warning{background-color:#ff851b}a.bg-warning:hover,a.bg-warning:focus{background-color:#e76b00}.bg-danger{background-color:#ff4136}a.bg-danger:hover,a.bg-danger:focus{background-color:#ff1103}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:2px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1450px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1450px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #eeeeee}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #eeeeee}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #eeeeee}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#28b62c}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#23a127}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#75caeb}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#5fc1e8}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#ff851b}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#ff7701}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#ff4136}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ff291c}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #eeeeee}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:8px;font-size:14px;line-height:1.42857143;color:#555555}.form-control{display:block;width:100%;height:38px;padding:7px 12px;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff;background-image:none;border:1px solid #e7e7e7;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:38px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:28px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:52px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:8px;padding-bottom:8px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-sm{height:28px;line-height:28px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.form-group-sm select.form-control{height:28px;line-height:28px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:28px;min-height:32px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-lg{height:52px;line-height:52px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.form-group-lg select.form-control{height:52px;line-height:52px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:52px;min-height:38px;padding:14px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:47.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:38px;height:38px;line-height:38px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:52px;height:52px;line-height:52px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:28px;height:28px;line-height:28px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#ffffff}.has-success .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-success .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#28b62c}.has-success .form-control-feedback{color:#ffffff}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#ffffff}.has-warning .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-warning .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#ff851b}.has-warning .form-control-feedback{color:#ffffff}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#ffffff}.has-error .form-control{border-color:#ffffff;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#e6e6e6;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-error .input-group-addon{color:#ffffff;border-color:#ffffff;background-color:#ff4136}.has-error .form-control-feedback{color:#ffffff}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#959595}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:8px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:28px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:8px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:5px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:7px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#555555;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.btn-default:focus,.btn-default.focus{color:#555555;background-color:#d5d5d5;border-color:#a2a2a2}.btn-default:hover{color:#555555;background-color:#d5d5d5;border-color:#c3c3c3}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#555555;background-color:#d5d5d5;border-color:#c3c3c3}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#555555;background-color:#c3c3c3;border-color:#a2a2a2}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#eeeeee;border-color:#e2e2e2}.btn-default .badge{color:#eeeeee;background-color:#555555}.btn-primary{color:#ffffff;background-color:#158cba;border-color:#127ba3}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#106a8c;border-color:#052531}.btn-primary:hover{color:#ffffff;background-color:#106a8c;border-color:#0c516c}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#106a8c;border-color:#0c516c}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#0c516c;border-color:#052531}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#158cba;border-color:#127ba3}.btn-primary .badge{color:#158cba;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#28b62c;border-color:#23a127}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#1f8c22;border-color:#0c390e}.btn-success:hover{color:#ffffff;background-color:#1f8c22;border-color:#186f1b}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#1f8c22;border-color:#186f1b}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#186f1b;border-color:#0c390e}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#28b62c;border-color:#23a127}.btn-success .badge{color:#28b62c;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#75caeb;border-color:#5fc1e8}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#48b9e5;border-color:#1984ae}.btn-info:hover{color:#ffffff;background-color:#48b9e5;border-color:#29ade0}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#48b9e5;border-color:#29ade0}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#29ade0;border-color:#1984ae}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#75caeb;border-color:#5fc1e8}.btn-info .badge{color:#75caeb;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#ff851b;border-color:#ff7701}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#e76b00;border-color:#813c00}.btn-warning:hover{color:#ffffff;background-color:#e76b00;border-color:#c35b00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#e76b00;border-color:#c35b00}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#c35b00;border-color:#813c00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#ff851b;border-color:#ff7701}.btn-warning .badge{color:#ff851b;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#ff4136;border-color:#ff291c}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#ff1103;border-color:#9c0900}.btn-danger:hover{color:#ffffff;background-color:#ff1103;border-color:#de0c00}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#ff1103;border-color:#de0c00}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#de0c00;border-color:#9c0900}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#ff4136;border-color:#ff291c}.btn-danger .badge{color:#ff4136;background-color:#ffffff}.btn-link{color:#158cba;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#158cba;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.btn-sm,.btn-group-sm>.btn{padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:2px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:0.35s;-o-transition-duration:0.35s;transition-duration:0.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#ffffff;border:1px solid #cccccc;border:1px solid #e7e7e7;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#eeeeee}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#333333;background-color:transparent}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;outline:0;background-color:#158cba}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#eeeeee}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:52px;line-height:52px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:28px;line-height:28px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:7px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555555;text-align:center;background-color:#eeeeee;border:1px solid #e7e7e7;border-radius:4px}.input-group-addon.input-sm{padding:4px 10px;font-size:12px;border-radius:2px}.input-group-addon.input-lg{padding:13px 16px;font-size:18px;border-radius:5px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#ffffff}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#ffffff;border-color:#158cba}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #e7e7e7}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #e7e7e7}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555555;background-color:#ffffff;border:1px solid #e7e7e7;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#158cba}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:6px;margin-bottom:6px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:6px;margin-bottom:6px}.navbar-btn.btn-sm{margin-top:11px;margin-bottom:11px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#333333}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-default .navbar-text{color:#555555}.navbar-default .navbar-nav>li>a{color:#999999}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-default .navbar-toggle{border-color:#eeeeee}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ffffff}.navbar-default .navbar-toggle .icon-bar{background-color:#999999}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:transparent;color:#333333}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-default .navbar-link{color:#999999}.navbar-default .navbar-link:hover{color:#333333}.navbar-default .btn-link{color:#999999}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#eeeeee}.navbar-inverse{background-color:#ffffff;border-color:#e6e6e6}.navbar-inverse .navbar-brand{color:#999999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-text{color:#999999}.navbar-inverse .navbar-nav>li>a{color:#999999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#eeeeee}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#eeeeee}.navbar-inverse .navbar-toggle .icon-bar{background-color:#999999}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#ededed}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:transparent;color:#333333}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-inverse .navbar-link{color:#999999}.navbar-inverse .navbar-link:hover{color:#333333}.navbar-inverse .btn-link{color:#999999}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#333333}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#eeeeee}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#fafafa;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:">\00a0";padding:0 5px;color:#999999}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:7px 12px;line-height:1.42857143;text-decoration:none;color:#555555;background-color:#eeeeee;border:1px solid #e2e2e2;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;background-color:#158cba;border-color:#127ba3;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;background-color:#eeeeee;border-color:#e2e2e2;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:13px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:5px;border-top-left-radius:5px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:5px;border-top-right-radius:5px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:2px;border-top-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:2px;border-top-right-radius:2px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#eeeeee;border:1px solid #e2e2e2;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;background-color:#eeeeee;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#158cba}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#106a8c}.label-success{background-color:#28b62c}.label-success[href]:hover,.label-success[href]:focus{background-color:#1f8c22}.label-info{background-color:#75caeb}.label-info[href]:hover,.label-info[href]:focus{background-color:#48b9e5}.label-warning{background-color:#ff851b}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#e76b00}.label-danger{background-color:#ff4136}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#ff1103}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:normal;color:#ffffff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#158cba;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#158cba;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#fafafa}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#e1e1e1}.container .jumbotron,.container-fluid .jumbotron{border-radius:5px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#158cba}.thumbnail .caption{padding:9px;color:#555555}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#28b62c;border-color:#24a528;color:#ffffff}.alert-success hr{border-top-color:#209023}.alert-success .alert-link{color:#e6e6e6}.alert-info{background-color:#75caeb;border-color:#40b5e3;color:#ffffff}.alert-info hr{border-top-color:#29ade0}.alert-info .alert-link{color:#e6e6e6}.alert-warning{background-color:#ff851b;border-color:#ff7701;color:#ffffff}.alert-warning hr{border-top-color:#e76b00}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{background-color:#ff4136;border-color:#ff1103;color:#ffffff}.alert-danger hr{border-top-color:#e90d00}.alert-danger .alert-link{color:#e6e6e6}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#fafafa;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#158cba;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#28b62c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#75caeb}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#ff851b}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#ff4136}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #eeeeee}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eeeeee;color:#999999;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#158cba;border-color:#158cba}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#a6dff5}.list-group-item-success{color:#ffffff;background-color:#28b62c}a.list-group-item-success,button.list-group-item-success{color:#ffffff}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#ffffff;background-color:#23a127}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-info{color:#ffffff;background-color:#75caeb}a.list-group-item-info,button.list-group-item-info{color:#ffffff}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#ffffff;background-color:#5fc1e8}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-warning{color:#ffffff;background-color:#ff851b}a.list-group-item-warning,button.list-group-item-warning{color:#ffffff}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#ffffff;background-color:#ff7701}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-danger{color:#ffffff;background-color:#ff4136}a.list-group-item-danger,button.list-group-item-danger{color:#ffffff}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#ffffff;background-color:#ff291c}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid transparent;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #eeeeee}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid transparent}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid transparent}.panel-default{border-color:transparent}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:transparent}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-primary{border-color:transparent}.panel-primary>.panel-heading{color:#ffffff;background-color:#158cba;border-color:transparent}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-primary>.panel-heading .badge{color:#158cba;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-success{border-color:transparent}.panel-success>.panel-heading{color:#ffffff;background-color:#28b62c;border-color:transparent}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-success>.panel-heading .badge{color:#28b62c;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-info{border-color:transparent}.panel-info>.panel-heading{color:#ffffff;background-color:#75caeb;border-color:transparent}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-info>.panel-heading .badge{color:#75caeb;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-warning{border-color:transparent}.panel-warning>.panel-heading{color:#ffffff;background-color:#ff851b;border-color:transparent}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-warning>.panel-heading .badge{color:#ff851b;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-danger{border-color:transparent}.panel-danger>.panel-heading{color:#ffffff;background-color:#ff4136;border-color:transparent}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-danger>.panel-heading .badge{color:#ff4136;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#fafafa;border:1px solid #e8e8e8;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:5px}.well-sm{padding:9px;border-radius:2px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#ffffff;text-decoration:none;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;border:1px solid #eeeeee;border:1px solid rgba(0,0,0,0.05);border-radius:5px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:0.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#ffffff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:4px 4px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#ffffff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#ffffff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#ffffff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.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{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:0.5;filter:alpha(opacity=50);font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, from(rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #ffffff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#ffffff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1449px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1449px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1449px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1449px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1450px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1450px){.visible-lg-block{display:block !important}}@media (min-width:1450px){.visible-lg-inline{display:inline !important}}@media (min-width:1450px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1449px){.hidden-md{display:none !important}}@media (min-width:1450px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border-width:0 1px 4px 1px}.btn{padding:9px 12px 7px;border-width:0 1px 4px 1px;font-size:12px;font-weight:bold;line-height:1.5;text-transform:uppercase}.btn:hover{margin-top:1px;border-bottom-width:3px}.btn:active{margin-top:2px;border-bottom-width:2px;-webkit-box-shadow:none;box-shadow:none}.btn-lg,.btn-group-lg>.btn{padding:15px 16px 13px;line-height:15px}.btn-sm,.btn-group-sm>.btn{padding:6px 10px 4px}.btn-xs,.btn-group-xs>.btn{padding:3px 5px 1px}.btn-default:hover,.btn-default:focus,.btn-group.open .dropdown-toggle.btn-default{background-color:#eeeeee;border-color:#e2e2e2}.btn-primary:hover,.btn-primary:focus,.btn-group.open .dropdown-toggle.btn-primary{background-color:#158cba;border-color:#127ba3}.btn-success:hover,.btn-success:focus,.btn-group.open .dropdown-toggle.btn-success{background-color:#28b62c;border-color:#23a127}.btn-info:hover,.btn-info:focus,.btn-group.open .dropdown-toggle.btn-info{background-color:#75caeb;border-color:#5fc1e8}.btn-warning:hover,.btn-warning:focus,.btn-group.open .dropdown-toggle.btn-warning{background-color:#ff851b;border-color:#ff7701}.btn-danger:hover,.btn-danger:focus,.btn-group.open .dropdown-toggle.btn-danger{background-color:#ff4136;border-color:#ff291c}.btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.navbar-btn:hover{margin-top:8px}.navbar-btn:active{margin-top:9px}.navbar-btn.btn-sm:hover{margin-top:11px}.navbar-btn.btn-sm:active{margin-top:12px}.navbar-btn.btn-xs:hover{margin-top:15px}.navbar-btn.btn-xs:active{margin-top:16px}.btn-group-vertical .btn+.btn:hover{border-top-width:1px}.btn-group-vertical .btn+.btn:active{border-top-width:2px}.text-primary,.text-primary:hover{color:#158cba}.text-success,.text-success:hover{color:#28b62c}.text-danger,.text-danger:hover{color:#ff4136}.text-warning,.text-warning:hover{color:#ff851b}.text-info,.text-info:hover{color:#75caeb}table a:not(.btn),.table a:not(.btn){text-decoration:underline}table .dropdown-menu a,.table .dropdown-menu a{text-decoration:none}table .success,.table .success,table .warning,.table .warning,table .danger,.table .danger,table .info,.table .info{color:#fff}table .success a:not(.btn),.table .success a:not(.btn),table .warning a:not(.btn),.table .warning a:not(.btn),table .danger a:not(.btn),.table .danger a:not(.btn),table .info a:not(.btn),.table .info a:not(.btn){color:#fff}table:not(.table-bordered)>thead>tr>th,.table:not(.table-bordered)>thead>tr>th,table:not(.table-bordered)>tbody>tr>th,.table:not(.table-bordered)>tbody>tr>th,table:not(.table-bordered)>tfoot>tr>th,.table:not(.table-bordered)>tfoot>tr>th,table:not(.table-bordered)>thead>tr>td,.table:not(.table-bordered)>thead>tr>td,table:not(.table-bordered)>tbody>tr>td,.table:not(.table-bordered)>tbody>tr>td,table:not(.table-bordered)>tfoot>tr>td,.table:not(.table-bordered)>tfoot>tr>td{border-color:transparent}.form-control{-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}label{font-weight:normal}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label,.has-warning .form-control-feedback{color:#ff851b}.has-warning .form-control,.has-warning .form-control:focus{border:1px solid #ff851b;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-warning .input-group-addon{border:1px solid #ff851b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label,.has-error .form-control-feedback{color:#ff4136}.has-error .form-control,.has-error .form-control:focus{border:1px solid #ff4136;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-error .input-group-addon{border:1px solid #ff4136}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label,.has-success .form-control-feedback{color:#28b62c}.has-success .form-control,.has-success .form-control:focus{border:1px solid #28b62c;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.075);box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-success .input-group-addon{border:1px solid #28b62c}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{border-color:transparent}.nav-tabs>li>a{margin-top:6px;border-color:#e7e7e7;color:#333333;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus,.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus,.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{padding-bottom:16px;margin-top:0}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{border-color:#e7e7e7}.nav-tabs>li.disabled>a:hover,.nav-tabs>li.disabled>a:focus{padding-top:10px;padding-bottom:10px;margin-top:6px}.nav-tabs.nav-justified>li{vertical-align:bottom}.dropdown-menu{margin-top:0;border-width:0 1px 4px 1px;border-top-width:1px;-webkit-box-shadow:none;box-shadow:none}.breadcrumb{border-color:#ededed;border-style:solid;border-width:0 1px 4px 1px}.pagination>li>a,.pager>li>a,.pagination>li>span,.pager>li>span{position:relative;top:0;border-width:0 1px 4px 1px;color:#555555;font-size:12px;font-weight:bold;text-transform:uppercase}.pagination>li>a:hover,.pager>li>a:hover,.pagination>li>span:hover,.pager>li>span:hover{top:1px;border-bottom-width:3px}.pagination>li>a:active,.pager>li>a:active,.pagination>li>span:active,.pager>li>span:active{top:2px;border-bottom-width:2px}.pagination>.disabled>a:hover,.pager>.disabled>a:hover,.pagination>.disabled>span:hover,.pager>.disabled>span:hover{top:0;border-width:0 1px 4px 1px}.pagination>.disabled>a:active,.pager>.disabled>a:active,.pagination>.disabled>span:active,.pager>.disabled>span:active{top:0;border-width:0 1px 4px 1px}.pager>li>a,.pager>li>span,.pager>.disabled>a,.pager>.disabled>span,.pager>li>a:hover,.pager>li>span:hover,.pager>.disabled>a:hover,.pager>.disabled>span:hover,.pager>li>a:active,.pager>li>span:active,.pager>.disabled>a:active,.pager>.disabled>span:active{border-left-width:2px;border-right-width:2px}.close{color:#fff;text-decoration:none;opacity:0.4}.close:hover,.close:focus{color:#fff;opacity:1}.alert{border-width:0 1px 4px 1px}.alert .alert-link{font-weight:normal;color:#fff;text-decoration:underline}.label{font-weight:normal}.progress{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.1);box-shadow:inset 0 2px 0 rgba(0,0,0,0.1)}.progress-bar{-webkit-box-shadow:inset 0 -4px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -4px 0 rgba(0,0,0,0.15)}.well{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.05);box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{border-color:#eeeeee}a.list-group-item-success.active{background-color:#28b62c}a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{background-color:#23a127}a.list-group-item-warning.active{background-color:#ff851b}a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{background-color:#ff7701}a.list-group-item-danger.active{background-color:#ff4136}a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{background-color:#ff291c}.jumbotron{border:1px solid #e7e7e7;-webkit-box-shadow:inset 0 2px 0 rgba(0,0,0,0.05);box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}.panel{border:1px solid #e7e7e7;border-width:0 1px 4px 1px}.panel-default .close{color:#555555}.modal .close{color:#555555}.popover{color:#555555} \ No newline at end of file diff --git a/data/web/css/build/001-bootstrap.min.css b/data/web/css/build/001-bootstrap.min.css new file mode 100644 index 00000000..769bf30c --- /dev/null +++ b/data/web/css/build/001-bootstrap.min.css @@ -0,0 +1,11 @@ +/*! + * bootswatch v3.4.1 + * Homepage: http://bootswatch.com + * Copyright 2012-2019 Thomas Park + * Licensed under MIT + * Based on Bootstrap +*//*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{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) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:"Glyphicons Halflings";src:url("/fonts/glyphicons-halflings-regular.eot");src:url("/fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("/fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("/fonts/glyphicons-halflings-regular.woff") format("woff"),url("/fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{box-sizing:border-box}*:before,*:after{box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#158cba;text-decoration:none}a:hover,a:focus{color:#158cba;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:5px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:400;line-height:1.1;color:#333333}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{padding:.2em;background-color:#ff851b}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#999999}.text-primary{color:#158cba}a.text-primary:hover,a.text-primary:focus{color:#106a8c}.text-success{color:#ffffff}a.text-success:hover,a.text-success:focus{color:#e6e6e6}.text-info{color:#ffffff}a.text-info:hover,a.text-info:focus{color:#e6e6e6}.text-warning{color:#ffffff}a.text-warning:hover,a.text-warning:focus{color:#e6e6e6}.text-danger{color:#ffffff}a.text-danger:hover,a.text-danger:focus{color:#e6e6e6}.bg-primary{color:#fff;background-color:#158cba}a.bg-primary:hover,a.bg-primary:focus{background-color:#106a8c}.bg-success{background-color:#28b62c}a.bg-success:hover,a.bg-success:focus{background-color:#1f8c22}.bg-info{background-color:#75caeb}a.bg-info:hover,a.bg-info:focus{background-color:#48b9e5}.bg-warning{background-color:#ff851b}a.bg-warning:hover,a.bg-warning:focus{background-color:#e76b00}.bg-danger{background-color:#ff4136}a.bg-danger:hover,a.bg-danger:focus{background-color:#ff1103}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eeeeee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:""}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:2px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*="col-"]{padding-right:0;padding-left:0}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}table col[class*="col-"]{position:static;display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #eeeeee}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #eeeeee}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #eeeeee}.table .table{background-color:#ffffff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #eeeeee}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#28b62c}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#23a127}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#75caeb}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#5fc1e8}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#ff851b}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#ff7701}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#ff4136}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ff291c}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #eeeeee}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type="search"]{box-sizing:border-box;-webkit-appearance:none;appearance:none}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:8px;font-size:14px;line-height:1.42857143;color:#555555}.form-control{display:block;width:100%;height:38px;padding:7px 12px;font-size:14px;line-height:1.42857143;color:#555555;background-color:#ffffff;background-image:none;border:1px solid #e7e7e7;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eeeeee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:38px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:28px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:52px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:8px;padding-bottom:8px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-sm{height:28px;line-height:28px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.form-group-sm select.form-control{height:28px;line-height:28px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:28px;min-height:32px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-lg{height:52px;line-height:52px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.form-group-lg select.form-control{height:52px;line-height:52px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:52px;min-height:38px;padding:14px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:47.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:38px;height:38px;line-height:38px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:52px;height:52px;line-height:52px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:28px;height:28px;line-height:28px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#ffffff}.has-success .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-success .input-group-addon{color:#ffffff;background-color:#28b62c;border-color:#ffffff}.has-success .form-control-feedback{color:#ffffff}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#ffffff}.has-warning .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-warning .input-group-addon{color:#ffffff;background-color:#ff851b;border-color:#ffffff}.has-warning .form-control-feedback{color:#ffffff}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#ffffff}.has-error .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-error .input-group-addon{color:#ffffff;background-color:#ff4136;border-color:#ffffff}.has-error .form-control-feedback{color:#ffffff}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#959595}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:8px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:28px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:8px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:5px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:7px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#555555;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:0.65;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.btn-default:focus,.btn-default.focus{color:#555555;background-color:#d5d5d5;border-color:#a2a2a2}.btn-default:hover{color:#555555;background-color:#d5d5d5;border-color:#c3c3c3}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#555555;background-color:#d5d5d5;background-image:none;border-color:#c3c3c3}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#555555;background-color:#c3c3c3;border-color:#a2a2a2}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#eeeeee;border-color:#e2e2e2}.btn-default .badge{color:#eeeeee;background-color:#555555}.btn-primary{color:#ffffff;background-color:#158cba;border-color:#127ba3}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#106a8c;border-color:#052531}.btn-primary:hover{color:#ffffff;background-color:#106a8c;border-color:#0c516c}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#106a8c;background-image:none;border-color:#0c516c}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#ffffff;background-color:#0c516c;border-color:#052531}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#158cba;border-color:#127ba3}.btn-primary .badge{color:#158cba;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#28b62c;border-color:#23a127}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#1f8c22;border-color:#0c390e}.btn-success:hover{color:#ffffff;background-color:#1f8c22;border-color:#186f1b}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#1f8c22;background-image:none;border-color:#186f1b}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#ffffff;background-color:#186f1b;border-color:#0c390e}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#28b62c;border-color:#23a127}.btn-success .badge{color:#28b62c;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#75caeb;border-color:#5fc1e8}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#48b9e5;border-color:#1984ae}.btn-info:hover{color:#ffffff;background-color:#48b9e5;border-color:#29ade0}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#48b9e5;background-image:none;border-color:#29ade0}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#ffffff;background-color:#29ade0;border-color:#1984ae}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#75caeb;border-color:#5fc1e8}.btn-info .badge{color:#75caeb;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#ff851b;border-color:#ff7701}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#e76b00;border-color:#813c00}.btn-warning:hover{color:#ffffff;background-color:#e76b00;border-color:#c35b00}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#e76b00;background-image:none;border-color:#c35b00}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#ffffff;background-color:#c35b00;border-color:#813c00}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#ff851b;border-color:#ff7701}.btn-warning .badge{color:#ff851b;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#ff4136;border-color:#ff291c}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#ff1103;border-color:#9c0900}.btn-danger:hover{color:#ffffff;background-color:#ff1103;border-color:#de0c00}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#ff1103;background-image:none;border-color:#de0c00}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#ffffff;background-color:#de0c00;border-color:#9c0900}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#ff4136;border-color:#ff291c}.btn-danger .badge{color:#ff4136;background-color:#ffffff}.btn-link{font-weight:400;color:#158cba;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#158cba;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}.btn-sm,.btn-group-sm>.btn{padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:2px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;transition:opacity 0.15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;transition-property:height, visibility;transition-duration:0.35s;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#ffffff;background-clip:padding-box;border:1px solid #cccccc;border:1px solid #e7e7e7;border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,0.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#eeeeee}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#333333;text-decoration:none;background-color:transparent}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;background-color:#158cba;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#eeeeee}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999999;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:52px;padding:13px 16px;font-size:18px;line-height:1.3333333;border-radius:5px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:52px;line-height:52px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:28px;padding:4px 10px;font-size:12px;line-height:1.5;border-radius:2px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:28px;line-height:28px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:7px 12px;font-size:14px;font-weight:400;line-height:1;color:#555555;text-align:center;background-color:#eeeeee;border:1px solid #e7e7e7;border-radius:4px}.input-group-addon.input-sm{padding:4px 10px;font-size:12px;border-radius:2px}.input-group-addon.input-lg{padding:13px 16px;font-size:18px;border-radius:5px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#ffffff}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#ffffff;border-color:#158cba}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #e7e7e7}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #e7e7e7}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555555;cursor:default;background-color:#ffffff;border:1px solid #e7e7e7;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#ffffff;background-color:#158cba}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #e7e7e7}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #e7e7e7;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:6px;margin-bottom:6px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:6px;margin-bottom:6px}.navbar-btn.btn-sm{margin-top:11px;margin-bottom:11px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#333333}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-default .navbar-text{color:#555555}.navbar-default .navbar-nav>li>a{color:#999999}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#333333;background-color:transparent}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#eeeeee}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ffffff}.navbar-default .navbar-toggle .icon-bar{background-color:#999999}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#999999}.navbar-default .navbar-link:hover{color:#333333}.navbar-default .btn-link{color:#999999}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#eeeeee}.navbar-inverse{background-color:#ffffff;border-color:#e6e6e6}.navbar-inverse .navbar-brand{color:#999999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-text{color:#999999}.navbar-inverse .navbar-nav>li>a{color:#999999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#eeeeee;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#333333;background-color:transparent}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#e6e6e6}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#333333;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#eeeeee;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#eeeeee}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#eeeeee}.navbar-inverse .navbar-toggle .icon-bar{background-color:#999999}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#ededed}.navbar-inverse .navbar-link{color:#999999}.navbar-inverse .navbar-link:hover{color:#333333}.navbar-inverse .btn-link{color:#999999}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#333333}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#eeeeee}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#fafafa;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#999999;content:">\00a0"}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:7px 12px;margin-left:-1px;line-height:1.42857143;color:#555555;text-decoration:none;background-color:#eeeeee;border:1px solid #e2e2e2}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#555555;background-color:#eeeeee;border-color:#e2e2e2}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#ffffff;cursor:default;background-color:#158cba;border-color:#127ba3}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;cursor:not-allowed;background-color:#eeeeee;border-color:#e2e2e2}.pagination-lg>li>a,.pagination-lg>li>span{padding:13px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:5px;border-bottom-left-radius:5px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:5px;border-bottom-right-radius:5px}.pagination-sm>li>a,.pagination-sm>li>span{padding:4px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:2px;border-bottom-left-radius:2px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:2px;border-bottom-right-radius:2px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#eeeeee;border:1px solid #e2e2e2;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eeeeee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999999;cursor:not-allowed;background-color:#eeeeee}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#158cba}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#106a8c}.label-success{background-color:#28b62c}.label-success[href]:hover,.label-success[href]:focus{background-color:#1f8c22}.label-info{background-color:#75caeb}.label-info[href]:hover,.label-info[href]:focus{background-color:#48b9e5}.label-warning{background-color:#ff851b}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#e76b00}.label-danger{background-color:#ff4136}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#ff1103}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:normal;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#158cba;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#158cba;background-color:#ffffff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#fafafa}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#e1e1e1}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:5px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#ffffff;border:1px solid #eeeeee;border-radius:4px;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#158cba}.thumbnail .caption{padding:9px;color:#555555}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#ffffff;background-color:#28b62c;border-color:#24a528}.alert-success hr{border-top-color:#209023}.alert-success .alert-link{color:#e6e6e6}.alert-info{color:#ffffff;background-color:#75caeb;border-color:#40b5e3}.alert-info hr{border-top-color:#29ade0}.alert-info .alert-link{color:#e6e6e6}.alert-warning{color:#ffffff;background-color:#ff851b;border-color:#ff7701}.alert-warning hr{border-top-color:#e76b00}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{color:#ffffff;background-color:#ff4136;border-color:#ff1103}.alert-danger hr{border-top-color:#e90d00}.alert-danger .alert-link{color:#e6e6e6}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#fafafa;border-radius:4px;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#158cba;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#28b62c}.progress-striped .progress-bar-success{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#75caeb}.progress-striped .progress-bar-info{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#ff851b}.progress-striped .progress-bar-warning{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#ff4136}.progress-striped .progress-bar-danger{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#ffffff;border:1px solid #eeeeee}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#999999;cursor:not-allowed;background-color:#eeeeee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#158cba;border-color:#158cba}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#a6dff5}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{color:#555555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#ffffff;background-color:#28b62c}a.list-group-item-success,button.list-group-item-success{color:#ffffff}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#ffffff;background-color:#23a127}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-info{color:#ffffff;background-color:#75caeb}a.list-group-item-info,button.list-group-item-info{color:#ffffff}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#ffffff;background-color:#5fc1e8}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-warning{color:#ffffff;background-color:#ff851b}a.list-group-item-warning,button.list-group-item-warning{color:#ffffff}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#ffffff;background-color:#ff7701}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-danger{color:#ffffff;background-color:#ff4136}a.list-group-item-danger,button.list-group-item-danger{color:#ffffff}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#ffffff;background-color:#ff291c}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#ffffff;border-color:#ffffff}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#ffffff;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid transparent;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #eeeeee}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid transparent}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid transparent}.panel-default{border-color:transparent}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:transparent}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-primary{border-color:transparent}.panel-primary>.panel-heading{color:#ffffff;background-color:#158cba;border-color:transparent}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-primary>.panel-heading .badge{color:#158cba;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-success{border-color:transparent}.panel-success>.panel-heading{color:#ffffff;background-color:#28b62c;border-color:transparent}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-success>.panel-heading .badge{color:#28b62c;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-info{border-color:transparent}.panel-info>.panel-heading{color:#ffffff;background-color:#75caeb;border-color:transparent}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-info>.panel-heading .badge{color:#75caeb;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-warning{border-color:transparent}.panel-warning>.panel-heading{color:#ffffff;background-color:#ff851b;border-color:transparent}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-warning>.panel-heading .badge{color:#ff851b;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.panel-danger{border-color:transparent}.panel-danger>.panel-heading{color:#ffffff;background-color:#ff4136;border-color:transparent}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:transparent}.panel-danger>.panel-heading .badge{color:#ff4136;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:transparent}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#fafafa;border:1px solid #e8e8e8;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:5px}.well-sm{padding:9px;border-radius:2px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=20);opacity:0.2}.close:hover,.close:focus{color:#ffffff;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:0.5}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);transform:translate(0, -25%);transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#ffffff;background-clip:padding-box;border:1px solid #eeeeee;border:1px solid rgba(0,0,0,0.05);border-radius:5px;box-shadow:0 3px 9px rgba(0,0,0,0.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:0.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{padding:20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:0.9}.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.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#ffffff;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:5px;box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#ffffff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#ffffff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999999;border-bottom-color:rgba(0,0,0,0.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#ffffff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#ffffff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:4px 4px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:0.5}.carousel-control.left{background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#ffffff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:0.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #ffffff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#ffffff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}.navbar{border-width:0 1px 4px 1px}.btn{padding:9px 12px 7px;border-width:0 1px 4px 1px;font-size:12px;font-weight:bold;text-transform:uppercase}.btn:hover{margin-top:1px;border-bottom-width:3px}.btn:active{margin-top:2px;border-bottom-width:2px;box-shadow:none}.btn-lg,.btn-group-lg>.btn{padding:15px 16px 13px;line-height:15px}.btn-sm,.btn-group-sm>.btn{padding:6px 10px 4px}.btn-xs,.btn-group-xs>.btn{padding:3px 5px 1px}.btn-default:hover,.btn-default:focus,.btn-group.open .dropdown-toggle.btn-default{background-color:#eeeeee;border-color:#e2e2e2}.btn-primary:hover,.btn-primary:focus,.btn-group.open .dropdown-toggle.btn-primary{background-color:#158cba;border-color:#127ba3}.btn-success:hover,.btn-success:focus,.btn-group.open .dropdown-toggle.btn-success{background-color:#28b62c;border-color:#23a127}.btn-info:hover,.btn-info:focus,.btn-group.open .dropdown-toggle.btn-info{background-color:#75caeb;border-color:#5fc1e8}.btn-warning:hover,.btn-warning:focus,.btn-group.open .dropdown-toggle.btn-warning{background-color:#ff851b;border-color:#ff7701}.btn-danger:hover,.btn-danger:focus,.btn-group.open .dropdown-toggle.btn-danger{background-color:#ff4136;border-color:#ff291c}.btn-group.open .dropdown-toggle{box-shadow:none}.navbar-btn:hover{margin-top:8px}.navbar-btn:active{margin-top:9px}.navbar-btn.btn-sm:hover{margin-top:11px}.navbar-btn.btn-sm:active{margin-top:12px}.navbar-btn.btn-xs:hover{margin-top:15px}.navbar-btn.btn-xs:active{margin-top:16px}.btn-group-vertical .btn+.btn:hover{border-top-width:1px}.btn-group-vertical .btn+.btn:active{border-top-width:2px}.text-primary,.text-primary:hover{color:#158cba}.text-success,.text-success:hover{color:#28b62c}.text-danger,.text-danger:hover{color:#ff4136}.text-warning,.text-warning:hover{color:#ff851b}.text-info,.text-info:hover{color:#75caeb}table a:not(.btn),.table a:not(.btn){text-decoration:underline}table .dropdown-menu a,.table .dropdown-menu a{text-decoration:none}table .success,.table .success,table .warning,.table .warning,table .danger,.table .danger,table .info,.table .info{color:#fff}table .success a:not(.btn),.table .success a:not(.btn),table .warning a:not(.btn),.table .warning a:not(.btn),table .danger a:not(.btn),.table .danger a:not(.btn),table .info a:not(.btn),.table .info a:not(.btn){color:#fff}table:not(.table-bordered)>thead>tr>th,.table:not(.table-bordered)>thead>tr>th,table:not(.table-bordered)>tbody>tr>th,.table:not(.table-bordered)>tbody>tr>th,table:not(.table-bordered)>tfoot>tr>th,.table:not(.table-bordered)>tfoot>tr>th,table:not(.table-bordered)>thead>tr>td,.table:not(.table-bordered)>thead>tr>td,table:not(.table-bordered)>tbody>tr>td,.table:not(.table-bordered)>tbody>tr>td,table:not(.table-bordered)>tfoot>tr>td,.table:not(.table-bordered)>tfoot>tr>td{border-color:transparent}.form-control{box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}label{font-weight:normal}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label,.has-warning .form-control-feedback{color:#ff851b}.has-warning .form-control,.has-warning .form-control:focus{border:1px solid #ff851b;box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-warning .input-group-addon{border:1px solid #ff851b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label,.has-error .form-control-feedback{color:#ff4136}.has-error .form-control,.has-error .form-control:focus{border:1px solid #ff4136;box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-error .input-group-addon{border:1px solid #ff4136}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label,.has-success .form-control-feedback{color:#28b62c}.has-success .form-control,.has-success .form-control:focus{border:1px solid #28b62c;box-shadow:inset 0 2px 0 rgba(0,0,0,0.075)}.has-success .input-group-addon{border:1px solid #28b62c}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{border-color:transparent}.nav-tabs>li>a{margin-top:6px;border-color:#e7e7e7;color:#333333;transition:all .2s ease-in-out}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus,.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus,.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{padding-bottom:16px;margin-top:0}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{border-color:#e7e7e7}.nav-tabs>li.disabled>a:hover,.nav-tabs>li.disabled>a:focus{padding-top:10px;padding-bottom:10px;margin-top:6px}.nav-tabs.nav-justified>li{vertical-align:bottom}.dropdown-menu{margin-top:0;border-width:0 1px 4px 1px;border-top-width:1px;box-shadow:none}.breadcrumb{border-color:#ededed;border-style:solid;border-width:0 1px 4px 1px}.pagination>li>a,.pager>li>a,.pagination>li>span,.pager>li>span{position:relative;top:0;border-width:0 1px 4px 1px;color:#555555;font-size:12px;font-weight:bold;text-transform:uppercase}.pagination>li>a:hover,.pager>li>a:hover,.pagination>li>span:hover,.pager>li>span:hover{top:1px;border-bottom-width:3px}.pagination>li>a:active,.pager>li>a:active,.pagination>li>span:active,.pager>li>span:active{top:2px;border-bottom-width:2px}.pagination>.disabled>a:hover,.pager>.disabled>a:hover,.pagination>.disabled>span:hover,.pager>.disabled>span:hover{top:0;border-width:0 1px 4px 1px}.pagination>.disabled>a:active,.pager>.disabled>a:active,.pagination>.disabled>span:active,.pager>.disabled>span:active{top:0;border-width:0 1px 4px 1px}.pager>li>a,.pager>li>span,.pager>.disabled>a,.pager>.disabled>span,.pager>li>a:hover,.pager>li>span:hover,.pager>.disabled>a:hover,.pager>.disabled>span:hover,.pager>li>a:active,.pager>li>span:active,.pager>.disabled>a:active,.pager>.disabled>span:active{border-left-width:2px;border-right-width:2px}.close{color:#fff;text-decoration:none;opacity:0.4}.close:hover,.close:focus{color:#fff;opacity:1}.alert{border-width:0 1px 4px 1px}.alert .alert-link{font-weight:normal;color:#fff;text-decoration:underline}.label{font-weight:normal}.progress{border:1px solid #e7e7e7;box-shadow:inset 0 2px 0 rgba(0,0,0,0.1)}.progress-bar{box-shadow:inset 0 -4px 0 rgba(0,0,0,0.15)}.well{border:1px solid #e7e7e7;box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{border-color:#eeeeee}a.list-group-item-success.active{background-color:#28b62c}a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{background-color:#23a127}a.list-group-item-warning.active{background-color:#ff851b}a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{background-color:#ff7701}a.list-group-item-danger.active{background-color:#ff4136}a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{background-color:#ff291c}.jumbotron{border:1px solid #e7e7e7;box-shadow:inset 0 2px 0 rgba(0,0,0,0.05)}.panel{border:1px solid #e7e7e7;border-width:0 1px 4px 1px}.panel-default .close{color:#555555}.modal .close{color:#555555}.popover{color:#555555} \ No newline at end of file diff --git a/data/web/css/breakpoint.min.css b/data/web/css/build/002-breakpoint.min.css similarity index 100% rename from data/web/css/breakpoint.min.css rename to data/web/css/build/002-breakpoint.min.css diff --git a/data/web/css/bootstrap-select.min.css b/data/web/css/build/003-bootstrap-select.min.css similarity index 100% rename from data/web/css/bootstrap-select.min.css rename to data/web/css/build/003-bootstrap-select.min.css diff --git a/data/web/css/build/004-bootstrap-slider.min.css b/data/web/css/build/004-bootstrap-slider.min.css new file mode 100644 index 00000000..f8e395be --- /dev/null +++ b/data/web/css/build/004-bootstrap-slider.min.css @@ -0,0 +1,41 @@ +/*! ======================================================= + VERSION 10.6.1 +========================================================= */ +/*! ========================================================= + * bootstrap-slider.js + * + * Maintainers: + * Kyle Kemp + * - Twitter: @seiyria + * - Github: seiyria + * Rohit Kalkur + * - Twitter: @Rovolutionary + * - Github: rovolution + * + * ========================================================= + * + * bootstrap-slider is released under the MIT License + * Copyright (c) 2019 Kyle Kemp, Rohit Kalkur, and contributors + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{position:relative;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#2e6da4;margin-top:0}.slider.slider-horizontal .slider-tick-container{white-space:nowrap;position:absolute;top:0;left:0;width:100%}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-horizontal .tooltip{-ms-transform:translateX(-50%);transform:translateX(-50%)}.slider.slider-horizontal.slider-rtl .slider-track{left:initial;right:0}.slider.slider-horizontal.slider-rtl .slider-tick,.slider.slider-horizontal.slider-rtl .slider-handle{margin-left:initial;margin-right:-10px}.slider.slider-horizontal.slider-rtl .slider-tick-container{left:initial;right:0}.slider.slider-horizontal.slider-rtl .tooltip{-ms-transform:translateX(50%);transform:translateX(50%)}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;left:25%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#2e6da4;border-right-color:#2e6da4;margin-left:0;margin-right:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-vertical .tooltip{-ms-transform:translateY(-50%);transform:translateY(-50%)}.slider.slider-vertical.slider-rtl .slider-track{left:initial;right:25%}.slider.slider-vertical.slider-rtl .slider-selection{left:initial;right:0}.slider.slider-vertical.slider-rtl .slider-tick.triangle,.slider.slider-vertical.slider-rtl .slider-handle.triangle{border-width:10px 10px 10px 0}.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label{padding-left:initial;padding-right:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip{pointer-events:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;top:0;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7',endColorstr='#ff2e6da4',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle:hover{cursor:pointer}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;cursor:pointer;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0);opacity:1} \ No newline at end of file diff --git a/data/web/css/bootstrap-switch.min.css b/data/web/css/build/005-bootstrap-switch.min.css similarity index 100% rename from data/web/css/bootstrap-switch.min.css rename to data/web/css/build/005-bootstrap-switch.min.css diff --git a/data/web/css/footable.bootstrap.min.css b/data/web/css/build/006-footable.bootstrap.min.css similarity index 100% rename from data/web/css/footable.bootstrap.min.css rename to data/web/css/build/006-footable.bootstrap.min.css diff --git a/data/web/css/build/007-languages.min.css b/data/web/css/build/007-languages.min.css new file mode 100644 index 00000000..2c6a9262 --- /dev/null +++ b/data/web/css/build/007-languages.min.css @@ -0,0 +1 @@ +.lang-lg,.lang-sm,.lang-xs{background-repeat:no-repeat;display:inline-block;background-image:url(/img/languages.png)}.lang-sm,.lang-sm:after,.lang-xs,.lang-xs:after{position:relative}.lang-xs{background-position:0 -484px;min-width:14px;height:11px;min-height:11px;max-height:11px}.lang-sm{background-position:0 -1199px;min-width:22px;height:16px;min-height:16px;max-height:16px}.lang-lg{background-position:0 -2134px;min-width:30px;height:22px;min-height:22px;max-height:22px}.lang-xs[lang=ar]{background-position:0 0}.lang-xs[lang=be]{background-position:0 -11px}.lang-xs[lang=bg]{background-position:0 -22px}.lang-xs[lang=cs]{background-position:0 -33px}.lang-xs[lang=da]{background-position:0 -44px}.lang-xs[lang=de]{background-position:0 -55px}.lang-xs[lang=el]{background-position:0 -66px}.lang-xs[lang=en]{background-position:0 -77px}.lang-xs[lang=es]{background-position:0 -88px}.lang-xs[lang=et]{background-position:0 -99px}.lang-xs[lang=fi]{background-position:0 -110px}.lang-xs[lang=fr]{background-position:0 -121px}.lang-xs[lang=ga]{background-position:0 -132px}.lang-xs[lang=hi]{background-position:0 -143px}.lang-xs[lang=hr]{background-position:0 -154px}.lang-xs[lang=hu]{background-position:0 -165px}.lang-xs[lang=in]{background-position:0 -176px}.lang-xs[lang=is]{background-position:0 -187px}.lang-xs[lang=it]{background-position:0 -198px}.lang-xs[lang=iw]{background-position:0 -209px}.lang-xs[lang=ja]{background-position:0 -220px}.lang-xs[lang=ko]{background-position:0 -231px}.lang-xs[lang=lt]{background-position:0 -242px}.lang-xs[lang=lv]{background-position:0 -253px}.lang-xs[lang=mk]{background-position:0 -264px}.lang-xs[lang=ms]{background-position:0 -275px}.lang-xs[lang=mt]{background-position:0 -286px}.lang-xs[lang=nl]{background-position:0 -297px}.lang-xs[lang=no]{background-position:0 -308px}.lang-xs[lang=pl]{background-position:0 -319px}.lang-xs[lang=pt]{background-position:0 -330px}.lang-xs[lang=ro]{background-position:0 -341px}.lang-xs[lang=ru]{background-position:0 -352px}.lang-xs[lang=sk]{background-position:0 -363px}.lang-xs[lang=sl]{background-position:0 -374px}.lang-xs[lang=sq]{background-position:0 -385px}.lang-xs[lang=sr]{background-position:0 -396px}.lang-xs[lang=sv]{background-position:0 -407px}.lang-xs[lang=th]{background-position:0 -418px}.lang-xs[lang=tr]{background-position:0 -429px}.lang-xs[lang=uk]{background-position:0 -440px}.lang-xs[lang=vi]{background-position:0 -451px}.lang-xs[lang=zh]{background-position:0 -462px}.lang-xs[lang=ca]{background-position:0 -473px}.lang-sm[lang=ar]{background-position:0 -495px}.lang-sm[lang=be]{background-position:0 -511px}.lang-sm[lang=bg]{background-position:0 -527px}.lang-sm[lang=cs]{background-position:0 -543px}.lang-sm[lang=da]{background-position:0 -559px}.lang-sm[lang=de]{background-position:0 -575px}.lang-sm[lang=el]{background-position:0 -591px}.lang-sm[lang=en]{background-position:0 -607px}.lang-sm[lang=es]{background-position:0 -623px}.lang-sm[lang=et]{background-position:0 -639px}.lang-sm[lang=fi]{background-position:0 -655px}.lang-sm[lang=fr]{background-position:0 -671px}.lang-sm[lang=ga]{background-position:0 -687px}.lang-sm[lang=hi]{background-position:0 -703px}.lang-sm[lang=hr]{background-position:0 -719px}.lang-sm[lang=hu]{background-position:0 -735px}.lang-sm[lang=in]{background-position:0 -751px}.lang-sm[lang=is]{background-position:0 -767px}.lang-sm[lang=it]{background-position:0 -783px}.lang-sm[lang=iw]{background-position:0 -799px}.lang-sm[lang=ja]{background-position:0 -815px}.lang-sm[lang=ko]{background-position:0 -831px}.lang-sm[lang=lt]{background-position:0 -847px}.lang-sm[lang=lv]{background-position:0 -863px}.lang-sm[lang=mk]{background-position:0 -879px}.lang-sm[lang=ms]{background-position:0 -895px}.lang-sm[lang=mt]{background-position:0 -911px}.lang-sm[lang=nl]{background-position:0 -927px}.lang-sm[lang=no]{background-position:0 -943px}.lang-sm[lang=pl]{background-position:0 -959px}.lang-sm[lang=pt]{background-position:0 -975px}.lang-sm[lang=ro]{background-position:0 -991px}.lang-sm[lang=ru]{background-position:0 -1007px}.lang-sm[lang=sk]{background-position:0 -1023px}.lang-sm[lang=sl]{background-position:0 -1039px}.lang-sm[lang=sq]{background-position:0 -1055px}.lang-sm[lang=sr]{background-position:0 -1071px}.lang-sm[lang=sv]{background-position:0 -1087px}.lang-sm[lang=th]{background-position:0 -1103px}.lang-sm[lang=tr]{background-position:0 -1119px}.lang-sm[lang=uk]{background-position:0 -1135px}.lang-sm[lang=vi]{background-position:0 -1151px}.lang-sm[lang=zh]{background-position:0 -1167px}.lang-sm[lang=ca]{background-position:0 -1183px}.lang-lg[lang=ar]{background-position:0 -1188px}.lang-lg[lang=be]{background-position:0 -1210px}.lang-lg[lang=bg]{background-position:0 -1232px}.lang-lg[lang=cs]{background-position:0 -1254px}.lang-lg[lang=da]{background-position:0 -1276px}.lang-lg[lang=de]{background-position:0 -1298px}.lang-lg[lang=el]{background-position:0 -1320px}.lang-lg[lang=en]{background-position:0 -1342px}.lang-lg[lang=es]{background-position:0 -1364px}.lang-lg[lang=et]{background-position:0 -1386px}.lang-lg[lang=fi]{background-position:0 -1408px}.lang-lg[lang=fr]{background-position:0 -1430px}.lang-lg[lang=ga]{background-position:0 -1452px}.lang-lg[lang=hi]{background-position:0 -1474px}.lang-lg[lang=hr]{background-position:0 -1496px}.lang-lg[lang=hu]{background-position:0 -1518px}.lang-lg[lang=in]{background-position:0 -1540px}.lang-lg[lang=is]{background-position:0 -1562px}.lang-lg[lang=it]{background-position:0 -1584px}.lang-lg[lang=iw]{background-position:0 -1606px}.lang-lg[lang=ja]{background-position:0 -1628px}.lang-lg[lang=ko]{background-position:0 -1650px}.lang-lg[lang=lt]{background-position:0 -1672px}.lang-lg[lang=lv]{background-position:0 -1694px}.lang-lg[lang=mk]{background-position:0 -1716px}.lang-lg[lang=ms]{background-position:0 -1738px}.lang-lg[lang=mt]{background-position:0 -1760px}.lang-lg[lang=nl]{background-position:0 -1782px}.lang-lg[lang=no]{background-position:0 -1804px}.lang-lg[lang=pl]{background-position:0 -1826px}.lang-lg[lang=pt]{background-position:0 -1848px}.lang-lg[lang=ro]{background-position:0 -1870px}.lang-lg[lang=ru]{background-position:0 -1892px}.lang-lg[lang=sk]{background-position:0 -1914px}.lang-lg[lang=sl]{background-position:0 -1936px}.lang-lg[lang=sq]{background-position:0 -1958px}.lang-lg[lang=sr]{background-position:0 -1980px}.lang-lg[lang=sv]{background-position:0 -2002px}.lang-lg[lang=th]{background-position:0 -2024px}.lang-lg[lang=tr]{background-position:0 -2046px}.lang-lg[lang=uk]{background-position:0 -2068px}.lang-lg[lang=vi]{background-position:0 -2090px}.lang-lg[lang=zh]{background-position:0 -2112px}.lang-lbl-en:after,.lang-lbl-full:after,.lang-lbl:after{content:"Unknown language"}.lang-lbl[lang=ar]:after{content:"\000627\000644\000639\000631\000628\00064A\000629"}.lang-lbl[lang=be]:after{content:"\000411\000435\00043B\000430\000440\000443\000441\00043A\000456"}.lang-lbl[lang=bg]:after{content:"\000411\00044A\00043B\000433\000430\000440\000441\00043A\000438"}.lang-lbl[lang=ca]:after{content:"Catal\0000E0"}.lang-lbl[lang=cs]:after{content:"\00010Ce\000161tina"}.lang-lbl[lang=da]:after{content:"Dansk"}.lang-lbl[lang=de]:after{content:"Deutsch"}.lang-lbl[lang=el]:after{content:"\000395\0003BB\0003BB\0003B7\0003BD\0003B9\0003BA\0003AC"}.lang-lbl[lang=en]:after{content:"English"}.lang-lbl[lang=es]:after{content:"Espa\0000F1ol"}.lang-lbl[lang=et]:after{content:"Eesti"}.lang-lbl[lang=fi]:after{content:"Suomi"}.lang-lbl[lang=fr]:after{content:"Fran\0000E7ais"}.lang-lbl[lang=ga]:after{content:"Gaeilge"}.lang-lbl[lang=hi]:after{content:"\000939\00093F\000902\000926\000940"}.lang-lbl[lang=hr]:after{content:"Hrvatski"}.lang-lbl[lang=hu]:after{content:"Magyar"}.lang-lbl[lang=in]:after{content:"Bahasa\000020indonesia"}.lang-lbl[lang=is]:after{content:"\0000CDslenska"}.lang-lbl[lang=it]:after{content:"Italiano"}.lang-lbl[lang=iw]:after{content:"\0005E2\0005D1\0005E8\0005D9\0005EA"}.lang-lbl[lang=ja]:after{content:"\0065E5\00672C\008A9E"}.lang-lbl[lang=ko]:after{content:"\00D55C\00AD6D\00C5B4"}.lang-lbl[lang=lt]:after{content:"Lietuvi\000173"}.lang-lbl[lang=lv]:after{content:"Latvie\000161u"}.lang-lbl[lang=mk]:after{content:"\00041C\000430\00043A\000435\000434\00043E\00043D\000441\00043A\000438"}.lang-lbl[lang=ms]:after{content:"Bahasa\000020melayu"}.lang-lbl[lang=mt]:after{content:"Malti"}.lang-lbl[lang=nl]:after{content:"Nederlands"}.lang-lbl[lang=no]:after{content:"Norsk"}.lang-lbl[lang=pl]:after{content:"Polski"}.lang-lbl[lang=pt]:after{content:"Portugu\0000EAs"}.lang-lbl[lang=ro]:after{content:"Rom\0000E2n\000103"}.lang-lbl[lang=ru]:after{content:"\000420\000443\000441\000441\00043A\000438\000439"}.lang-lbl[lang=sk]:after{content:"Sloven\00010Dina"}.lang-lbl[lang=sl]:after{content:"Sloven\000161\00010Dina"}.lang-lbl[lang=sq]:after{content:"Shqipe"}.lang-lbl[lang=sr]:after{content:"\000421\000440\00043F\000441\00043A\000438"}.lang-lbl[lang=sv]:after{content:"Svenska"}.lang-lbl[lang=th]:after{content:"\000E44\000E17\000E22"}.lang-lbl[lang=tr]:after{content:"T\0000FCrk\0000E7e"}.lang-lbl[lang=uk]:after{content:"\000423\00043A\000440\000430\000457\00043D\000441\00044C\00043A\000430"}.lang-lbl[lang=vi]:after{content:"Ti\001EBFng\000020vi\001EC7t"}.lang-lbl[lang=zh]:after{content:"\004E2D\006587"}.lang-lbl-en[lang=ar]:after{content:"Arabic"}.lang-lbl-en[lang=be]:after{content:"Belarusian"}.lang-lbl-en[lang=bg]:after{content:"Bulgarian"}.lang-lbl-en[lang=ca]:after{content:"Catalan"}.lang-lbl-en[lang=cs]:after{content:"Czech"}.lang-lbl-en[lang=da]:after{content:"Danish"}.lang-lbl-en[lang=de]:after{content:"German"}.lang-lbl-en[lang=el]:after{content:"Greek"}.lang-lbl-en[lang=en]:after{content:"English"}.lang-lbl-en[lang=es]:after{content:"Spanish"}.lang-lbl-en[lang=et]:after{content:"Estonian"}.lang-lbl-en[lang=fi]:after{content:"Finnish"}.lang-lbl-en[lang=fr]:after{content:"French"}.lang-lbl-en[lang=ga]:after{content:"Irish"}.lang-lbl-en[lang=hi]:after{content:"Hindi"}.lang-lbl-en[lang=hr]:after{content:"Croatian"}.lang-lbl-en[lang=hu]:after{content:"Hungarian"}.lang-lbl-en[lang=in]:after{content:"Indonesian"}.lang-lbl-en[lang=is]:after{content:"Icelandic"}.lang-lbl-en[lang=it]:after{content:"Italian"}.lang-lbl-en[lang=iw]:after{content:"Hebrew"}.lang-lbl-en[lang=ja]:after{content:"Japanese"}.lang-lbl-en[lang=ko]:after{content:"Korean"}.lang-lbl-en[lang=lt]:after{content:"Lithuanian"}.lang-lbl-en[lang=lv]:after{content:"Latvian"}.lang-lbl-en[lang=mk]:after{content:"Macedonian"}.lang-lbl-en[lang=ms]:after{content:"Malay"}.lang-lbl-en[lang=mt]:after{content:"Maltese"}.lang-lbl-en[lang=nl]:after{content:"Dutch"}.lang-lbl-en[lang=no]:after{content:"Norwegian"}.lang-lbl-en[lang=pl]:after{content:"Polish"}.lang-lbl-en[lang=pt]:after{content:"Portuguese"}.lang-lbl-en[lang=ro]:after{content:"Romanian"}.lang-lbl-en[lang=ru]:after{content:"Russian"}.lang-lbl-en[lang=sk]:after{content:"Slovak"}.lang-lbl-en[lang=sl]:after{content:"Slovenian"}.lang-lbl-en[lang=sq]:after{content:"Albanian"}.lang-lbl-en[lang=sr]:after{content:"Serbian"}.lang-lbl-en[lang=sv]:after{content:"Swedish"}.lang-lbl-en[lang=th]:after{content:"Thai"}.lang-lbl-en[lang=tr]:after{content:"Turkish"}.lang-lbl-en[lang=uk]:after{content:"Ukrainian"}.lang-lbl-en[lang=vi]:after{content:"Vietnamese"}.lang-lbl-en[lang=zh]:after{content:"Chinese"}.lang-lbl-full[lang=ar]:after{content:"\000627\000644\000639\000631\000628\00064A\000629\0000A0/\0000A0Arabic"}.lang-lbl-full[lang=be]:after{content:"\000411\000435\00043B\000430\000440\000443\000441\00043A\000456\0000A0/\0000A0Belarusian"}.lang-lbl-full[lang=bg]:after{content:"\000411\00044A\00043B\000433\000430\000440\000441\00043A\000438\0000A0/\0000A0Bulgarian"}.lang-lbl-full[lang=ca]:after{content:"Catal\0000E0\0000A0/\0000A0Catalan"}.lang-lbl-full[lang=cs]:after{content:"\00010Ce\000161tina\0000A0/\0000A0Czech"}.lang-lbl-full[lang=da]:after{content:"Dansk\0000A0/\0000A0Danish"}.lang-lbl-full[lang=de]:after{content:"Deutsch\0000A0/\0000A0German"}.lang-lbl-full[lang=el]:after{content:"\000395\0003BB\0003BB\0003B7\0003BD\0003B9\0003BA\0003AC\0000A0/\0000A0Greek"}.lang-lbl-full[lang=en]:after{content:"English\0000A0/\0000A0English"}.lang-lbl-full[lang=es]:after{content:"Espa\0000F1ol\0000A0/\0000A0Spanish"}.lang-lbl-full[lang=et]:after{content:"Eesti\0000A0/\0000A0Estonian"}.lang-lbl-full[lang=fi]:after{content:"Suomi\0000A0/\0000A0Finnish"}.lang-lbl-full[lang=fr]:after{content:"Fran\0000E7ais\0000A0/\0000A0French"}.lang-lbl-full[lang=ga]:after{content:"Gaeilge\0000A0/\0000A0Irish"}.lang-lbl-full[lang=hi]:after{content:"\000939\00093F\000902\000926\000940\0000A0/\0000A0Hindi"}.lang-lbl-full[lang=hr]:after{content:"Hrvatski\0000A0/\0000A0Croatian"}.lang-lbl-full[lang=hu]:after{content:"Magyar\0000A0/\0000A0Hungarian"}.lang-lbl-full[lang=in]:after{content:"Bahasa\000020indonesia\0000A0/\0000A0Indonesian"}.lang-lbl-full[lang=is]:after{content:"\0000CDslenska\0000A0/\0000A0Icelandic"}.lang-lbl-full[lang=it]:after{content:"Italiano\0000A0/\0000A0Italian"}.lang-lbl-full[lang=iw]:after{content:"\0005E2\0005D1\0005E8\0005D9\0005EA\0000A0/\0000A0Hebrew"}.lang-lbl-full[lang=ja]:after{content:"\0065E5\00672C\008A9E\0000A0/\0000A0Japanese"}.lang-lbl-full[lang=ko]:after{content:"\00D55C\00AD6D\00C5B4\0000A0/\0000A0Korean"}.lang-lbl-full[lang=lt]:after{content:"Lietuvi\000173\0000A0/\0000A0Lithuanian"}.lang-lbl-full[lang=lv]:after{content:"Latvie\000161u\0000A0/\0000A0Latvian"}.lang-lbl-full[lang=mk]:after{content:"\00041C\000430\00043A\000435\000434\00043E\00043D\000441\00043A\000438\0000A0/\0000A0Macedonian"}.lang-lbl-full[lang=ms]:after{content:"Bahasa\000020melayu\0000A0/\0000A0Malay"}.lang-lbl-full[lang=mt]:after{content:"Malti\0000A0/\0000A0Maltese"}.lang-lbl-full[lang=nl]:after{content:"Nederlands\0000A0/\0000A0Dutch"}.lang-lbl-full[lang=no]:after{content:"Norsk\0000A0/\0000A0Norwegian"}.lang-lbl-full[lang=pl]:after{content:"Polski\0000A0/\0000A0Polish"}.lang-lbl-full[lang=pt]:after{content:"Portugu\0000EAs\0000A0/\0000A0Portuguese"}.lang-lbl-full[lang=ro]:after{content:"Rom\0000E2n\000103\0000A0/\0000A0Romanian"}.lang-lbl-full[lang=ru]:after{content:"\000420\000443\000441\000441\00043A\000438\000439\0000A0/\0000A0Russian"}.lang-lbl-full[lang=sk]:after{content:"Sloven\00010Dina\0000A0/\0000A0Slovak"}.lang-lbl-full[lang=sl]:after{content:"Sloven\000161\00010Dina\0000A0/\0000A0Slovenian"}.lang-lbl-full[lang=sq]:after{content:"Shqipe\0000A0/\0000A0Albanian"}.lang-lbl-full[lang=sr]:after{content:"\000421\000440\00043F\000441\00043A\000438\0000A0/\0000A0Serbian"}.lang-lbl-full[lang=sv]:after{content:"Svenska\0000A0/\0000A0Swedish"}.lang-lbl-full[lang=th]:after{content:"\000E44\000E17\000E22\0000A0/\0000A0Thai"}.lang-lbl-full[lang=tr]:after{content:"T\0000FCrk\0000E7e\0000A0/\0000A0Turkish"}.lang-lbl-full[lang=uk]:after{content:"\000423\00043A\000440\000430\000457\00043D\000441\00044C\00043A\000430\0000A0/\0000A0Ukrainian"}.lang-lbl-full[lang=vi]:after{content:"Ti\001EBFng\000020vi\001EC7t\0000A0/\0000A0Vietnamese"}.lang-lbl-full[lang=zh]:after{content:"\004E2D\006587\0000A0/\0000A0Chinese"}.lang-lg:before,.lang-sm:before,.lang-xs:before{content:'\0000A0'}.lang-xs.lang-lbl,.lang-xs.lang-lbl-en,.lang-xs.lang-lbl-full{padding-left:16px}.lang-sm.lang-lbl,.lang-sm.lang-lbl-en,.lang-sm.lang-lbl-full{padding-left:24px}.lang-lg.lang-lbl,.lang-lg.lang-lbl-en,.lang-lg.lang-lbl-full{padding-left:32px}.lang-lg.lang-lbl-en:before,.lang-lg.lang-lbl-full:before,.lang-lg.lang-lbl:before,.lang-sm.lang-lbl-en:before,.lang-sm.lang-lbl-full:before,.lang-sm.lang-lbl:before,.lang-xs.lang-lbl-en:before,.lang-xs.lang-lbl-full:before,.lang-xs.lang-lbl:before{content:''}.lang-lg,.lang-lg:after{top:0;position:relative}.lang-sm{top:1px}.lang-sm:after{top:-1px}.lang-xs{top:4px}.lang-xs:after{top:-4px}.lead>.lang-lg{top:2px}.lead>.lang-lg:after{top:-2px}.lead>.lang-sm{top:6px}.lead>.lang-sm:after{top:-6px}.lead>.lang-xs{top:8px}.lead>.lang-xs:after{top:-8px}small>.lang-sm{top:-1px}small>.lang-sm:after{top:1px}small>.lang-xs{top:2px}small>.lang-xs:after{top:-2px}h1>.lang-lg{top:9px}h1>.lang-lg:after{top:-9px}h1>.lang-sm{top:12px}h1>.lang-sm:after{top:-12px}h1>.lang-xs{top:14px}h1>.lang-xs:after{top:-14px}h2>.lang-lg{top:5px}h2>.lang-lg:after{top:-5px}h2>.lang-sm{top:8px}h2>.lang-sm:after{top:-8px}h2>.lang-xs{top:10px}h2>.lang-xs:after{top:-10px}h3>.lang-lg{top:1px}h3>.lang-lg:after{top:-1px}h3>.lang-sm{top:5px}h3>.lang-sm:after{top:-5px}h3>.lang-xs{top:8px}h3>.lang-xs:after{top:-8px}h4>.lang-lg{top:-1px}h4>.lang-lg:after,h4>.lang-sm{top:1px}h4>.lang-sm:after{top:-1px}h4>.lang-xs{top:4px}h4>.lang-xs:after{top:-4px}h5>.lang-sm,h5>.lang-sm:after{top:0}h5>.lang-xs{top:2px}h5>.lang-xs:after{top:-2px}h6>.lang-sm,h6>.lang-sm:after{top:0}h6>.lang-xs{top:1px}h6>.lang-xs:after{top:-1px}.btn>.lang-sm{top:2px}.btn>.lang-sm:after{top:-2px}.btn>.lang-xs{top:4px}.btn>.lang-xs:after{top:-4px}.btn.btn-xs>.lang-sm,.btn.btn-xs>.lang-sm:after{top:0}.btn.btn-xs>.lang-xs{top:3px}.btn.btn-xs>.lang-xs:after{top:-3px}.btn.btn-sm>.lang-sm,.btn.btn-sm>.lang-sm:after{top:0}.btn.btn-sm>.lang-xs{top:3px}.btn.btn-sm>.lang-xs:after{top:-3px}.btn.btn-lg>.lang-lg{top:1px}.btn.btn-lg>.lang-lg:after{top:-1px}.btn.btn-lg>.lang-sm{top:3px}.btn.btn-lg>.lang-sm:after{top:-3px}.btn.btn-lg>.lang-xs{top:6px}.btn.btn-lg>.lang-xs:after{top:-6px} \ No newline at end of file diff --git a/data/web/css/build/008-mailcow.css b/data/web/css/build/008-mailcow.css new file mode 100644 index 00000000..5a51bfae --- /dev/null +++ b/data/web/css/build/008-mailcow.css @@ -0,0 +1,172 @@ +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 400; + src: local('PT Sans'), local('PTSans-Regular'), + url('/fonts/pt-sans-v9-cyrillic_latin-regular.woff2') format('woff2'), + url('/fonts/pt-sans-v9-cyrillic_latin-regular.woff') format('woff'); +} +@font-face { + font-family: 'PT Sans'; + font-style: normal; + font-weight: 700; + src: local('PT Sans Bold'), local('PTSans-Bold'), + url('/fonts/pt-sans-v9-cyrillic_latin-700.woff2') format('woff2'), + url('/fonts/pt-sans-v9-cyrillic_latin-700.woff') format('woff'); +} +@font-face { + font-family: 'PT Sans'; + font-style: italic; + font-weight: 400; + src: local('PT Sans Italic'), local('PTSans-Italic'), + url('/fonts/pt-sans-v9-cyrillic_latin-italic.woff2') format('woff2'), + url('/fonts/pt-sans-v9-cyrillic_latin-italic.woff') format('woff'); +} +#maxmsgsize { min-width: 80px; } +#slider1 .slider-selection { + background: #FFD700; +} +#slider1 .slider-track-high { + background: #FF4500; +} +#slider1 .slider-track-low { + background: #66CD00; +} +.striped:nth-child(odd) { + background-color: #fff; +} +.striped:nth-child(even) { + background-color: #fafafa; + border:1px solid white; +} +.btn { + text-transform: none; +} +.textarea-code { + font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; + background:transparent !important; +} +.navbar-nav { + margin: 0; +} +.navbar-fixed-bottom .navbar-collapse, +.navbar-fixed-top .navbar-collapse { + max-height: 1000px +} +.glyphicon-spin { + font-size:12px; + -webkit-animation: spin 2000ms infinite linear; + animation: spin 2000ms infinite linear; +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;} +.footable-sortable { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +/* Fix modal moving content left */ +body.modal-open { + overflow: inherit; + padding-right: inherit !important; +} +body { + font-family: "PT Sans","Helvetica Neue",Helvetica,Arial,sans-serif; +} +#mailcow-alert { + position: fixed; + bottom: 8px; + right: 25px; + min-width: 350px; + max-width: 550px; + z-index: 2000; +} +.input-group-sm .btn { margin-top: 0px !important } +legend { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none + -o-user-select: none; + user-select: none; + font-size: 12pt; +} +.navbar .navbar-brand { + padding-top: 5px; +} +.navbar .navbar-brand img { + height: 40px; +} +.mailcow-logo img { + max-width: 250px; +} +.lang-link-disabled a { + pointer-events: none; +} +.lang-link-disabled { + cursor: not-allowed; +} +.dkim-label { + margin: 0 0 2px !important; +} +.overlay { + background: #fff; + position: absolute; + z-index: 10000; + top: 0; right: 0; bottom: 0; left: 0; + opacity: 0.7; +} +nav .glyphicon { + font-size: 12px !important; +} +#top { + padding-top: 70px; +} +.bootstrap-select.btn-group .no-results { + display: none; +} +.dropdown-desc { + display: block; + padding: 3px 10px; + clear: both; + font-weight: bold; + color: #5a5a5a; + white-space: nowrap; +} +.haveibeenpwned { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.full-width-select { + width: 100%!important; +} +.tooltip { + font-family: inherit; + font-size: 12px; +} +.progress-bar { + font-size: 12px; + line-height: 14px; +} \ No newline at end of file diff --git a/data/web/css/animate.min.css b/data/web/css/build/009-animate.min.css similarity index 100% rename from data/web/css/animate.min.css rename to data/web/css/build/009-animate.min.css diff --git a/data/web/css/numberedtextarea.min.css b/data/web/css/build/010-numberedtextarea.min.css similarity index 88% rename from data/web/css/numberedtextarea.min.css rename to data/web/css/build/010-numberedtextarea.min.css index c147b16b..133faf95 100644 --- a/data/web/css/numberedtextarea.min.css +++ b/data/web/css/build/010-numberedtextarea.min.css @@ -1 +1 @@ -div.numberedtextarea-wrapper{position:relative}div.numberedtextarea-wrapper textarea{display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}div.numberedtextarea-line-numbers{position:absolute;top:0;left:0;right:0;bottom:0;width:50px;border-right:none;color:rgba(0,0,0,.4);overflow:hidden}div.numberedtextarea-number{padding-right:6px;text-align:right}textarea#script_data{font-family:Monospace} \ No newline at end of file +div.numberedtextarea-wrapper{position:relative}div.numberedtextarea-wrapper textarea{display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}div.numberedtextarea-line-numbers{position:absolute;top:0;left:0;right:0;bottom:0;width:50px;border-right:none;color:rgba(0,0,0,.4);overflow:hidden}div.numberedtextarea-number{padding-right:6px;text-align:right} diff --git a/data/web/css/jquery.jqplot.min.css b/data/web/css/build/011-jquery.jqplot.min.css similarity index 100% rename from data/web/css/jquery.jqplot.min.css rename to data/web/css/build/011-jquery.jqplot.min.css diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css deleted file mode 100644 index 374688a1..00000000 --- a/data/web/css/mailcow.css +++ /dev/null @@ -1,150 +0,0 @@ -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 300; - src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light.woff2') format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular.woff2') format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 700; - src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url('../fonts/SourceSansPro-Bold.woff2') format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} -@font-face { - font-family: 'Source Sans Pro'; - font-style: italic; - font-weight: 700; - src: local('Source Sans Pro Bold Italic'), local('SourceSansPro-BoldIt'), url('../fonts/SourceSansPro-BoldIt.woff2') format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} -#maxmsgsize { min-width: 80px; } -#slider1 .slider-selection { - background: #FFD700; -} -#slider1 .slider-track-high { - background: #FF4500; -} -#slider1 .slider-track-low { - background: #66CD00; -} -.striped:nth-child(odd) { - background-color: #fff; -} -.striped:nth-child(even) { - background-color: #fafafa; - border:1px solid white; -} -.btn { - text-transform: none; -} -.glyphicon-spin { - font-size:12px; - -webkit-animation: spin 2000ms infinite linear; - animation: spin 2000ms infinite linear; -} -@-webkit-keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;} -.footable-sortable { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -/* Fix modal moving content left */ -body.modal-open { - overflow: inherit; - padding-right: inherit !important; -} -body { - font-size:11pt; -} -#mailcow-alert { - position: fixed; - bottom: 8px; - right: 25px; - min-width: 350px; - max-width: 550px; - z-index: 2000; -} -.input-group-sm .btn { margin-top: 0px !important } -legend { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none - -o-user-select: none; - user-select: none; - font-size: 12pt; -} -.navbar .navbar-brand { - padding-top: 5px; -} -.navbar .navbar-brand img { - height: 40px; -} -.mailcow-logo img { - max-width: 250px; -} -.lang-link-disabled a { - pointer-events: none; -} -.lang-link-disabled { - cursor: not-allowed; -} -.dkim-label { - margin: 0 0 2px !important; -} -.overlay { - background: #fff; - position: absolute; - z-index: 10000; - top: 0; right: 0; bottom: 0; left: 0; - opacity: 0.7; -} -nav .glyphicon { - font-size: 12px !important; -} -.logged-in-as { - border-left: 1px solid #E7E7E7; -} -#top { - padding-top: 70px; -} -.bootstrap-select.btn-group .no-results { - display: none; -} -.dropdown-desc { - display: block; - padding: 3px 10px; - clear: both; - font-weight: bold; - color: #5a5a5a; - white-space: nowrap; -} diff --git a/data/web/css/admin.css b/data/web/css/site/admin.css similarity index 76% rename from data/web/css/admin.css rename to data/web/css/site/admin.css index a53d721c..cadc4a3a 100644 --- a/data/web/css/admin.css +++ b/data/web/css/site/admin.css @@ -24,6 +24,11 @@ body.modal-open { overflow-y:scroll; padding-right: inherit !important; } +@media (min-width: 992px) { + .container { + width: 80%; + } +} .mass-actions-admin { user-select: none; padding:10px 0 10px 0; @@ -60,17 +65,9 @@ body.modal-open { .nav-tabs>li>a { z-index: 1; } -#settings_map { - font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; - font-size:9pt; - background:transparent; -} -.bootstrap-select { - width: auto!important; -} .table-condensed .input-sm { width: 100%!important; } -.full-width-select { - width: 100%!important; -} +.table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { + padding: 3px; +} \ No newline at end of file diff --git a/data/web/css/debug.css b/data/web/css/site/debug.css similarity index 92% rename from data/web/css/debug.css rename to data/web/css/site/debug.css index b127d5da..0eb81bc3 100644 --- a/data/web/css/debug.css +++ b/data/web/css/site/debug.css @@ -40,5 +40,4 @@ table.footable>tbody>tr.footable-empty>td { } tbody { font-size:14px; - color:#333; } \ No newline at end of file diff --git a/data/web/css/edit.css b/data/web/css/site/edit.css similarity index 100% rename from data/web/css/edit.css rename to data/web/css/site/edit.css diff --git a/data/web/css/mailbox.css b/data/web/css/site/mailbox.css similarity index 80% rename from data/web/css/mailbox.css rename to data/web/css/site/mailbox.css index da2e96e3..80ff063b 100644 --- a/data/web/css/mailbox.css +++ b/data/web/css/site/mailbox.css @@ -8,6 +8,14 @@ table.footable>tbody>tr.footable-empty>td { .panel panel-default { overflow: visible !important; } +.table-responsive { + overflow: auto !important; +} +@media screen and (max-width: 767px) { + .table-responsive { + overflow-x: scroll !important; + } +} .btn-group { width: max-content; } diff --git a/data/web/css/quarantine.css b/data/web/css/site/quarantine.css similarity index 69% rename from data/web/css/quarantine.css rename to data/web/css/site/quarantine.css index 6690ab90..5d0fa1ef 100644 --- a/data/web/css/quarantine.css +++ b/data/web/css/site/quarantine.css @@ -35,3 +35,17 @@ table.footable>tbody>tr.footable-empty>td { .inputMissingAttr { border-color: #FF4136; } +.dot-danger { + height: 10px; + width: 10px; + background-color: #ff4136; + border-radius: 50%; + display: inline-block; +} +.dot-neutral { + height: 10px; + width: 10px; + background-color: #d4d4d4; + border-radius: 50%; + display: inline-block; +} \ No newline at end of file diff --git a/data/web/css/user.css b/data/web/css/site/user.css similarity index 91% rename from data/web/css/user.css rename to data/web/css/site/user.css index e24bebe4..aa3ddad7 100644 --- a/data/web/css/user.css +++ b/data/web/css/site/user.css @@ -36,4 +36,7 @@ table.footable>tbody>tr.footable-empty>td { white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word; +} +body { + overflow-y:scroll; } \ No newline at end of file diff --git a/data/web/debug.php b/data/web/debug.php index 646aaa19..bbeda91c 100644 --- a/data/web/debug.php +++ b/data/web/debug.php @@ -1,16 +1,21 @@
-
- +
+ - +
@@ -300,17 +398,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
-
+
- +
-
- +
+ - +
@@ -338,7 +436,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -350,25 +456,25 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +

- - + +
-
- +
+
- +
@@ -414,13 +521,14 @@ if (isset($_SESSION['mailcow_cc_role'])) {
max. MiB
- + + 0 = โˆž
-
- +
- +
@@ -500,7 +608,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
+ + +
+
+
+
+
+
@@ -508,21 +624,45 @@ if (isset($_SESSION['mailcow_cc_role'])) {
-

Ratelimit

+

- +
-
- + +
+
+
+
+
+
+
+

ACL

+
+
+
+ +
+
+
@@ -541,19 +681,19 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
- +
- +
@@ -565,7 +705,60 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- + +
+
+
+ + + +

+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+
+
+
+
+
@@ -588,13 +781,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
- @@ -604,7 +797,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- @@ -625,7 +818,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -671,7 +864,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -683,7 +876,9 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- + +
+
+ + + + +

:

+
+
+ +
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+
+
+ +
+
+
+
+
+
@@ -885,7 +1141,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -924,7 +1180,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -936,7 +1192,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -965,14 +1221,13 @@ else { - - add('/web/js/site/edit.js'); +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; ?> diff --git a/data/web/fonts/PTSans.txt b/data/web/fonts/PTSans.txt new file mode 100644 index 00000000..1e09546e --- /dev/null +++ b/data/web/fonts/PTSans.txt @@ -0,0 +1,94 @@ +๏ปฟCopyright (c) 2010, ParaType Ltd. (http://www.paratype.com/public), +with Reserved Font Names "PT Sans" and "ParaType". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/data/web/fonts/SourceSansPro-Bold.woff2 b/data/web/fonts/SourceSansPro-Bold.woff2 deleted file mode 100644 index 89bfd796..00000000 Binary files a/data/web/fonts/SourceSansPro-Bold.woff2 and /dev/null differ diff --git a/data/web/fonts/SourceSansPro-BoldIt.woff2 b/data/web/fonts/SourceSansPro-BoldIt.woff2 deleted file mode 100644 index 83d5b491..00000000 Binary files a/data/web/fonts/SourceSansPro-BoldIt.woff2 and /dev/null differ diff --git a/data/web/fonts/SourceSansPro-Light.woff2 b/data/web/fonts/SourceSansPro-Light.woff2 deleted file mode 100644 index 75ec2c04..00000000 Binary files a/data/web/fonts/SourceSansPro-Light.woff2 and /dev/null differ diff --git a/data/web/fonts/SourceSansPro-Regular.woff2 b/data/web/fonts/SourceSansPro-Regular.woff2 deleted file mode 100644 index 6dda30cd..00000000 Binary files a/data/web/fonts/SourceSansPro-Regular.woff2 and /dev/null differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff b/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff new file mode 100644 index 00000000..7d6f0c4a Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff2 b/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff2 new file mode 100644 index 00000000..24b3daed Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-700.woff2 differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff b/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff new file mode 100644 index 00000000..b73c2004 Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff2 b/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff2 new file mode 100644 index 00000000..6d47b145 Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-italic.woff2 differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff b/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff new file mode 100644 index 00000000..b4223a1f Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff differ diff --git a/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff2 b/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff2 new file mode 100644 index 00000000..c1209b46 Binary files /dev/null and b/data/web/fonts/pt-sans-v9-cyrillic_latin-regular.woff2 differ diff --git a/data/web/img/languages.png b/data/web/img/languages.png new file mode 100644 index 00000000..85d9a6e5 Binary files /dev/null and b/data/web/img/languages.png differ diff --git a/data/web/inc/ajax/dns_diagnostics.php b/data/web/inc/ajax/dns_diagnostics.php index dd67dec9..8d9f74d7 100644 --- a/data/web/inc/ajax/dns_diagnostics.php +++ b/data/web/inc/ajax/dns_diagnostics.php @@ -10,9 +10,11 @@ define('state_optional', " 2"); if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "admin"|| $_SESSION['mailcow_cc_role'] == "domainadmin")) { $domains = mailbox('get', 'domains'); -foreach(mailbox('get', 'domains') as $dn) { - $domains = array_merge($domains, mailbox('get', 'alias_domains', $dn)); +$alias_domains = array(); +foreach($domains as $dn) { + $alias_domains = array_merge($alias_domains, mailbox('get', 'alias_domains', $dn)); } +$domains = array_merge($domains, $alias_domains); if (isset($_GET['domain'])) { if (is_valid_domain_name($_GET['domain'])) { @@ -105,76 +107,80 @@ if ($_SESSION['mailcow_cc_role'] == "admin") { 'TLSA', generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1) ); - $records[] = array( - '_'.$https_port. - '._tcp.'.$mailcow_hostname, - 'TLSA', - generate_tlsa_digest($mailcow_hostname, $https_port) - ); - $records[] = array( - '_'.$autodiscover_config['pop3']['tlsport']. - '._tcp.'.$autodiscover_config['pop3']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['tlsport'], 1) - ); - $records[] = array( - '_'.$autodiscover_config['imap']['tlsport']. - '._tcp.'.$autodiscover_config['imap']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['tlsport'], 1) - ); - $records[] = array( - '_'.$autodiscover_config['smtp']['port']. - '._tcp.'.$autodiscover_config['smtp']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['port']) - ); - $records[] = array( - '_'.$autodiscover_config['smtp']['tlsport']. - '._tcp.'.$autodiscover_config['smtp']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['tlsport'], 1) - ); - $records[] = array( - '_'.$autodiscover_config['imap']['port']. - '._tcp.'.$autodiscover_config['imap']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['port']) - ); - $records[] = array( - '_'.$autodiscover_config['pop3']['port']. - '._tcp.'.$autodiscover_config['pop3']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['port']) - ); - $records[] = array( - '_'.$autodiscover_config['sieve']['port']. - '._tcp.'.$autodiscover_config['sieve']['server'], - 'TLSA', - generate_tlsa_digest($autodiscover_config['sieve']['server'], $autodiscover_config['sieve']['port'], 1) - ); + if (!in_array($domain, $alias_domains)) { + $records[] = array( + '_'.$https_port. + '._tcp.'.$mailcow_hostname, + 'TLSA', + generate_tlsa_digest($mailcow_hostname, $https_port) + ); + $records[] = array( + '_'.$autodiscover_config['pop3']['tlsport']. + '._tcp.'.$autodiscover_config['pop3']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['tlsport'], 1) + ); + $records[] = array( + '_'.$autodiscover_config['imap']['tlsport']. + '._tcp.'.$autodiscover_config['imap']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['tlsport'], 1) + ); + $records[] = array( + '_'.$autodiscover_config['smtp']['port']. + '._tcp.'.$autodiscover_config['smtp']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['port']) + ); + $records[] = array( + '_'.$autodiscover_config['smtp']['tlsport']. + '._tcp.'.$autodiscover_config['smtp']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['tlsport'], 1) + ); + $records[] = array( + '_'.$autodiscover_config['imap']['port']. + '._tcp.'.$autodiscover_config['imap']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['port']) + ); + $records[] = array( + '_'.$autodiscover_config['pop3']['port']. + '._tcp.'.$autodiscover_config['pop3']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['port']) + ); + $records[] = array( + '_'.$autodiscover_config['sieve']['port']. + '._tcp.'.$autodiscover_config['sieve']['server'], + 'TLSA', + generate_tlsa_digest($autodiscover_config['sieve']['server'], $autodiscover_config['sieve']['port'], 1) + ); + } } $records[] = array( $domain, 'MX', $mailcow_hostname ); -$records[] = array( - 'autodiscover.'.$domain, - 'CNAME', - $mailcow_hostname -); -$records[] = array( - '_autodiscover._tcp.'.$domain, - 'SRV', - $mailcow_hostname. - ' '.$https_port -); -$records[] = array( - 'autoconfig.'.$domain, - 'CNAME', - $mailcow_hostname -); +if (!in_array($domain, $alias_domains)) { + $records[] = array( + 'autodiscover.'.$domain, + 'CNAME', + $mailcow_hostname + ); + $records[] = array( + '_autodiscover._tcp.'.$domain, + 'SRV', + $mailcow_hostname. + ' '.$https_port + ); + $records[] = array( + 'autoconfig.'.$domain, + 'CNAME', + $mailcow_hostname + ); +} $records[] = array( $domain, 'TXT', @@ -195,74 +201,76 @@ if (!empty($dkim = dkim('details', $domain))) { $dkim['dkim_txt'] ); } -$current_records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV); -if (count($current_records) == 0 || $current_records[0]['target'] != '') { - if ($autodiscover_config['pop3']['tlsport'] != '110') { +if (!in_array($domain, $alias_domains)) { + $current_records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV); + if (count($current_records) == 0 || $current_records[0]['target'] != '') { + if ($autodiscover_config['pop3']['tlsport'] != '110') { + $records[] = array( + '_pop3._tcp.' . $domain, + 'SRV', + $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['tlsport'] + ); + } + } + else { $records[] = array( '_pop3._tcp.' . $domain, 'SRV', - $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['tlsport'] + '. 0' ); } -} -else { - $records[] = array( - '_pop3._tcp.' . $domain, - 'SRV', - '. 0' - ); -} -$current_records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV); -if (count($current_records) == 0 || $current_records[0]['target'] != '') { - if ($autodiscover_config['pop3']['port'] != '995') { + $current_records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV); + if (count($current_records) == 0 || $current_records[0]['target'] != '') { + if ($autodiscover_config['pop3']['port'] != '995') { + $records[] = array( + '_pop3s._tcp.' . $domain, + 'SRV', + $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['port'] + ); + } + } + else { $records[] = array( '_pop3s._tcp.' . $domain, 'SRV', - $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['port'] + '. 0' + ); + } + if ($autodiscover_config['imap']['tlsport'] != '143') { + $records[] = array( + '_imap._tcp.' . $domain, + 'SRV', + $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['tlsport'] + ); + } + if ($autodiscover_config['imap']['port'] != '993') { + $records[] = array( + '_imaps._tcp.' . $domain, + 'SRV', + $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['port'] + ); + } + if ($autodiscover_config['smtp']['tlsport'] != '587') { + $records[] = array( + '_submission._tcp.' . $domain, + 'SRV', + $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['tlsport'] + ); + } + if ($autodiscover_config['smtp']['port'] != '465') { + $records[] = array( + '_smtps._tcp.' . $domain, + 'SRV', + $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['port'] + ); + } + if ($autodiscover_config['sieve']['port'] != '4190') { + $records[] = array( + '_sieve._tcp.' . $domain, + 'SRV', + $autodiscover_config['sieve']['server'] . ' ' . $autodiscover_config['sieve']['port'] ); } -} -else { - $records[] = array( - '_pop3s._tcp.' . $domain, - 'SRV', - '. 0' - ); -} -if ($autodiscover_config['imap']['tlsport'] != '143') { - $records[] = array( - '_imap._tcp.' . $domain, - 'SRV', - $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['tlsport'] - ); -} -if ($autodiscover_config['imap']['port'] != '993') { - $records[] = array( - '_imaps._tcp.' . $domain, - 'SRV', - $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['port'] - ); -} -if ($autodiscover_config['smtp']['tlsport'] != '587') { - $records[] = array( - '_submission._tcp.' . $domain, - 'SRV', - $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['tlsport'] - ); -} -if ($autodiscover_config['smtp']['port'] != '465') { - $records[] = array( - '_smtps._tcp.' . $domain, - 'SRV', - $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['port'] - ); -} -if ($autodiscover_config['sieve']['port'] != '4190') { - $records[] = array( - '_sieve._tcp.' . $domain, - 'SRV', - $autodiscover_config['sieve']['server'] . ' ' . $autodiscover_config['sieve']['port'] - ); } $record_types = array( diff --git a/data/web/inc/ajax/qitem_details.php b/data/web/inc/ajax/qitem_details.php index 801fd3d0..71d32cc9 100644 --- a/data/web/inc/ajax/qitem_details.php +++ b/data/web/inc/ajax/qitem_details.php @@ -40,6 +40,13 @@ if (!empty($_GET['id']) && ctype_alnum($_GET['id'])) { $data['text_plain'] = $mail_parser->getMessageBody('text'); // Get html content and convert to text $data['text_html'] = $html2text->convert($mail_parser->getMessageBody('html')); + if (empty($data['text_plain']) && empty($data['text_html'])) { + // Failed to parse content, try raw + $text = trim(substr($mailc['msg'], strpos($mailc['msg'], "\r\n\r\n") + 1)); + // Only return html->text + $data['text_plain'] = 'Parser failed, assuming HTML'; + $data['text_html'] = $html2text->convert($text); + } (empty($data['text_plain'])) ? $data['text_plain'] = '-' : null; // Get subject $data['subject'] = $mail_parser->getHeader('subject'); @@ -67,6 +74,9 @@ if (!empty($_GET['id']) && ctype_alnum($_GET['id'])) { } } if (isset($_GET['att'])) { + if ($_SESSION['acl']['quarantine_attachments'] == 0) { + exit(json_encode('Forbidden')); + } $dl_id = intval($_GET['att']); $dl_filename = $data['attachments'][$dl_id][0]; if (!is_dir($tmpdir . $dl_filename) && file_exists($tmpdir . $dl_filename)) { diff --git a/data/web/inc/ajax/qr_gen.php b/data/web/inc/ajax/qr_gen.php new file mode 100644 index 00000000..a39c3f64 --- /dev/null +++ b/data/web/inc/ajax/qr_gen.php @@ -0,0 +1,13 @@ +getQRCodeImageAsDataUri($_SESSION['mailcow_cc_username'], $_GET['token']); +} + +?> diff --git a/data/web/inc/ajax/queue_manager.php b/data/web/inc/ajax/queue_manager.php new file mode 100644 index 00000000..8ae5cb35 --- /dev/null +++ b/data/web/inc/ajax/queue_manager.php @@ -0,0 +1,16 @@ + 'mailq')); + +if (isset($docker_return['type']['danger'])) { + echo "Cannot load mail queue: " . $docker_return['msg']; +} +else { + echo $docker_return; +} +?> diff --git a/data/web/inc/ajax/relay_check.php b/data/web/inc/ajax/transport_check.php similarity index 64% rename from data/web/inc/ajax/relay_check.php rename to data/web/inc/ajax/transport_check.php index 34f8eceb..e956f4f2 100644 --- a/data/web/inc/ajax/relay_check.php +++ b/data/web/inc/ajax/transport_check.php @@ -4,23 +4,49 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php'; error_reporting(0); if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") { - $relayhost_id = intval($_GET['relayhost_id']); + $transport_id = intval($_GET['transport_id']); + $transport_type = $_GET['transport_type']; if (isset($_GET['mail_from']) && filter_var($_GET['mail_from'], FILTER_VALIDATE_EMAIL)) { $mail_from = $_GET['mail_from']; } else { $mail_from = "relay@example.org"; } - $relayhost_details = relayhost('details', $relayhost_id); - if (!empty($relayhost_details)) { + if ($transport_type == 'transport-map') { + $transport_details = transport('details', $transport_id); + $nexthop = $transport_details['nexthop']; + } + elseif ($transport_type == 'sender-dependent') { + $transport_details = relayhost('details', $transport_id); + $nexthop = $transport_details['hostname']; + } + if (!empty($transport_details)) { // Remove [ and ] - $hostname_w_port = preg_replace('/\[|\]/', '', $relayhost_details['hostname']); + $hostname_w_port = preg_replace('/\[|\]/', '', $nexthop); + $skip_lookup_mx = strpos($nexthop, '['); // Explode to hostname and port list($hostname, $port) = explode(':', $hostname_w_port); + // Try to get MX if host is not [host] + if ($skip_lookup_mx === false) { + getmxrr($hostname, $mx_records, $mx_weight); + if (!empty($mx_records)) { + for ($i = 0; $i < count($mx_records); $i++) { + $mxs[$mx_records[$i]] = $mx_weight[$i]; + } + asort ($mxs); + $records = array_keys($mxs); + echo 'Using first matched primary MX for "' . $hostname . '": '; + $hostname = $records[0]; + echo $hostname . '
'; + } + else { + echo 'No MX records for ' . $hostname . ' were found in DNS, skipping and using hostname as next-hop.
'; + } + } // Use port 25 if no port was given $port = (empty($port)) ? 25 : $port; - $username = $relayhost_details['username']; - $password = $relayhost_details['password']; + $username = $transport_details['username']; + $password = $transport_details['password']; $mail = new PHPMailer; $mail->Timeout = 10; @@ -32,6 +58,9 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi ) ); $mail->SMTPDebug = 3; + if ($port == 465) { + $mail->SMTPSecure = "ssl"; + } $mail->Debugoutput = function($str, $level) { foreach(preg_split("/((\r?\n)|(\r\n?)|\n)/", $str) as $line){ if (empty($line)) { continue; } @@ -73,7 +102,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi $mail->send(); } else { - echo "Unknown relayhost."; + echo "Unknown transport."; } } else { diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php index cdef8e0b..f1cca54c 100644 --- a/data/web/inc/footer.inc.php +++ b/data/web/inc/footer.inc.php @@ -3,19 +3,17 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/footer.php'; logger(); ?>
- - - - - - - - - - - + - - - - - - - - - - - - - - - -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> - - + + + + + + <?=$UI_TEXTS['title_name'];?> + add('/web/css/site/mailbox.css'); + } + if (preg_match("/admin/i", $_SERVER['REQUEST_URI'])) { + $css_minifier->add('/web/css/site/admin.css'); + } + if (preg_match("/user/i", $_SERVER['REQUEST_URI'])) { + $css_minifier->add('/web/css/site/user.css'); + } + if (preg_match("/edit/i", $_SERVER['REQUEST_URI'])) { + $css_minifier->add('/web/css/site/edit.css'); + } + if (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) { + $css_minifier->add('/web/css/site/quarantine.css'); + } + if (preg_match("/debug/i", $_SERVER['REQUEST_URI'])) { + $css_minifier->add('/web/css/site/debug.css'); + } + ?> + + + + + + -
- -
+ + +
  • + +
  • ()
  • + + +
    +
    + +
    diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index c318d634..3c553bfd 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "19082018_1004"; + $db_version = "30032019_1905"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -78,7 +78,6 @@ function init_db_schema() { // TODO -> use TEXT and check if SOGo login breaks on empty aliases "aliases" => "TEXT NOT NULL", "ad_aliases" => "VARCHAR(6144) NOT NULL DEFAULT ''", - "home" => "VARCHAR(255)", "kind" => "VARCHAR(100) NOT NULL DEFAULT ''", "multiple_bookings" => "INT NOT NULL DEFAULT -1" ), @@ -110,6 +109,26 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "transports" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "destination" => "VARCHAR(255) NOT NULL", + "nexthop" => "VARCHAR(255) NOT NULL", + "username" => "VARCHAR(255) NOT NULL", + "password" => "VARCHAR(255) NOT NULL", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ), + "key" => array( + "destination" => array("destination"), + "nexthop" => array("nexthop"), + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "alias" => array( "cols" => array( "id" => "INT NOT NULL AUTO_INCREMENT", @@ -118,6 +137,8 @@ function init_db_schema() { "domain" => "VARCHAR(255) NOT NULL", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "private_comment" => "TEXT", + "public_comment" => "TEXT", "active" => "TINYINT(1) NOT NULL DEFAULT '1'" ), "keys" => array( @@ -135,7 +156,6 @@ function init_db_schema() { ), "api" => array( "cols" => array( - "username" => "VARCHAR(255) NOT NULL", "api_key" => "VARCHAR(255) NOT NULL", "allow_from" => "VARCHAR(512) NOT NULL", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", @@ -144,16 +164,8 @@ function init_db_schema() { ), "keys" => array( "primary" => array( - "" => array("username") + "" => array("api_key") ), - "fkey" => array( - "fk_username_api" => array( - "col" => "username", - "ref" => "admin.username", - "delete" => "CASCADE", - "update" => "CASCADE" - ) - ) ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), @@ -171,6 +183,7 @@ function init_db_schema() { "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), "domain" => array( + // Todo: Move some attributes to json "cols" => array( "domain" => "VARCHAR(255) NOT NULL", "description" => "VARCHAR(255)", @@ -180,6 +193,7 @@ function init_db_schema() { "quota" => "BIGINT(20) NOT NULL DEFAULT '102400'", "relayhost" => "VARCHAR(255) NOT NULL DEFAULT '0'", "backupmx" => "TINYINT(1) NOT NULL DEFAULT '0'", + "gal" => "TINYINT(1) NOT NULL DEFAULT '1'", "relay_all_recipients" => "TINYINT(1) NOT NULL DEFAULT '0'", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", @@ -192,18 +206,40 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "tls_policy_override" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "dest" => "VARCHAR(255) NOT NULL", + "policy" => "ENUM('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL", + "parameters" => "VARCHAR(255) DEFAULT ''", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ), + "unique" => array( + "dest" => array("dest") + ), + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "quarantine" => array( "cols" => array( "id" => "INT NOT NULL AUTO_INCREMENT", "qid" => "VARCHAR(30) NOT NULL", + "subject" => "VARCHAR(500)", "score" => "FLOAT(8,2)", - "ip" => "VARBINARY(16)", + "ip" => "VARCHAR(50)", "action" => "CHAR(20) NOT NULL DEFAULT 'unknown'", "symbols" => "JSON", "sender" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'", "rcpt" => "VARCHAR(255)", "msg" => "LONGTEXT", "domain" => "VARCHAR(255)", + "notified" => "TINYINT(1) NOT NULL DEFAULT '0'", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "user" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'", ), @@ -219,7 +255,8 @@ function init_db_schema() { "username" => "VARCHAR(255) NOT NULL", "password" => "VARCHAR(255) NOT NULL", "name" => "VARCHAR(255)", - "maildir" => "VARCHAR(255) NOT NULL", + // mailbox_path_prefix is followed by domain/local_part/ + "mailbox_path_prefix" => "VARCHAR(150) DEFAULT '/var/vmail/'", "quota" => "BIGINT(20) NOT NULL DEFAULT '102400'", "local_part" => "VARCHAR(255) NOT NULL", "domain" => "VARCHAR(255) NOT NULL", @@ -280,10 +317,10 @@ function init_db_schema() { "delimiter_action" => "TINYINT(1) NOT NULL DEFAULT '1'", "syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'", "eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'", - "filters" => "TINYINT(1) NOT NULL DEFAULT '1'", + "sogo_profile_reset" => "TINYINT(1) NOT NULL DEFAULT '1'", "quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'", - "bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'", - "recipient_maps" => "TINYINT(1) NOT NULL DEFAULT '0'", + "quarantine_attachments" => "TINYINT(1) NOT NULL DEFAULT '1'", + "quarantine_notification" => "TINYINT(1) NOT NULL DEFAULT '1'", ), "keys" => array( "primary" => array( @@ -417,6 +454,26 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "da_acl" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'", + "quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'", + "login_as" => "TINYINT(1) NOT NULL DEFAULT '1'", + "bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'", + "filters" => "TINYINT(1) NOT NULL DEFAULT '1'", + "ratelimit" => "TINYINT(1) NOT NULL DEFAULT '1'", + "spam_policy" => "TINYINT(1) NOT NULL DEFAULT '1'", + "unlimited_quota" => "TINYINT(1) NOT NULL DEFAULT '0'", + "alias_domains" => "TINYINT(1) NOT NULL DEFAULT '0'", + ), + "keys" => array( + "primary" => array( + "" => array("username") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "imapsync" => array( "cols" => array( "id" => "INT NOT NULL AUTO_INCREMENT", @@ -935,30 +992,88 @@ DELIMITER ;'; // Insert new DB schema version $stmt = $pdo->query("REPLACE INTO `versions` (`application`, `version`) VALUES ('db_schema', '" . $db_version . "');"); - // Migrate tls_enforce_* options and add force_pw_update attribute - $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` IS NULL;"); - $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', 0) WHERE JSON_EXTRACT(`attributes`, '$.force_pw_update') IS NULL;"); + // Migrate attributes + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;"); + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', \"0\") WHERE JSON_EXTRACT(`attributes`, '$.force_pw_update') IS NULL;"); + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_access', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.sogo_access') IS NULL;"); + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.mailbox_format', \"maildir:\") WHERE JSON_EXTRACT(`attributes`, '$.mailbox_format') IS NULL;"); + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.quarantine_notification', \"never\") WHERE JSON_EXTRACT(`attributes`, '$.quarantine_notification') IS NULL;"); foreach($tls_options as $tls_user => $tls_options) { $stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_enforce_in), `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_enforce_out) WHERE `username` = :username"); $stmt->execute(array(':tls_enforce_in' => $tls_options['tls_enforce_in'], ':tls_enforce_out' => $tls_options['tls_enforce_out'], ':username' => $tls_user)); } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__), - 'msg' => 'db_init_complete' - ); - - // Fix user_acl + // Set tls_enforce_* if still missing (due to deleted attrs for example) + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.tls_enforce_out') IS NULL;"); + $stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.tls_enforce_in') IS NULL;"); + // Fix ACL $stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);"); + $stmt = $pdo->query("INSERT INTO `da_acl` (`username`) SELECT DISTINCT `username` FROM `domain_admins` WHERE `username` != 'admin' AND NOT EXISTS (SELECT `username` FROM `da_acl`);"); + // Fix domain_admins + $stmt = $pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';"); + + if (php_sapi_name() == "cli") { + echo "DB initialization completed" . PHP_EOL; + } else { + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__), + 'msg' => 'db_init_complete' + ); + } } catch (PDOException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__), - 'msg' => array('mysql_error', $e) - ); + if (php_sapi_name() == "cli") { + echo "DB initialization failed: " . print_r($e, true) . PHP_EOL; + } else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__), + 'msg' => array('mysql_error', $e) + ); + } } } -?> +if (php_sapi_name() == "cli") { + include '/web/inc/vars.inc.php'; + // $now = new DateTime(); + // $mins = $now->getOffset() / 60; + // $sgn = ($mins < 0 ? -1 : 1); + // $mins = abs($mins); + // $hrs = floor($mins / 60); + // $mins -= $hrs * 60; + // $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); + $dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; + $opt = [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + //PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "', group_concat_max_len = 3423543543;", + ]; + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); + $stmt = $pdo->query("SELECT COUNT('OK') AS OK_C FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view' OR TABLE_NAME = '_sogo_static_view';"); + $res = $stmt->fetch(PDO::FETCH_ASSOC); + if (intval($res['OK_C']) === 2) { + // Be more precise when replacing into _sogo_static_view, col orders may change + try { + $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `kind`, `multiple_bookings`) + SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `kind`, `multiple_bookings` from sogo_view"); + $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); + echo "Fixed _sogo_static_view" . PHP_EOL; + } + catch ( Exception $e ) { + // Dunno + } + } + try { + $m = new Memcached(); + $m->addServer('memcached', 11211); + $m->flush(); + echo "Cleaned up memcached". PHP_EOL; + } + catch ( Exception $e ) { + // Dunno + } + init_db_schema(); +} diff --git a/data/web/inc/languages.min.css b/data/web/inc/languages.min.css deleted file mode 100644 index 7293e888..00000000 --- a/data/web/inc/languages.min.css +++ /dev/null @@ -1 +0,0 @@ -.lang-lg,.lang-sm,.lang-xs{background-repeat:no-repeat;display:inline-block;background-image:url(languages.png)}.lang-sm,.lang-sm:after,.lang-xs,.lang-xs:after{position:relative}.lang-xs{background-position:0 -484px;min-width:14px;height:11px;min-height:11px;max-height:11px}.lang-sm{background-position:0 -1199px;min-width:22px;height:16px;min-height:16px;max-height:16px}.lang-lg{background-position:0 -2134px;min-width:30px;height:22px;min-height:22px;max-height:22px}.lang-xs[lang=ar]{background-position:0 0}.lang-xs[lang=be]{background-position:0 -11px}.lang-xs[lang=bg]{background-position:0 -22px}.lang-xs[lang=cs]{background-position:0 -33px}.lang-xs[lang=da]{background-position:0 -44px}.lang-xs[lang=de]{background-position:0 -55px}.lang-xs[lang=el]{background-position:0 -66px}.lang-xs[lang=en]{background-position:0 -77px}.lang-xs[lang=es]{background-position:0 -88px}.lang-xs[lang=et]{background-position:0 -99px}.lang-xs[lang=fi]{background-position:0 -110px}.lang-xs[lang=fr]{background-position:0 -121px}.lang-xs[lang=ga]{background-position:0 -132px}.lang-xs[lang=hi]{background-position:0 -143px}.lang-xs[lang=hr]{background-position:0 -154px}.lang-xs[lang=hu]{background-position:0 -165px}.lang-xs[lang=in]{background-position:0 -176px}.lang-xs[lang=is]{background-position:0 -187px}.lang-xs[lang=it]{background-position:0 -198px}.lang-xs[lang=iw]{background-position:0 -209px}.lang-xs[lang=ja]{background-position:0 -220px}.lang-xs[lang=ko]{background-position:0 -231px}.lang-xs[lang=lt]{background-position:0 -242px}.lang-xs[lang=lv]{background-position:0 -253px}.lang-xs[lang=mk]{background-position:0 -264px}.lang-xs[lang=ms]{background-position:0 -275px}.lang-xs[lang=mt]{background-position:0 -286px}.lang-xs[lang=nl]{background-position:0 -297px}.lang-xs[lang=no]{background-position:0 -308px}.lang-xs[lang=pl]{background-position:0 -319px}.lang-xs[lang=pt]{background-position:0 -330px}.lang-xs[lang=ro]{background-position:0 -341px}.lang-xs[lang=ru]{background-position:0 -352px}.lang-xs[lang=sk]{background-position:0 -363px}.lang-xs[lang=sl]{background-position:0 -374px}.lang-xs[lang=sq]{background-position:0 -385px}.lang-xs[lang=sr]{background-position:0 -396px}.lang-xs[lang=sv]{background-position:0 -407px}.lang-xs[lang=th]{background-position:0 -418px}.lang-xs[lang=tr]{background-position:0 -429px}.lang-xs[lang=uk]{background-position:0 -440px}.lang-xs[lang=vi]{background-position:0 -451px}.lang-xs[lang=zh]{background-position:0 -462px}.lang-xs[lang=ca]{background-position:0 -473px}.lang-sm[lang=ar]{background-position:0 -495px}.lang-sm[lang=be]{background-position:0 -511px}.lang-sm[lang=bg]{background-position:0 -527px}.lang-sm[lang=cs]{background-position:0 -543px}.lang-sm[lang=da]{background-position:0 -559px}.lang-sm[lang=de]{background-position:0 -575px}.lang-sm[lang=el]{background-position:0 -591px}.lang-sm[lang=en]{background-position:0 -607px}.lang-sm[lang=es]{background-position:0 -623px}.lang-sm[lang=et]{background-position:0 -639px}.lang-sm[lang=fi]{background-position:0 -655px}.lang-sm[lang=fr]{background-position:0 -671px}.lang-sm[lang=ga]{background-position:0 -687px}.lang-sm[lang=hi]{background-position:0 -703px}.lang-sm[lang=hr]{background-position:0 -719px}.lang-sm[lang=hu]{background-position:0 -735px}.lang-sm[lang=in]{background-position:0 -751px}.lang-sm[lang=is]{background-position:0 -767px}.lang-sm[lang=it]{background-position:0 -783px}.lang-sm[lang=iw]{background-position:0 -799px}.lang-sm[lang=ja]{background-position:0 -815px}.lang-sm[lang=ko]{background-position:0 -831px}.lang-sm[lang=lt]{background-position:0 -847px}.lang-sm[lang=lv]{background-position:0 -863px}.lang-sm[lang=mk]{background-position:0 -879px}.lang-sm[lang=ms]{background-position:0 -895px}.lang-sm[lang=mt]{background-position:0 -911px}.lang-sm[lang=nl]{background-position:0 -927px}.lang-sm[lang=no]{background-position:0 -943px}.lang-sm[lang=pl]{background-position:0 -959px}.lang-sm[lang=pt]{background-position:0 -975px}.lang-sm[lang=ro]{background-position:0 -991px}.lang-sm[lang=ru]{background-position:0 -1007px}.lang-sm[lang=sk]{background-position:0 -1023px}.lang-sm[lang=sl]{background-position:0 -1039px}.lang-sm[lang=sq]{background-position:0 -1055px}.lang-sm[lang=sr]{background-position:0 -1071px}.lang-sm[lang=sv]{background-position:0 -1087px}.lang-sm[lang=th]{background-position:0 -1103px}.lang-sm[lang=tr]{background-position:0 -1119px}.lang-sm[lang=uk]{background-position:0 -1135px}.lang-sm[lang=vi]{background-position:0 -1151px}.lang-sm[lang=zh]{background-position:0 -1167px}.lang-sm[lang=ca]{background-position:0 -1183px}.lang-lg[lang=ar]{background-position:0 -1188px}.lang-lg[lang=be]{background-position:0 -1210px}.lang-lg[lang=bg]{background-position:0 -1232px}.lang-lg[lang=cs]{background-position:0 -1254px}.lang-lg[lang=da]{background-position:0 -1276px}.lang-lg[lang=de]{background-position:0 -1298px}.lang-lg[lang=el]{background-position:0 -1320px}.lang-lg[lang=en]{background-position:0 -1342px}.lang-lg[lang=es]{background-position:0 -1364px}.lang-lg[lang=et]{background-position:0 -1386px}.lang-lg[lang=fi]{background-position:0 -1408px}.lang-lg[lang=fr]{background-position:0 -1430px}.lang-lg[lang=ga]{background-position:0 -1452px}.lang-lg[lang=hi]{background-position:0 -1474px}.lang-lg[lang=hr]{background-position:0 -1496px}.lang-lg[lang=hu]{background-position:0 -1518px}.lang-lg[lang=in]{background-position:0 -1540px}.lang-lg[lang=is]{background-position:0 -1562px}.lang-lg[lang=it]{background-position:0 -1584px}.lang-lg[lang=iw]{background-position:0 -1606px}.lang-lg[lang=ja]{background-position:0 -1628px}.lang-lg[lang=ko]{background-position:0 -1650px}.lang-lg[lang=lt]{background-position:0 -1672px}.lang-lg[lang=lv]{background-position:0 -1694px}.lang-lg[lang=mk]{background-position:0 -1716px}.lang-lg[lang=ms]{background-position:0 -1738px}.lang-lg[lang=mt]{background-position:0 -1760px}.lang-lg[lang=nl]{background-position:0 -1782px}.lang-lg[lang=no]{background-position:0 -1804px}.lang-lg[lang=pl]{background-position:0 -1826px}.lang-lg[lang=pt]{background-position:0 -1848px}.lang-lg[lang=ro]{background-position:0 -1870px}.lang-lg[lang=ru]{background-position:0 -1892px}.lang-lg[lang=sk]{background-position:0 -1914px}.lang-lg[lang=sl]{background-position:0 -1936px}.lang-lg[lang=sq]{background-position:0 -1958px}.lang-lg[lang=sr]{background-position:0 -1980px}.lang-lg[lang=sv]{background-position:0 -2002px}.lang-lg[lang=th]{background-position:0 -2024px}.lang-lg[lang=tr]{background-position:0 -2046px}.lang-lg[lang=uk]{background-position:0 -2068px}.lang-lg[lang=vi]{background-position:0 -2090px}.lang-lg[lang=zh]{background-position:0 -2112px}.lang-lbl-en:after,.lang-lbl-full:after,.lang-lbl:after{content:"Unknown language"}.lang-lbl[lang=ar]:after{content:"\000627\000644\000639\000631\000628\00064A\000629"}.lang-lbl[lang=be]:after{content:"\000411\000435\00043B\000430\000440\000443\000441\00043A\000456"}.lang-lbl[lang=bg]:after{content:"\000411\00044A\00043B\000433\000430\000440\000441\00043A\000438"}.lang-lbl[lang=ca]:after{content:"Catal\0000E0"}.lang-lbl[lang=cs]:after{content:"\00010Ce\000161tina"}.lang-lbl[lang=da]:after{content:"Dansk"}.lang-lbl[lang=de]:after{content:"Deutsch"}.lang-lbl[lang=el]:after{content:"\000395\0003BB\0003BB\0003B7\0003BD\0003B9\0003BA\0003AC"}.lang-lbl[lang=en]:after{content:"English"}.lang-lbl[lang=es]:after{content:"Espa\0000F1ol"}.lang-lbl[lang=et]:after{content:"Eesti"}.lang-lbl[lang=fi]:after{content:"Suomi"}.lang-lbl[lang=fr]:after{content:"Fran\0000E7ais"}.lang-lbl[lang=ga]:after{content:"Gaeilge"}.lang-lbl[lang=hi]:after{content:"\000939\00093F\000902\000926\000940"}.lang-lbl[lang=hr]:after{content:"Hrvatski"}.lang-lbl[lang=hu]:after{content:"Magyar"}.lang-lbl[lang=in]:after{content:"Bahasa\000020indonesia"}.lang-lbl[lang=is]:after{content:"\0000CDslenska"}.lang-lbl[lang=it]:after{content:"Italiano"}.lang-lbl[lang=iw]:after{content:"\0005E2\0005D1\0005E8\0005D9\0005EA"}.lang-lbl[lang=ja]:after{content:"\0065E5\00672C\008A9E"}.lang-lbl[lang=ko]:after{content:"\00D55C\00AD6D\00C5B4"}.lang-lbl[lang=lt]:after{content:"Lietuvi\000173"}.lang-lbl[lang=lv]:after{content:"Latvie\000161u"}.lang-lbl[lang=mk]:after{content:"\00041C\000430\00043A\000435\000434\00043E\00043D\000441\00043A\000438"}.lang-lbl[lang=ms]:after{content:"Bahasa\000020melayu"}.lang-lbl[lang=mt]:after{content:"Malti"}.lang-lbl[lang=nl]:after{content:"Nederlands"}.lang-lbl[lang=no]:after{content:"Norsk"}.lang-lbl[lang=pl]:after{content:"Polski"}.lang-lbl[lang=pt]:after{content:"Portugu\0000EAs"}.lang-lbl[lang=ro]:after{content:"Rom\0000E2n\000103"}.lang-lbl[lang=ru]:after{content:"\000420\000443\000441\000441\00043A\000438\000439"}.lang-lbl[lang=sk]:after{content:"Sloven\00010Dina"}.lang-lbl[lang=sl]:after{content:"Sloven\000161\00010Dina"}.lang-lbl[lang=sq]:after{content:"Shqipe"}.lang-lbl[lang=sr]:after{content:"\000421\000440\00043F\000441\00043A\000438"}.lang-lbl[lang=sv]:after{content:"Svenska"}.lang-lbl[lang=th]:after{content:"\000E44\000E17\000E22"}.lang-lbl[lang=tr]:after{content:"T\0000FCrk\0000E7e"}.lang-lbl[lang=uk]:after{content:"\000423\00043A\000440\000430\000457\00043D\000441\00044C\00043A\000430"}.lang-lbl[lang=vi]:after{content:"Ti\001EBFng\000020vi\001EC7t"}.lang-lbl[lang=zh]:after{content:"\004E2D\006587"}.lang-lbl-en[lang=ar]:after{content:"Arabic"}.lang-lbl-en[lang=be]:after{content:"Belarusian"}.lang-lbl-en[lang=bg]:after{content:"Bulgarian"}.lang-lbl-en[lang=ca]:after{content:"Catalan"}.lang-lbl-en[lang=cs]:after{content:"Czech"}.lang-lbl-en[lang=da]:after{content:"Danish"}.lang-lbl-en[lang=de]:after{content:"German"}.lang-lbl-en[lang=el]:after{content:"Greek"}.lang-lbl-en[lang=en]:after{content:"English"}.lang-lbl-en[lang=es]:after{content:"Spanish"}.lang-lbl-en[lang=et]:after{content:"Estonian"}.lang-lbl-en[lang=fi]:after{content:"Finnish"}.lang-lbl-en[lang=fr]:after{content:"French"}.lang-lbl-en[lang=ga]:after{content:"Irish"}.lang-lbl-en[lang=hi]:after{content:"Hindi"}.lang-lbl-en[lang=hr]:after{content:"Croatian"}.lang-lbl-en[lang=hu]:after{content:"Hungarian"}.lang-lbl-en[lang=in]:after{content:"Indonesian"}.lang-lbl-en[lang=is]:after{content:"Icelandic"}.lang-lbl-en[lang=it]:after{content:"Italian"}.lang-lbl-en[lang=iw]:after{content:"Hebrew"}.lang-lbl-en[lang=ja]:after{content:"Japanese"}.lang-lbl-en[lang=ko]:after{content:"Korean"}.lang-lbl-en[lang=lt]:after{content:"Lithuanian"}.lang-lbl-en[lang=lv]:after{content:"Latvian"}.lang-lbl-en[lang=mk]:after{content:"Macedonian"}.lang-lbl-en[lang=ms]:after{content:"Malay"}.lang-lbl-en[lang=mt]:after{content:"Maltese"}.lang-lbl-en[lang=nl]:after{content:"Dutch"}.lang-lbl-en[lang=no]:after{content:"Norwegian"}.lang-lbl-en[lang=pl]:after{content:"Polish"}.lang-lbl-en[lang=pt]:after{content:"Portuguese"}.lang-lbl-en[lang=ro]:after{content:"Romanian"}.lang-lbl-en[lang=ru]:after{content:"Russian"}.lang-lbl-en[lang=sk]:after{content:"Slovak"}.lang-lbl-en[lang=sl]:after{content:"Slovenian"}.lang-lbl-en[lang=sq]:after{content:"Albanian"}.lang-lbl-en[lang=sr]:after{content:"Serbian"}.lang-lbl-en[lang=sv]:after{content:"Swedish"}.lang-lbl-en[lang=th]:after{content:"Thai"}.lang-lbl-en[lang=tr]:after{content:"Turkish"}.lang-lbl-en[lang=uk]:after{content:"Ukrainian"}.lang-lbl-en[lang=vi]:after{content:"Vietnamese"}.lang-lbl-en[lang=zh]:after{content:"Chinese"}.lang-lbl-full[lang=ar]:after{content:"\000627\000644\000639\000631\000628\00064A\000629\0000A0/\0000A0Arabic"}.lang-lbl-full[lang=be]:after{content:"\000411\000435\00043B\000430\000440\000443\000441\00043A\000456\0000A0/\0000A0Belarusian"}.lang-lbl-full[lang=bg]:after{content:"\000411\00044A\00043B\000433\000430\000440\000441\00043A\000438\0000A0/\0000A0Bulgarian"}.lang-lbl-full[lang=ca]:after{content:"Catal\0000E0\0000A0/\0000A0Catalan"}.lang-lbl-full[lang=cs]:after{content:"\00010Ce\000161tina\0000A0/\0000A0Czech"}.lang-lbl-full[lang=da]:after{content:"Dansk\0000A0/\0000A0Danish"}.lang-lbl-full[lang=de]:after{content:"Deutsch\0000A0/\0000A0German"}.lang-lbl-full[lang=el]:after{content:"\000395\0003BB\0003BB\0003B7\0003BD\0003B9\0003BA\0003AC\0000A0/\0000A0Greek"}.lang-lbl-full[lang=en]:after{content:"English\0000A0/\0000A0English"}.lang-lbl-full[lang=es]:after{content:"Espa\0000F1ol\0000A0/\0000A0Spanish"}.lang-lbl-full[lang=et]:after{content:"Eesti\0000A0/\0000A0Estonian"}.lang-lbl-full[lang=fi]:after{content:"Suomi\0000A0/\0000A0Finnish"}.lang-lbl-full[lang=fr]:after{content:"Fran\0000E7ais\0000A0/\0000A0French"}.lang-lbl-full[lang=ga]:after{content:"Gaeilge\0000A0/\0000A0Irish"}.lang-lbl-full[lang=hi]:after{content:"\000939\00093F\000902\000926\000940\0000A0/\0000A0Hindi"}.lang-lbl-full[lang=hr]:after{content:"Hrvatski\0000A0/\0000A0Croatian"}.lang-lbl-full[lang=hu]:after{content:"Magyar\0000A0/\0000A0Hungarian"}.lang-lbl-full[lang=in]:after{content:"Bahasa\000020indonesia\0000A0/\0000A0Indonesian"}.lang-lbl-full[lang=is]:after{content:"\0000CDslenska\0000A0/\0000A0Icelandic"}.lang-lbl-full[lang=it]:after{content:"Italiano\0000A0/\0000A0Italian"}.lang-lbl-full[lang=iw]:after{content:"\0005E2\0005D1\0005E8\0005D9\0005EA\0000A0/\0000A0Hebrew"}.lang-lbl-full[lang=ja]:after{content:"\0065E5\00672C\008A9E\0000A0/\0000A0Japanese"}.lang-lbl-full[lang=ko]:after{content:"\00D55C\00AD6D\00C5B4\0000A0/\0000A0Korean"}.lang-lbl-full[lang=lt]:after{content:"Lietuvi\000173\0000A0/\0000A0Lithuanian"}.lang-lbl-full[lang=lv]:after{content:"Latvie\000161u\0000A0/\0000A0Latvian"}.lang-lbl-full[lang=mk]:after{content:"\00041C\000430\00043A\000435\000434\00043E\00043D\000441\00043A\000438\0000A0/\0000A0Macedonian"}.lang-lbl-full[lang=ms]:after{content:"Bahasa\000020melayu\0000A0/\0000A0Malay"}.lang-lbl-full[lang=mt]:after{content:"Malti\0000A0/\0000A0Maltese"}.lang-lbl-full[lang=nl]:after{content:"Nederlands\0000A0/\0000A0Dutch"}.lang-lbl-full[lang=no]:after{content:"Norsk\0000A0/\0000A0Norwegian"}.lang-lbl-full[lang=pl]:after{content:"Polski\0000A0/\0000A0Polish"}.lang-lbl-full[lang=pt]:after{content:"Portugu\0000EAs\0000A0/\0000A0Portuguese"}.lang-lbl-full[lang=ro]:after{content:"Rom\0000E2n\000103\0000A0/\0000A0Romanian"}.lang-lbl-full[lang=ru]:after{content:"\000420\000443\000441\000441\00043A\000438\000439\0000A0/\0000A0Russian"}.lang-lbl-full[lang=sk]:after{content:"Sloven\00010Dina\0000A0/\0000A0Slovak"}.lang-lbl-full[lang=sl]:after{content:"Sloven\000161\00010Dina\0000A0/\0000A0Slovenian"}.lang-lbl-full[lang=sq]:after{content:"Shqipe\0000A0/\0000A0Albanian"}.lang-lbl-full[lang=sr]:after{content:"\000421\000440\00043F\000441\00043A\000438\0000A0/\0000A0Serbian"}.lang-lbl-full[lang=sv]:after{content:"Svenska\0000A0/\0000A0Swedish"}.lang-lbl-full[lang=th]:after{content:"\000E44\000E17\000E22\0000A0/\0000A0Thai"}.lang-lbl-full[lang=tr]:after{content:"T\0000FCrk\0000E7e\0000A0/\0000A0Turkish"}.lang-lbl-full[lang=uk]:after{content:"\000423\00043A\000440\000430\000457\00043D\000441\00044C\00043A\000430\0000A0/\0000A0Ukrainian"}.lang-lbl-full[lang=vi]:after{content:"Ti\001EBFng\000020vi\001EC7t\0000A0/\0000A0Vietnamese"}.lang-lbl-full[lang=zh]:after{content:"\004E2D\006587\0000A0/\0000A0Chinese"}.lang-lg:before,.lang-sm:before,.lang-xs:before{content:'\0000A0'}.lang-xs.lang-lbl,.lang-xs.lang-lbl-en,.lang-xs.lang-lbl-full{padding-left:16px}.lang-sm.lang-lbl,.lang-sm.lang-lbl-en,.lang-sm.lang-lbl-full{padding-left:24px}.lang-lg.lang-lbl,.lang-lg.lang-lbl-en,.lang-lg.lang-lbl-full{padding-left:32px}.lang-lg.lang-lbl-en:before,.lang-lg.lang-lbl-full:before,.lang-lg.lang-lbl:before,.lang-sm.lang-lbl-en:before,.lang-sm.lang-lbl-full:before,.lang-sm.lang-lbl:before,.lang-xs.lang-lbl-en:before,.lang-xs.lang-lbl-full:before,.lang-xs.lang-lbl:before{content:''}.lang-lg,.lang-lg:after{top:0;position:relative}.lang-sm{top:1px}.lang-sm:after{top:-1px}.lang-xs{top:4px}.lang-xs:after{top:-4px}.lead>.lang-lg{top:2px}.lead>.lang-lg:after{top:-2px}.lead>.lang-sm{top:6px}.lead>.lang-sm:after{top:-6px}.lead>.lang-xs{top:8px}.lead>.lang-xs:after{top:-8px}small>.lang-sm{top:-1px}small>.lang-sm:after{top:1px}small>.lang-xs{top:2px}small>.lang-xs:after{top:-2px}h1>.lang-lg{top:9px}h1>.lang-lg:after{top:-9px}h1>.lang-sm{top:12px}h1>.lang-sm:after{top:-12px}h1>.lang-xs{top:14px}h1>.lang-xs:after{top:-14px}h2>.lang-lg{top:5px}h2>.lang-lg:after{top:-5px}h2>.lang-sm{top:8px}h2>.lang-sm:after{top:-8px}h2>.lang-xs{top:10px}h2>.lang-xs:after{top:-10px}h3>.lang-lg{top:1px}h3>.lang-lg:after{top:-1px}h3>.lang-sm{top:5px}h3>.lang-sm:after{top:-5px}h3>.lang-xs{top:8px}h3>.lang-xs:after{top:-8px}h4>.lang-lg{top:-1px}h4>.lang-lg:after,h4>.lang-sm{top:1px}h4>.lang-sm:after{top:-1px}h4>.lang-xs{top:4px}h4>.lang-xs:after{top:-4px}h5>.lang-sm,h5>.lang-sm:after{top:0}h5>.lang-xs{top:2px}h5>.lang-xs:after{top:-2px}h6>.lang-sm,h6>.lang-sm:after{top:0}h6>.lang-xs{top:1px}h6>.lang-xs:after{top:-1px}.btn>.lang-sm{top:2px}.btn>.lang-sm:after{top:-2px}.btn>.lang-xs{top:4px}.btn>.lang-xs:after{top:-4px}.btn.btn-xs>.lang-sm,.btn.btn-xs>.lang-sm:after{top:0}.btn.btn-xs>.lang-xs{top:3px}.btn.btn-xs>.lang-xs:after{top:-3px}.btn.btn-sm>.lang-sm,.btn.btn-sm>.lang-sm:after{top:0}.btn.btn-sm>.lang-xs{top:3px}.btn.btn-sm>.lang-xs:after{top:-3px}.btn.btn-lg>.lang-lg{top:1px}.btn.btn-lg>.lang-lg:after{top:-1px}.btn.btn-lg>.lang-sm{top:3px}.btn.btn-lg>.lang-sm:after{top:-3px}.btn.btn-lg>.lang-xs{top:6px}.btn.btn-lg>.lang-xs:after{top:-6px} \ No newline at end of file diff --git a/data/web/inc/languages.png b/data/web/inc/languages.png deleted file mode 100644 index f5f1a2f0..00000000 Binary files a/data/web/inc/languages.png and /dev/null differ diff --git a/data/web/inc/lib/Yubico.php b/data/web/inc/lib/Yubico.php index 68a3087b..d8aa41c3 100644 --- a/data/web/inc/lib/Yubico.php +++ b/data/web/inc/lib/Yubico.php @@ -6,9 +6,9 @@ * @package Auth_Yubico * @author Simon Josefsson , Olov Danielson * @copyright 2007-2015 Yubico AB - * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @license https://opensource.org/licenses/bsd-license.php New BSD License * @version 2.0 - * @link http://www.yubico.com/ + * @link https://www.yubico.com/ */ require_once 'PEAR.php'; @@ -80,12 +80,6 @@ class Auth_Yubico */ var $_response; - /** - * Flag whether to use https or not. - * @var boolean - */ - var $_https; - /** * Flag whether to verify HTTPS server certificates or not. * @var boolean @@ -98,24 +92,18 @@ class Auth_Yubico * Sets up the object * @param string $id The client identity * @param string $key The client MAC key (optional) - * @param boolean $https Flag whether to use https (optional) + * @param boolean $https noop * @param boolean $httpsverify Flag whether to use verify HTTPS * server certificates (optional, * default true) * @access public */ - function __construct($id, $key = '', $https = 0, $httpsverify = 1) + public function __construct($id, $key = '', $https = 0, $httpsverify = 1) { $this->_id = $id; $this->_key = base64_decode($key); - $this->_https = $https; $this->_httpsverify = $httpsverify; } - - function Auth_Yubico($id, $key = '', $https = 0, $httpsverify = 1) - { - self::__construct(); - } /** * Specify to use a different URL part for verification. @@ -129,22 +117,6 @@ class Auth_Yubico $this->_url = $url; } - /** - * Get URL part to use for validation. - * - * @return string Server URL part - * @access public - */ - function getURLpart() - { - if ($this->_url) { - return $this->_url; - } else { - return "api.yubico.com/wsapi/verify"; - } - } - - /** * Get next URL part from list to use for validation. * @@ -154,12 +126,12 @@ class Auth_Yubico function getNextURLpart() { if ($this->_url_list) $url_list=$this->_url_list; - else $url_list=array('api.yubico.com/wsapi/2.0/verify', - 'api2.yubico.com/wsapi/2.0/verify', - 'api3.yubico.com/wsapi/2.0/verify', - 'api4.yubico.com/wsapi/2.0/verify', - 'api5.yubico.com/wsapi/2.0/verify'); - + else $url_list=array('https://api.yubico.com/wsapi/2.0/verify', + 'https://api2.yubico.com/wsapi/2.0/verify', + 'https://api3.yubico.com/wsapi/2.0/verify', + 'https://api4.yubico.com/wsapi/2.0/verify', + 'https://api5.yubico.com/wsapi/2.0/verify'); + if ($this->_url_index>=count($url_list)) return false; else return $url_list[$this->_url_index++]; } @@ -318,13 +290,7 @@ class Auth_Yubico $ch = array(); while($URLpart=$this->getNextURLpart()) { - /* Support https. */ - if ($this->_https) { - $query = "https://"; - } else { - $query = "http://"; - } - $query .= $URLpart . "?" . $parameters; + $query = $URLpart . "?" . $parameters; if ($this->_lastquery) { $this->_lastquery .= " "; } $this->_lastquery .= $query; @@ -392,7 +358,7 @@ class Auth_Yubico /* Case 2. Verify signature first */ $rows = explode("\r\n", trim($str)); $response=array(); - while (list($key, $val) = each($rows)) { + foreach ($rows as $key => $val) { /* = is also used in BASE64 encoding so we only replace the first = by # which is not used in BASE64 */ $val = preg_replace('/=/', '#', $val, 1); $row = explode("#", $val); diff --git a/data/web/inc/lib/composer.json b/data/web/inc/lib/composer.json index 6107bac7..e072a0dd 100644 --- a/data/web/inc/lib/composer.json +++ b/data/web/inc/lib/composer.json @@ -4,6 +4,8 @@ "yubico/u2flib-server": "^1.0", "phpmailer/phpmailer": "^5.2", "php-mime-mail-parser/php-mime-mail-parser": "^2.9", - "soundasleep/html2text": "^0.5.0" + "soundasleep/html2text": "^0.5.0", + "ddeboer/imap": "^1.5", + "matthiasmullie/minify": "^1.3" } } diff --git a/data/web/inc/lib/composer.lock b/data/web/inc/lib/composer.lock index 841f2e93..b2d6defe 100644 --- a/data/web/inc/lib/composer.lock +++ b/data/web/inc/lib/composer.lock @@ -4,8 +4,221 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3edeec2e3fa875d4f9d5e7f22a8179be", + "content-hash": "e72f119b7f62fea0aa6123109abb9a35", "packages": [ + { + "name": "ddeboer/imap", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/ddeboer/imap.git", + "reference": "4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ddeboer/imap/zipball/4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede", + "reference": "4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-imap": "*", + "ext-mbstring": "*", + "php": "^7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.13", + "phpstan/phpstan": "^0.9.1", + "phpstan/phpstan-phpunit": "^0.9.3", + "phpunit/phpunit": "^7.4", + "zendframework/zend-mail": "^2.10" + }, + "type": "library", + "autoload": { + "psr-4": { + "Ddeboer\\Imap\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + }, + { + "name": "Community contributors", + "homepage": "https://github.com/ddeboer/imap/graphs/contributors" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com" + } + ], + "description": "Object-oriented IMAP for PHP", + "keywords": [ + "email", + "imap", + "mail" + ], + "time": "2018-12-04T13:35:19+00:00" + }, + { + "name": "matthiasmullie/minify", + "version": "1.3.61", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/minify.git", + "reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751", + "reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "matthiasmullie/path-converter": "~1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.0", + "matthiasmullie/scrapbook": "~1.0", + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "psr/cache-implementation": "Cache implementation to use with Minify::cache" + }, + "bin": [ + "bin/minifycss", + "bin/minifyjs" + ], + "type": "library", + "autoload": { + "psr-4": { + "MatthiasMullie\\Minify\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "minify@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.", + "homepage": "http://www.minifier.org", + "keywords": [ + "JS", + "css", + "javascript", + "minifier", + "minify" + ], + "time": "2018-11-26T23:10:39+00:00" + }, + { + "name": "matthiasmullie/path-converter", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/path-converter.git", + "reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/5e4b121c8b9f97c80835c1d878b0812ba1d607c9", + "reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "MatthiasMullie\\PathConverter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "pathconverter@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "Relative path converter", + "homepage": "http://github.com/matthiasmullie/path-converter", + "keywords": [ + "converter", + "path", + "paths", + "relative" + ], + "time": "2018-10-25T15:19:41+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, { "name": "php-mime-mail-parser/php-mime-mail-parser", "version": "2.11.1", @@ -88,16 +301,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v5.2.26", + "version": "v5.2.27", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "70362997bda4376378be7d92d81e2200550923f7" + "reference": "dde1db116511aa4956389d75546c5be4c2beb2a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/70362997bda4376378be7d92d81e2200550923f7", - "reference": "70362997bda4376378be7d92d81e2200550923f7", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/dde1db116511aa4956389d75546c5be4c2beb2a6", + "reference": "dde1db116511aa4956389d75546c5be4c2beb2a6", "shasum": "" }, "require": { @@ -161,7 +374,7 @@ } ], "description": "PHPMailer is a full-featured email creation and transfer class for PHP", - "time": "2017-11-04T09:26:05+00:00" + "time": "2018-11-15T22:32:31+00:00" }, { "name": "robthree/twofactorauth", @@ -266,24 +479,26 @@ }, { "name": "yubico/u2flib-server", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/Yubico/php-u2flib-server.git", - "reference": "dc318c80b59e62921c210f31b014def26ceebbab" + "reference": "55d813acf68212ad2cadecde07551600d6971939" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/dc318c80b59e62921c210f31b014def26ceebbab", - "reference": "dc318c80b59e62921c210f31b014def26ceebbab", + "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/55d813acf68212ad2cadecde07551600d6971939", + "reference": "55d813acf68212ad2cadecde07551600d6971939", "shasum": "" }, "require": { "ext-openssl": "*", + "paragonie/random_compat": ">= 1", "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "~5.7" + "phpunit/phpunit": "~5.7", + "vimeo/psalm": "^0|^1|^2" }, "type": "library", "autoload": { @@ -297,7 +512,7 @@ ], "description": "Library for U2F implementation", "homepage": "https://developers.yubico.com/php-u2flib-server", - "time": "2017-05-09T07:33:58+00:00" + "time": "2018-09-07T08:16:44+00:00" } ], "packages-dev": [], diff --git a/data/web/inc/lib/vendor/bin/minifycss b/data/web/inc/lib/vendor/bin/minifycss new file mode 120000 index 00000000..04f60a4b --- /dev/null +++ b/data/web/inc/lib/vendor/bin/minifycss @@ -0,0 +1 @@ +../matthiasmullie/minify/bin/minifycss \ No newline at end of file diff --git a/data/web/inc/lib/vendor/bin/minifyjs b/data/web/inc/lib/vendor/bin/minifyjs new file mode 120000 index 00000000..61124467 --- /dev/null +++ b/data/web/inc/lib/vendor/bin/minifyjs @@ -0,0 +1 @@ +../matthiasmullie/minify/bin/minifyjs \ No newline at end of file diff --git a/data/web/inc/lib/vendor/composer/ClassLoader.php b/data/web/inc/lib/vendor/composer/ClassLoader.php index dc02dfb1..fce8549f 100644 --- a/data/web/inc/lib/vendor/composer/ClassLoader.php +++ b/data/web/inc/lib/vendor/composer/ClassLoader.php @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -377,7 +377,7 @@ class ClassLoader $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); - $search = $subPath.'\\'; + $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { diff --git a/data/web/inc/lib/vendor/composer/autoload_psr4.php b/data/web/inc/lib/vendor/composer/autoload_psr4.php index cfa01d56..e7b93543 100644 --- a/data/web/inc/lib/vendor/composer/autoload_psr4.php +++ b/data/web/inc/lib/vendor/composer/autoload_psr4.php @@ -8,5 +8,8 @@ $baseDir = dirname($vendorDir); return array( 'RobThree\\Auth\\' => array($vendorDir . '/robthree/twofactorauth/lib'), 'PhpMimeMailParser\\' => array($vendorDir . '/php-mime-mail-parser/php-mime-mail-parser/src'), + 'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'), + 'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'), 'Html2Text\\' => array($vendorDir . '/soundasleep/html2text/src'), + 'Ddeboer\\Imap\\' => array($vendorDir . '/ddeboer/imap/src'), ); diff --git a/data/web/inc/lib/vendor/composer/autoload_static.php b/data/web/inc/lib/vendor/composer/autoload_static.php index 9d9f1a85..7bcc3ed6 100644 --- a/data/web/inc/lib/vendor/composer/autoload_static.php +++ b/data/web/inc/lib/vendor/composer/autoload_static.php @@ -15,10 +15,19 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b array ( 'PhpMimeMailParser\\' => 18, ), + 'M' => + array ( + 'MatthiasMullie\\PathConverter\\' => 29, + 'MatthiasMullie\\Minify\\' => 22, + ), 'H' => array ( 'Html2Text\\' => 10, ), + 'D' => + array ( + 'Ddeboer\\Imap\\' => 13, + ), ); public static $prefixDirsPsr4 = array ( @@ -30,10 +39,22 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b array ( 0 => __DIR__ . '/..' . '/php-mime-mail-parser/php-mime-mail-parser/src', ), + 'MatthiasMullie\\PathConverter\\' => + array ( + 0 => __DIR__ . '/..' . '/matthiasmullie/path-converter/src', + ), + 'MatthiasMullie\\Minify\\' => + array ( + 0 => __DIR__ . '/..' . '/matthiasmullie/minify/src', + ), 'Html2Text\\' => array ( 0 => __DIR__ . '/..' . '/soundasleep/html2text/src', ), + 'Ddeboer\\Imap\\' => + array ( + 0 => __DIR__ . '/..' . '/ddeboer/imap/src', + ), ); public static $classMap = array ( diff --git a/data/web/inc/lib/vendor/composer/installed.json b/data/web/inc/lib/vendor/composer/installed.json index bd1deb85..42f210d0 100644 --- a/data/web/inc/lib/vendor/composer/installed.json +++ b/data/web/inc/lib/vendor/composer/installed.json @@ -1,4 +1,225 @@ [ + { + "name": "ddeboer/imap", + "version": "1.6.0", + "version_normalized": "1.6.0.0", + "source": { + "type": "git", + "url": "https://github.com/ddeboer/imap.git", + "reference": "4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ddeboer/imap/zipball/4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede", + "reference": "4d3b31c7cc5eb3cf3a8a0369fabd0d6e3f39cede", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-imap": "*", + "ext-mbstring": "*", + "php": "^7.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.13", + "phpstan/phpstan": "^0.9.1", + "phpstan/phpstan-phpunit": "^0.9.3", + "phpunit/phpunit": "^7.4", + "zendframework/zend-mail": "^2.10" + }, + "time": "2018-12-04T13:35:19+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Ddeboer\\Imap\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + }, + { + "name": "Community contributors", + "homepage": "https://github.com/ddeboer/imap/graphs/contributors" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com" + } + ], + "description": "Object-oriented IMAP for PHP", + "keywords": [ + "email", + "imap", + "mail" + ] + }, + { + "name": "matthiasmullie/minify", + "version": "1.3.61", + "version_normalized": "1.3.61.0", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/minify.git", + "reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751", + "reference": "d5acb8ce5b6acb7d11bafe97cecc533f6e4fd751", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "matthiasmullie/path-converter": "~1.1", + "php": ">=5.3.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.0", + "matthiasmullie/scrapbook": "~1.0", + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "psr/cache-implementation": "Cache implementation to use with Minify::cache" + }, + "time": "2018-11-26T23:10:39+00:00", + "bin": [ + "bin/minifycss", + "bin/minifyjs" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MatthiasMullie\\Minify\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "minify@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.", + "homepage": "http://www.minifier.org", + "keywords": [ + "JS", + "css", + "javascript", + "minifier", + "minify" + ] + }, + { + "name": "matthiasmullie/path-converter", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/matthiasmullie/path-converter.git", + "reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/5e4b121c8b9f97c80835c1d878b0812ba1d607c9", + "reference": "5e4b121c8b9f97c80835c1d878b0812ba1d607c9", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "time": "2018-10-25T15:19:41+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "MatthiasMullie\\PathConverter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthias Mullie", + "email": "pathconverter@mullie.eu", + "homepage": "http://www.mullie.eu", + "role": "Developer" + } + ], + "description": "Relative path converter", + "homepage": "http://github.com/matthiasmullie/path-converter", + "keywords": [ + "converter", + "path", + "paths", + "relative" + ] + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "version_normalized": "9.99.99.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "time": "2018-07-02T15:55:56+00:00", + "type": "library", + "installation-source": "dist", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ] + }, { "name": "php-mime-mail-parser/php-mime-mail-parser", "version": "2.11.1", @@ -83,17 +304,17 @@ }, { "name": "phpmailer/phpmailer", - "version": "v5.2.26", - "version_normalized": "5.2.26.0", + "version": "v5.2.27", + "version_normalized": "5.2.27.0", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "70362997bda4376378be7d92d81e2200550923f7" + "reference": "dde1db116511aa4956389d75546c5be4c2beb2a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/70362997bda4376378be7d92d81e2200550923f7", - "reference": "70362997bda4376378be7d92d81e2200550923f7", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/dde1db116511aa4956389d75546c5be4c2beb2a6", + "reference": "dde1db116511aa4956389d75546c5be4c2beb2a6", "shasum": "" }, "require": { @@ -123,7 +344,7 @@ "suggest": { "league/oauth2-google": "Needed for Google XOAUTH2 authentication" }, - "time": "2017-11-04T09:26:05+00:00", + "time": "2018-11-15T22:32:31+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -267,27 +488,29 @@ }, { "name": "yubico/u2flib-server", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "version": "1.0.2", + "version_normalized": "1.0.2.0", "source": { "type": "git", "url": "https://github.com/Yubico/php-u2flib-server.git", - "reference": "dc318c80b59e62921c210f31b014def26ceebbab" + "reference": "55d813acf68212ad2cadecde07551600d6971939" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/dc318c80b59e62921c210f31b014def26ceebbab", - "reference": "dc318c80b59e62921c210f31b014def26ceebbab", + "url": "https://api.github.com/repos/Yubico/php-u2flib-server/zipball/55d813acf68212ad2cadecde07551600d6971939", + "reference": "55d813acf68212ad2cadecde07551600d6971939", "shasum": "" }, "require": { "ext-openssl": "*", + "paragonie/random_compat": ">= 1", "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "~5.7" + "phpunit/phpunit": "~5.7", + "vimeo/psalm": "^0|^1|^2" }, - "time": "2017-05-09T07:33:58+00:00", + "time": "2018-09-07T08:16:44+00:00", "type": "library", "installation-source": "dist", "autoload": { diff --git a/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md b/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md new file mode 100644 index 00000000..4635313f --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md @@ -0,0 +1,510 @@ +# Change Log + +## [1.6.0](https://github.com/ddeboer/imap/tree/1.6.0) (2018-12-04) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.5...1.6.0) + +**Implemented enhancements:** + +- Require PHP ^7.1 [\#257](https://github.com/ddeboer/imap/issues/257) +- Require PHP ^7.1 [\#383](https://github.com/ddeboer/imap/pull/383) ([Slamdunk](https://github.com/Slamdunk)) +- Add ability to pass options and retries to imap\_open [\#382](https://github.com/ddeboer/imap/pull/382) ([Slamdunk](https://github.com/Slamdunk)) +- Docker setup for running tests [\#374](https://github.com/ddeboer/imap/pull/374) ([LeadTechVisas](https://github.com/LeadTechVisas)) +- Get messages by UID sequence [\#373](https://github.com/ddeboer/imap/pull/373) ([LeadTechVisas](https://github.com/LeadTechVisas)) + +**Fixed bugs:** + +- Undeliverable mail: attachment parsing error [\#334](https://github.com/ddeboer/imap/issues/334) +- imap\_getmailboxes returns false; [\#134](https://github.com/ddeboer/imap/issues/134) +- Fix mailbox name as only numbers [\#381](https://github.com/ddeboer/imap/pull/381) ([Slamdunk](https://github.com/Slamdunk)) +- Gracefully handle possible non-array return value of imap\_getmailboxes [\#372](https://github.com/ddeboer/imap/pull/372) ([Slamdunk](https://github.com/Slamdunk)) + +**Closed issues:** + +- \[AUTHENTICATIONFAILED\] Authentication failed - Too many login failures [\#368](https://github.com/ddeboer/imap/issues/368) +- last folder in list [\#353](https://github.com/ddeboer/imap/issues/353) +- Caching IMAP server connections [\#88](https://github.com/ddeboer/imap/issues/88) + +## [1.5.5](https://github.com/ddeboer/imap/tree/1.5.5) (2018-08-21) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.4...1.5.5) + +**Fixed bugs:** + +- Plain text attachments are not identified as Attachment parts [\#341](https://github.com/ddeboer/imap/issues/341) +- Handle plain/text attachments without Content-Type header [\#367](https://github.com/ddeboer/imap/pull/367) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.5.4](https://github.com/ddeboer/imap/tree/1.5.4) (2018-08-19) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.3...1.5.4) + +**Fixed bugs:** + +- Very long filename, result of getFilename\(\) = NULL? [\#365](https://github.com/ddeboer/imap/issues/365) +- Support RFC2231 attachment filenames [\#366](https://github.com/ddeboer/imap/pull/366) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.5.3](https://github.com/ddeboer/imap/tree/1.5.3) (2018-07-20) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.2...1.5.3) + +**Fixed bugs:** + +- Dates: handle UT timezone [\#361](https://github.com/ddeboer/imap/pull/361) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.5.2](https://github.com/ddeboer/imap/tree/1.5.2) (2018-07-10) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.1...1.5.2) + +**Fixed bugs:** + +- Fails to load Message Headers [\#358](https://github.com/ddeboer/imap/issues/358) +- Handle invalid headers [\#359](https://github.com/ddeboer/imap/pull/359) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.5.1](https://github.com/ddeboer/imap/tree/1.5.1) (2018-05-04) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.0...1.5.1) + +**Fixed bugs:** + +- getContent\(\) method returns wrong content part [\#342](https://github.com/ddeboer/imap/issues/342) +- Fix handle of attachment messages with attachments [\#343](https://github.com/ddeboer/imap/pull/343) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.5.0](https://github.com/ddeboer/imap/tree/1.5.0) (2018-03-26) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.1...1.5.0) + +**Implemented enhancements:** + +- ImapResource: cache last opened mailbox [\#328](https://github.com/ddeboer/imap/pull/328) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.4.1](https://github.com/ddeboer/imap/tree/1.4.1) (2018-03-22) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.0...1.4.1) + +**Fixed bugs:** + +- Return value of Ddeboer\\Imap\\Message\\AbstractPart::getDecodedContent\(\) must be of the type string, boolean returned [\#284](https://github.com/ddeboer/imap/issues/284) +- base64\_decode may return false in PHP \< 7.1 [\#324](https://github.com/ddeboer/imap/pull/324) ([Slamdunk](https://github.com/Slamdunk)) + +**Merged pull requests:** + +- Add entry in README about Mailbox::addMessage [\#325](https://github.com/ddeboer/imap/pull/325) ([soywod](https://github.com/soywod)) + +## [1.4.0](https://github.com/ddeboer/imap/tree/1.4.0) (2018-03-19) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.1...1.4.0) + +**Implemented enhancements:** + +- Lazy load Message [\#320](https://github.com/ddeboer/imap/pull/320) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- Invalid argument supplied for foreach\(\) in Parameters.php line 52 [\#317](https://github.com/ddeboer/imap/issues/317) +- Message "11964" does not exist: imap\_fetchstructure\(\): Bad message number [\#310](https://github.com/ddeboer/imap/issues/310) +- imap\_mime\_header\_decode may return false [\#322](https://github.com/ddeboer/imap/pull/322) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.3.1](https://github.com/ddeboer/imap/tree/1.3.1) (2018-03-09) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.0...1.3.1) + +**Implemented enhancements:** + +- Allow empty port [\#312](https://github.com/ddeboer/imap/pull/312) ([Slamdunk](https://github.com/Slamdunk)) + +**Closed issues:** + +- getServerString\(\) with no port [\#311](https://github.com/ddeboer/imap/issues/311) + +## [1.3.0](https://github.com/ddeboer/imap/tree/1.3.0) (2018-02-28) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.3...1.3.0) + +**Implemented enhancements:** + +- Implement bulk-move [\#306](https://github.com/ddeboer/imap/pull/306) ([particleflux](https://github.com/particleflux)) + +**Closed issues:** + +- feature: Bulk move [\#305](https://github.com/ddeboer/imap/issues/305) + +**Merged pull requests:** + +- README.md: add `Unknown search criterion: OR` note [\#304](https://github.com/ddeboer/imap/pull/304) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.2.3](https://github.com/ddeboer/imap/tree/1.2.3) (2018-02-09) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.2...1.2.3) + +**Fixed bugs:** + +- $part-\>type can be 9 [\#301](https://github.com/ddeboer/imap/issues/301) +- AbstractPart::isAttachment\(\) handle unknown part type [\#302](https://github.com/ddeboer/imap/pull/302) ([Slamdunk](https://github.com/Slamdunk)) + +**Merged pull requests:** + +- README.md: code-coverage has higher priority than Scrutinizer [\#300](https://github.com/ddeboer/imap/pull/300) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.2.2](https://github.com/ddeboer/imap/tree/1.2.2) (2018-02-05) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.1...1.2.2) + +**Implemented enhancements:** + +- Allow PHPUnit ^7.0 [\#296](https://github.com/ddeboer/imap/pull/296) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- Attachment-\>getFilename return null [\#297](https://github.com/ddeboer/imap/issues/297) +- Don't handle multiplart as an attachment [\#298](https://github.com/ddeboer/imap/pull/298) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.2.1](https://github.com/ddeboer/imap/tree/1.2.1) (2018-01-29) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.0...1.2.1) + +**Implemented enhancements:** + +- Introduce strict comparison [\#289](https://github.com/ddeboer/imap/pull/289) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- Invalid Date header found: "Thur, 04 Jan 2018 06:44:23 +0400" [\#293](https://github.com/ddeboer/imap/issues/293) +- MessageIterator::current\(\) fails when there are no messages [\#288](https://github.com/ddeboer/imap/issues/288) +- Remove weekday while parsing date header [\#294](https://github.com/ddeboer/imap/pull/294) ([Slamdunk](https://github.com/Slamdunk)) +- MessageIterator: forbid raw calls [\#290](https://github.com/ddeboer/imap/pull/290) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.2.0](https://github.com/ddeboer/imap/tree/1.2.0) (2018-01-15) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.2...1.2.0) + +**Implemented enhancements:** + +- Make imap\_append\(\) optional arguments reachable [\#280](https://github.com/ddeboer/imap/pull/280) ([Slamdunk](https://github.com/Slamdunk)) +- PHPStan: introduce static analysis [\#276](https://github.com/ddeboer/imap/pull/276) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- getAttachments\(\) problem when mixin inline and attachment [\#281](https://github.com/ddeboer/imap/issues/281) +- UnexpectedEncodingException: Cannot decode "5" [\#278](https://github.com/ddeboer/imap/issues/278) +- Handle correctly multiple nested attachments [\#283](https://github.com/ddeboer/imap/pull/283) ([Slamdunk](https://github.com/Slamdunk)) +- Manageable UnexpectedEncodingException [\#282](https://github.com/ddeboer/imap/pull/282) ([Slamdunk](https://github.com/Slamdunk)) + +**Closed issues:** + +- Appending mail with options [\#279](https://github.com/ddeboer/imap/issues/279) + +## [1.1.2](https://github.com/ddeboer/imap/tree/1.1.2) (2017-12-12) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.1...1.1.2) + +**Fixed bugs:** + +- Unsupported charset "134": mb\_convert\_encoding\(\): Illegal character encoding specified [\#270](https://github.com/ddeboer/imap/issues/270) +- Support Microsoft charset values [\#271](https://github.com/ddeboer/imap/pull/271) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.1.1](https://github.com/ddeboer/imap/tree/1.1.1) (2017-11-10) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.0...1.1.1) + +**Implemented enhancements:** + +- Transcoder: expand charset aliases list [\#267](https://github.com/ddeboer/imap/pull/267) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- Charset aliases: fix to lowercase search [\#266](https://github.com/ddeboer/imap/pull/266) ([Slamdunk](https://github.com/Slamdunk)) + +**Merged pull requests:** + +- README.md: add timeout note [\#263](https://github.com/ddeboer/imap/pull/263) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.1.0](https://github.com/ddeboer/imap/tree/1.1.0) (2017-11-06) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.8...1.1.0) + +**Implemented enhancements:** + +- Headers: no catchable exception [\#246](https://github.com/ddeboer/imap/issues/246) +- imap\_thread [\#113](https://github.com/ddeboer/imap/issues/113) +- Deprecate MessageInterface::maskAsSeen\(\) in favour of MessageInterface::markAsSeen\(\) [\#255](https://github.com/ddeboer/imap/pull/255) ([Slamdunk](https://github.com/Slamdunk)) +- Lazy load structured Headers [\#250](https://github.com/ddeboer/imap/pull/250) ([Slamdunk](https://github.com/Slamdunk)) +- Implement imap\_thread [\#249](https://github.com/ddeboer/imap/pull/249) ([Slamdunk](https://github.com/Slamdunk)) +- Require ext-iconv [\#248](https://github.com/ddeboer/imap/pull/248) ([Slamdunk](https://github.com/Slamdunk)) +- Message Part: expose $partNumber [\#244](https://github.com/ddeboer/imap/pull/244) ([wujku](https://github.com/wujku)) +- Add Mockability helpers and documentation [\#236](https://github.com/ddeboer/imap/pull/236) ([Slamdunk](https://github.com/Slamdunk)) +- Add missing interface change for \#225 [\#233](https://github.com/ddeboer/imap/pull/233) ([Slamdunk](https://github.com/Slamdunk)) +- Connection: check if the connection is still active with `imap\_ping` [\#232](https://github.com/ddeboer/imap/pull/232) ([wujku](https://github.com/wujku)) +- Message: add `References` and `In-Reply-To` headers shortcuts [\#230](https://github.com/ddeboer/imap/pull/230) ([wujku](https://github.com/wujku)) +- Added bulk set / clear flags functionality for mailbox messages [\#225](https://github.com/ddeboer/imap/pull/225) ([wujku](https://github.com/wujku)) + +**Merged pull requests:** + +- make docs more obvious [\#252](https://github.com/ddeboer/imap/pull/252) ([lgg](https://github.com/lgg)) +- README.md: add Table of Contents with Travis checker [\#234](https://github.com/ddeboer/imap/pull/234) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.8](https://github.com/ddeboer/imap/tree/1.0.8) (2017-10-27) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.7...1.0.8) + +**Fixed bugs:** + +- \[TypeError\] Return value of Ddeboer\Imap\Message\AbstractMessage::getId\(\) must be of the type string, null returned [\#253](https://github.com/ddeboer/imap/issues/253) +- BasicMessageInterface::getId\(\) can be null [\#254](https://github.com/ddeboer/imap/pull/254) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.7](https://github.com/ddeboer/imap/tree/1.0.7) (2017-10-16) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.6...1.0.7) + +**Fixed bugs:** + +- Problem with a IMAP resource stream [\#245](https://github.com/ddeboer/imap/issues/245) +- IMAP resource must be checked at every call for mailbox context [\#247](https://github.com/ddeboer/imap/pull/247) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.6](https://github.com/ddeboer/imap/tree/1.0.6) (2017-10-12) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.5...1.0.6) + +**Fixed bugs:** + +- \[TypeError\] Return value of AbstractMessage::getFrom\(\) must be an instance of EmailAddress, null returned [\#241](https://github.com/ddeboer/imap/issues/241) +- Message: Date header can be absent [\#243](https://github.com/ddeboer/imap/pull/243) ([Slamdunk](https://github.com/Slamdunk)) +- Message: From header can be absent [\#242](https://github.com/ddeboer/imap/pull/242) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.5](https://github.com/ddeboer/imap/tree/1.0.5) (2017-10-12) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.4...1.0.5) + +**Fixed bugs:** + +- Use set\_error\_handler with late exception [\#240](https://github.com/ddeboer/imap/pull/240) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.4](https://github.com/ddeboer/imap/tree/1.0.4) (2017-10-11) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.3...1.0.4) + +**Implemented enhancements:** + +- Avoid \(set|restor\)\_error\_handler [\#239](https://github.com/ddeboer/imap/pull/239) ([Slamdunk](https://github.com/Slamdunk)) + +**Fixed bugs:** + +- Current Transcoder class does not support all charsets. [\#237](https://github.com/ddeboer/imap/issues/237) +- Relay also iconv during decoding [\#238](https://github.com/ddeboer/imap/pull/238) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.3](https://github.com/ddeboer/imap/tree/1.0.3) (2017-10-11) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.2...1.0.3) + +**Fixed bugs:** + +- Attachment::getFilename\(\) may be null on inline-att, widen return type [\#235](https://github.com/ddeboer/imap/pull/235) ([wujku](https://github.com/wujku)) + +## [1.0.2](https://github.com/ddeboer/imap/tree/1.0.2) (2017-10-06) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.1...1.0.2) + +**Fixed bugs:** + +- Issue with saving XML attachments [\#228](https://github.com/ddeboer/imap/issues/228) +- Do not charset-decode attachments [\#231](https://github.com/ddeboer/imap/pull/231) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.1](https://github.com/ddeboer/imap/tree/1.0.1) (2017-10-05) +[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.0...1.0.1) + +**Fixed bugs:** + +- Error with attachment charset [\#226](https://github.com/ddeboer/imap/issues/226) +- If charset is not specified defaults to "us-ascii" [\#227](https://github.com/ddeboer/imap/pull/227) ([Slamdunk](https://github.com/Slamdunk)) + +## [1.0.0](https://github.com/ddeboer/imap/tree/1.0.0) (2017-10-04) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.2...1.0.0) + +**Implemented enhancements:** + +- Need getAll for headers [\#200](https://github.com/ddeboer/imap/issues/200) +- Tests: implement @covers to avoid false positive on code-coverage [\#188](https://github.com/ddeboer/imap/issues/188) +- Remove commented code [\#174](https://github.com/ddeboer/imap/issues/174) +- Regex in SearchExpressions [\#157](https://github.com/ddeboer/imap/issues/157) +- How do I get unread messages count? [\#98](https://github.com/ddeboer/imap/issues/98) +- Add mocking ability through Interfaces [\#221](https://github.com/ddeboer/imap/pull/221) ([Slamdunk](https://github.com/Slamdunk)) +- Wrap imap resource to periodically check its status [\#220](https://github.com/ddeboer/imap/pull/220) ([Slamdunk](https://github.com/Slamdunk)) +- Add more coding-standard rules [\#218](https://github.com/ddeboer/imap/pull/218) ([Slamdunk](https://github.com/Slamdunk)) +- Always keep unseen: remove keepUnseen, add markAsSeen [\#217](https://github.com/ddeboer/imap/pull/217) ([Slamdunk](https://github.com/Slamdunk)) +- Embedded messages: refactor \#106 [\#216](https://github.com/ddeboer/imap/pull/216) ([Slamdunk](https://github.com/Slamdunk)) +- Headers now extends \ArrayIterator [\#215](https://github.com/ddeboer/imap/pull/215) ([Slamdunk](https://github.com/Slamdunk)) +- Implement imap\_mail\_copy [\#214](https://github.com/ddeboer/imap/pull/214) ([Slamdunk](https://github.com/Slamdunk)) +- Imap sort [\#213](https://github.com/ddeboer/imap/pull/213) ([Slamdunk](https://github.com/Slamdunk)) +- Increased code-coverage [\#211](https://github.com/ddeboer/imap/pull/211) ([Slamdunk](https://github.com/Slamdunk)) +- Update to PHPUnit ^6.2 [\#209](https://github.com/ddeboer/imap/pull/209) ([Slamdunk](https://github.com/Slamdunk)) +- Use specific exceptions to ease user catches [\#208](https://github.com/ddeboer/imap/pull/208) ([Slamdunk](https://github.com/Slamdunk)) +- Wrap Exception on invalid Date header [\#205](https://github.com/ddeboer/imap/pull/205) ([Slamdunk](https://github.com/Slamdunk)) +- Add tests for \#144 set flags functionalities [\#203](https://github.com/ddeboer/imap/pull/203) ([Slamdunk](https://github.com/Slamdunk)) +- Add imap\_fetchheader\(\) functionality to get raw headers [\#202](https://github.com/ddeboer/imap/pull/202) ([Slamdunk](https://github.com/Slamdunk)) +- Parse all email type headers [\#199](https://github.com/ddeboer/imap/pull/199) ([Slamdunk](https://github.com/Slamdunk)) +- Test search conditions [\#198](https://github.com/ddeboer/imap/pull/198) ([Slamdunk](https://github.com/Slamdunk)) +- Mailbox: get status [\#192](https://github.com/ddeboer/imap/pull/192) ([Slamdunk](https://github.com/Slamdunk)) +- SearchExpression is a Search\ConditionInterface [\#191](https://github.com/ddeboer/imap/pull/191) ([Slamdunk](https://github.com/Slamdunk)) +- SearchCondition: \_\_toString\(\) -\> toString\(\) [\#187](https://github.com/ddeboer/imap/pull/187) ([Slamdunk](https://github.com/Slamdunk)) +- Retain imap\_getmailboxes\(\) results [\#184](https://github.com/ddeboer/imap/pull/184) ([Slamdunk](https://github.com/Slamdunk)) +- Add type hints and return types [\#183](https://github.com/ddeboer/imap/pull/183) ([Slamdunk](https://github.com/Slamdunk)) +- Exception: increase verbosity with imap\_alerts\(\) and imap\_errors\(\) [\#182](https://github.com/ddeboer/imap/pull/182) ([Slamdunk](https://github.com/Slamdunk)) +- Add coding-standards [\#181](https://github.com/ddeboer/imap/pull/181) ([Slamdunk](https://github.com/Slamdunk)) +- Travis: re-enable code-coverage on scrutinizer [\#177](https://github.com/ddeboer/imap/pull/177) ([Slamdunk](https://github.com/Slamdunk)) +- Add .gitattributes to remove from releases unneded files [\#173](https://github.com/ddeboer/imap/pull/173) ([Slamdunk](https://github.com/Slamdunk)) +- Travis: use local Dovecot installation [\#170](https://github.com/ddeboer/imap/pull/170) ([Slamdunk](https://github.com/Slamdunk)) +- Need all Headers in string format [\#149](https://github.com/ddeboer/imap/pull/149) ([FlashWS](https://github.com/FlashWS)) +- Get raw mail [\#146](https://github.com/ddeboer/imap/pull/146) ([styxit](https://github.com/styxit)) +- add getBcc\(\), Set, Clear Flag\(\Seen, \Answered, \Flagged, \Deleted, and \Draft\), getHeadersRaw\(\) [\#144](https://github.com/ddeboer/imap/pull/144) ([trungpv93](https://github.com/trungpv93)) + +**Fixed bugs:** + +- Search\Condition needs charset escaping/indication [\#190](https://github.com/ddeboer/imap/issues/190) +- imap\_utf7\_\(encode|decode\) -\> mb\_convert\_encoding [\#185](https://github.com/ddeboer/imap/issues/185) +- Espaรฑa [\#176](https://github.com/ddeboer/imap/issues/176) +- getHeaders\(\) decode broke information [\#171](https://github.com/ddeboer/imap/issues/171) +- Date format for date search condition [\#168](https://github.com/ddeboer/imap/issues/168) +- Error when trying fetch messages from container [\#167](https://github.com/ddeboer/imap/issues/167) +- Attachment encoding error [\#158](https://github.com/ddeboer/imap/issues/158) +- getFilename\(\) is empty and no attachment, even when there is an attachment. [\#142](https://github.com/ddeboer/imap/issues/142) +- Encoding issues [\#136](https://github.com/ddeboer/imap/issues/136) +- URGENT: The timezone could not be found in the database [\#135](https://github.com/ddeboer/imap/issues/135) +- Incorrect transcoding of text attachments [\#132](https://github.com/ddeboer/imap/issues/132) +- Undefined offset [\#123](https://github.com/ddeboer/imap/issues/123) +- ICS file not supported as attachment [\#120](https://github.com/ddeboer/imap/issues/120) +- Should iconv be a requirement? [\#115](https://github.com/ddeboer/imap/issues/115) +- KeepUnseen doen't work [\#92](https://github.com/ddeboer/imap/issues/92) +- PHP Fatal error Failed to parse time string in ddeboer/imap/src/Message.php [\#89](https://github.com/ddeboer/imap/issues/89) +- encoding issue [\#85](https://github.com/ddeboer/imap/issues/85) +- keepUnseen not working correctly with Hotmail [\#84](https://github.com/ddeboer/imap/issues/84) +- Iconv Exception [\#78](https://github.com/ddeboer/imap/issues/78) +- $message-\>getAttachments\(\) doesn't recognize some attachments [\#74](https://github.com/ddeboer/imap/issues/74) +- Message::move\(\) doesn't work. [\#73](https://github.com/ddeboer/imap/issues/73) +- Message\Part: part number must distinguish original message [\#223](https://github.com/ddeboer/imap/pull/223) ([Slamdunk](https://github.com/Slamdunk)) +- Recursive Embedded email body bug [\#222](https://github.com/ddeboer/imap/pull/222) ([Slamdunk](https://github.com/Slamdunk)) +- Exclude HTML from allowed attachment subtype [\#212](https://github.com/ddeboer/imap/pull/212) ([Slamdunk](https://github.com/Slamdunk)) +- Fix imap\_mail\_move behaviour and test it [\#207](https://github.com/ddeboer/imap/pull/207) ([Slamdunk](https://github.com/Slamdunk)) +- Undefined encoding: throw exception [\#197](https://github.com/ddeboer/imap/pull/197) ([Slamdunk](https://github.com/Slamdunk)) +- Message charset: mb\_convert\_encoding + aliases [\#196](https://github.com/ddeboer/imap/pull/196) ([Slamdunk](https://github.com/Slamdunk)) +- Mailbox: only UTF-8 names [\#193](https://github.com/ddeboer/imap/pull/193) ([Slamdunk](https://github.com/Slamdunk)) +- Search\Date\AbstractDate: fix format to RFC-3501 [\#189](https://github.com/ddeboer/imap/pull/189) ([Slamdunk](https://github.com/Slamdunk)) +- Travis: fix failing tests [\#172](https://github.com/ddeboer/imap/pull/172) ([Slamdunk](https://github.com/Slamdunk)) +- Return body of single-part HTML message as HTML, not text [\#101](https://github.com/ddeboer/imap/pull/101) ([joker806](https://github.com/joker806)) +- Implement "undisclosed recipients" addresses [\#86](https://github.com/ddeboer/imap/pull/86) ([darit](https://github.com/darit)) + +**Closed issues:** + +- Potential memory issue with attachments [\#195](https://github.com/ddeboer/imap/issues/195) +- Explain Message::delete [\#175](https://github.com/ddeboer/imap/issues/175) +- Get raw message [\#161](https://github.com/ddeboer/imap/issues/161) +- Composer install problem [\#160](https://github.com/ddeboer/imap/issues/160) +- Transcoder not exist [\#154](https://github.com/ddeboer/imap/issues/154) +- The library doesn't support using sort by [\#151](https://github.com/ddeboer/imap/issues/151) +- Office 365 - Array to string conversion error [\#131](https://github.com/ddeboer/imap/issues/131) +- Is there a method to turn a seen message into an "unseen" one ? [\#130](https://github.com/ddeboer/imap/issues/130) +- Create mailbox [\#126](https://github.com/ddeboer/imap/issues/126) +- Move and Delete Message not working [\#112](https://github.com/ddeboer/imap/issues/112) +- Problem on production server [\#111](https://github.com/ddeboer/imap/issues/111) +- Authentication failed for a Gmail account [\#109](https://github.com/ddeboer/imap/issues/109) +- A method to run IMAP commands? [\#83](https://github.com/ddeboer/imap/issues/83) + +**Merged pull requests:** + +- Update README.md to latest develop changes [\#224](https://github.com/ddeboer/imap/pull/224) ([Slamdunk](https://github.com/Slamdunk)) +- Add Filippo Tessarotto as an author of the package [\#219](https://github.com/ddeboer/imap/pull/219) ([Slamdunk](https://github.com/Slamdunk)) +- README.md: call Connection::expunge after move and delete [\#210](https://github.com/ddeboer/imap/pull/210) ([Slamdunk](https://github.com/Slamdunk)) +- Remove misleading Mailbox::expunge\(\) [\#206](https://github.com/ddeboer/imap/pull/206) ([Slamdunk](https://github.com/Slamdunk)) +- Add CHANGELOG.md [\#194](https://github.com/ddeboer/imap/pull/194) ([Slamdunk](https://github.com/Slamdunk)) +- README.md updates [\#178](https://github.com/ddeboer/imap/pull/178) ([Slamdunk](https://github.com/Slamdunk)) + +## [0.5.2](https://github.com/ddeboer/imap/tree/0.5.2) (2015-12-03) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.1...0.5.2) + +**Closed issues:** + +- $message-\>getAttachments\(\) returns null if message has no attachments [\#80](https://github.com/ddeboer/imap/issues/80) +- Email objects visibility [\#76](https://github.com/ddeboer/imap/issues/76) + +**Merged pull requests:** + +- Fixed the keepUnseen method [\#95](https://github.com/ddeboer/imap/pull/95) ([aeyoll](https://github.com/aeyoll)) +- Mark Mailbox as countable, fix doc comments [\#91](https://github.com/ddeboer/imap/pull/91) ([krzysiekpiasecki](https://github.com/krzysiekpiasecki)) +- Message::getAttachments confirm to signature [\#82](https://github.com/ddeboer/imap/pull/82) ([boekkooi](https://github.com/boekkooi)) +- Added hasMailbox to Connection [\#81](https://github.com/ddeboer/imap/pull/81) ([boekkooi](https://github.com/boekkooi)) +- Make sure imap connection are reopened [\#79](https://github.com/ddeboer/imap/pull/79) ([joserobleda](https://github.com/joserobleda)) + +## [0.5.1](https://github.com/ddeboer/imap/tree/0.5.1) (2015-02-01) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.0...0.5.1) + +**Closed issues:** + +- imap\_open error [\#72](https://github.com/ddeboer/imap/issues/72) +- $message-\>getAttachments\(\) does not return anything, even though a message has at least one attachment [\#71](https://github.com/ddeboer/imap/issues/71) +- Prepare docs for 1.0 [\#69](https://github.com/ddeboer/imap/issues/69) +- "date" header is not reliable [\#63](https://github.com/ddeboer/imap/issues/63) +- File Attachments don't show up [\#55](https://github.com/ddeboer/imap/issues/55) + +**Merged pull requests:** + +- Add support for attachments without content disposition [\#70](https://github.com/ddeboer/imap/pull/70) ([ddeboer](https://github.com/ddeboer)) + +## [0.5.0](https://github.com/ddeboer/imap/tree/0.5.0) (2015-01-24) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.4.0...0.5.0) + +**Closed issues:** + +- Use utf8\_encode\(\) function to encode content [\#66](https://github.com/ddeboer/imap/issues/66) +- Please add function order by date [\#59](https://github.com/ddeboer/imap/issues/59) +- mb\_convert\_encoding breaks code [\#57](https://github.com/ddeboer/imap/issues/57) +- How get I getMessages but newest first ... [\#11](https://github.com/ddeboer/imap/issues/11) + +## [0.4.0](https://github.com/ddeboer/imap/tree/0.4.0) (2015-01-04) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.1...0.4.0) + +**Closed issues:** + +- Please add 6th parameter to imap\_open call [\#62](https://github.com/ddeboer/imap/issues/62) +- Should Message::delete\(\) use the Message UID? [\#46](https://github.com/ddeboer/imap/issues/46) +- mb\_convert\_encoding\(\): Illegal character encoding specified [\#35](https://github.com/ddeboer/imap/issues/35) +- Deleting a message isn't working [\#30](https://github.com/ddeboer/imap/issues/30) +- imap\_header doesn't work with message uid [\#26](https://github.com/ddeboer/imap/issues/26) + +**Merged pull requests:** + +- Added basic requirement [\#61](https://github.com/ddeboer/imap/pull/61) ([nikoskip](https://github.com/nikoskip)) +- FIX: PHP error: "Cannot declare class Ddeboer\Imap\Search\Text\Text ..." [\#58](https://github.com/ddeboer/imap/pull/58) ([racztiborzoltan](https://github.com/racztiborzoltan)) +- Message::delete sets the FT\_UID flag. Fixes \#30 Fixes \#46 [\#54](https://github.com/ddeboer/imap/pull/54) ([ctalbot](https://github.com/ctalbot)) +- Allow binary-encoded part content [\#48](https://github.com/ddeboer/imap/pull/48) ([joker806](https://github.com/joker806)) +- Fix CS [\#47](https://github.com/ddeboer/imap/pull/47) ([xelan](https://github.com/xelan)) +- fixed typo [\#45](https://github.com/ddeboer/imap/pull/45) ([xelan](https://github.com/xelan)) + +## [0.3.1](https://github.com/ddeboer/imap/tree/0.3.1) (2014-08-11) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.0...0.3.1) + +**Merged pull requests:** + +- \imap\_header dosen't work with UID [\#44](https://github.com/ddeboer/imap/pull/44) ([ysramirez](https://github.com/ysramirez)) + +## [0.3.0](https://github.com/ddeboer/imap/tree/0.3.0) (2014-08-10) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.2...0.3.0) + +**Closed issues:** + +- please remove useless wiki [\#42](https://github.com/ddeboer/imap/issues/42) +- Travis tests allways fail? [\#40](https://github.com/ddeboer/imap/issues/40) +- Garbled e-mail body encoding [\#27](https://github.com/ddeboer/imap/issues/27) +- Improve docs [\#25](https://github.com/ddeboer/imap/issues/25) +- "undisclosed-recipients" throws error [\#23](https://github.com/ddeboer/imap/issues/23) + +**Merged pull requests:** + +- correct minor typo [\#43](https://github.com/ddeboer/imap/pull/43) ([cordoval](https://github.com/cordoval)) +- Utf-8 encode body content. [\#39](https://github.com/ddeboer/imap/pull/39) ([cmoralesweb](https://github.com/cmoralesweb)) +- Fix regex parsing the date header \(allowing multiple brackets\) [\#38](https://github.com/ddeboer/imap/pull/38) ([joker806](https://github.com/joker806)) +- Allow empty connection flags [\#34](https://github.com/ddeboer/imap/pull/34) ([joker806](https://github.com/joker806)) +- Fixed typo [\#32](https://github.com/ddeboer/imap/pull/32) ([abhinavkumar940](https://github.com/abhinavkumar940)) + +## [0.2](https://github.com/ddeboer/imap/tree/0.2) (2013-11-24) +[Full Changelog](https://github.com/ddeboer/imap/compare/0.1...0.2) + +## [0.1](https://github.com/ddeboer/imap/tree/0.1) (2013-11-22) +**Closed issues:** + +- Prevent setting SEEN flag [\#20](https://github.com/ddeboer/imap/issues/20) +- Add tests [\#18](https://github.com/ddeboer/imap/issues/18) +- delete messages [\#9](https://github.com/ddeboer/imap/issues/9) +- README is missing basic usage [\#7](https://github.com/ddeboer/imap/issues/7) +- Subject and other texts are decoded incorrectly [\#3](https://github.com/ddeboer/imap/issues/3) + +**Merged pull requests:** + +- also fetch inline attachments [\#24](https://github.com/ddeboer/imap/pull/24) ([kaiserlos](https://github.com/kaiserlos)) +- since leading slash is always needed [\#22](https://github.com/ddeboer/imap/pull/22) ([huglester](https://github.com/huglester)) +- Added missed createMailbox\($name\) function [\#19](https://github.com/ddeboer/imap/pull/19) ([burci](https://github.com/burci)) +- Added move and delete function to message + expunge function [\#17](https://github.com/ddeboer/imap/pull/17) ([burci](https://github.com/burci)) +- Clean up some unused variable [\#16](https://github.com/ddeboer/imap/pull/16) ([burci](https://github.com/burci)) +- Fixed mailbox encoding [\#15](https://github.com/ddeboer/imap/pull/15) ([burci](https://github.com/burci)) +- Create new mailbox [\#14](https://github.com/ddeboer/imap/pull/14) ([burci](https://github.com/burci)) +- Fixed bug in getDecodedContent with 'format=flowed' email [\#13](https://github.com/ddeboer/imap/pull/13) ([burci](https://github.com/burci)) +- Fixed date parsing for some imap servers [\#12](https://github.com/ddeboer/imap/pull/12) ([thelfensdrfer](https://github.com/thelfensdrfer)) +- Add support for more complex search expressions. [\#10](https://github.com/ddeboer/imap/pull/10) ([jamesiarmes](https://github.com/jamesiarmes)) +- Allow user to change server connection flags [\#6](https://github.com/ddeboer/imap/pull/6) ([mvar](https://github.com/mvar)) +- Improvements in EmailAddress class [\#4](https://github.com/ddeboer/imap/pull/4) ([mvar](https://github.com/mvar)) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/data/web/inc/lib/vendor/ddeboer/imap/LICENSE b/data/web/inc/lib/vendor/ddeboer/imap/LICENSE new file mode 100644 index 00000000..2c679e30 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2013 David de Boer + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/data/web/inc/lib/vendor/ddeboer/imap/README.md b/data/web/inc/lib/vendor/ddeboer/imap/README.md new file mode 100644 index 00000000..250f0504 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/README.md @@ -0,0 +1,356 @@ +# IMAP library + +[![Build Status](https://travis-ci.org/ddeboer/imap.svg?branch=master)](https://travis-ci.org/ddeboer/imap) +[![Code Coverage](https://scrutinizer-ci.com/g/ddeboer/imap/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/imap/?branch=master) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/ddeboer/imap/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/imap/?branch=master) +[![Latest Stable Version](https://poser.pugx.org/ddeboer/imap/v/stable.svg)](https://packagist.org/packages/ddeboer/imap) +[![Total Downloads](https://poser.pugx.org/ddeboer/imap/downloads.png)](https://packagist.org/packages/ddeboer/imap) + +A PHP 7.1+ library to read and process e-mails over IMAP. + +This library requires [IMAP](https://secure.php.net/manual/en/book.imap.php), +[iconv](https://secure.php.net/manual/en/book.iconv.php) and +[Multibyte String](https://secure.php.net/manual/en/book.mbstring.php) extensions installed. + +## Table of Contents + +1. [Installation](#installation) +1. [Usage](#usage) + 1. [Connect and Authenticate](#connect-and-authenticate) + 1. [Mailboxes](#mailboxes) + 1. [Messages](#messages) + 1. [Searching for Messages](#searching-for-messages) + 1. [Unknown search criterion: OR](#unknown-search-criterion-or) + 1. [Message Properties and Operations](#message-properties-and-operations) + 1. [Message Attachments](#message-attachments) + 1. [Embedded Messages](#embedded-messages) + 1. [Timeouts](#timeouts) +1. [Mock the library](#mock-the-library) +1. [Running the Tests](#running-the-tests) + 1. [Running Tests using Docker](#running-tests-using-docker) + +## Installation + +The recommended way to install the IMAP library is through [Composer](https://getcomposer.org): + +```bash +$ composer require ddeboer/imap +``` + +This command requires you to have Composer installed globally, as explained +in the [installation chapter](https://getcomposer.org/doc/00-intro.md) +of the Composer documentation. + +## Usage + +### Connect and Authenticate + +```php +use Ddeboer\Imap\Server; + +$server = new Server('imap.gmail.com'); + +// $connection is instance of \Ddeboer\Imap\Connection +$connection = $server->authenticate('my_username', 'my_password'); +``` + +You can specify port, [flags and parameters](https://secure.php.net/manual/en/function.imap-open.php) +to the server: + +```php +$server = new Server( + $hostname, // required + $port, // defaults to '993' + $flags, // defaults to '/imap/ssl/validate-cert' + $parameters +); +``` + +### Mailboxes + +Retrieve mailboxes (also known as mail folders) from the mail server and iterate +over them: + +```php +$mailboxes = $connection->getMailboxes(); + +foreach ($mailboxes as $mailbox) { + // Skip container-only mailboxes + // @see https://secure.php.net/manual/en/function.imap-getmailboxes.php + if ($mailbox->getAttributes() & \LATT_NOSELECT) { + continue; + } + + // $mailbox is instance of \Ddeboer\Imap\Mailbox + printf('Mailbox "%s" has %s messages', $mailbox->getName(), $mailbox->count()); +} +``` + +Or retrieve a specific mailbox: + +```php +$mailbox = $connection->getMailbox('INBOX'); +``` + +Delete a mailbox: + +```php +$connection->deleteMailbox($mailbox); +``` + +You can bulk set, or clear, any [flag](https://secure.php.net/manual/en/function.imap-setflag-full.php) of mailbox messages (by UIDs): + +```php +$mailbox->setFlag('\\Seen \\Flagged', ['1:5', '7', '9']); +$mailbox->setFlag('\\Seen', '1,3,5,6:8'); + +$mailbox->clearFlag('\\Flagged', '1,3'); +``` + +**WARNING** You must retrieve new Message instances in case of bulk modify flags to refresh the single Messages flags. + +### Messages + +Retrieve messages (e-mails) from a mailbox and iterate over them: + +```php +$messages = $mailbox->getMessages(); + +foreach ($messages as $message) { + // $message is instance of \Ddeboer\Imap\Message +} +``` + +To insert a new message (that just has been sent) into the Sent mailbox and flag it as seen: + +```php +$mailbox = $connection->getMailbox('Sent'); +$mailbox->addMessage($messageMIME, '\\Seen'); +``` + +Note that the message should be a string at MIME format (as described in the [RFC2045](https://tools.ietf.org/html/rfc2045)). + +#### Searching for Messages + +```php +use Ddeboer\Imap\SearchExpression; +use Ddeboer\Imap\Search\Email\To; +use Ddeboer\Imap\Search\Text\Body; + +$search = new SearchExpression(); +$search->addCondition(new To('me@here.com')); +$search->addCondition(new Body('contents')); + +$messages = $mailbox->getMessages($search); +``` + +**WARNING** We are currently unable to have both spaces _and_ double-quotes +escaped together. Only spaces are currently escaped correctly. +You can use `Ddeboer\Imap\Search\RawExpression` to write the complete search +condition by yourself. + +Messages can also be retrieved sorted as per [imap_sort](https://secure.php.net/manual/en/function.imap-sort.php) +function: + +```php +$today = new DateTimeImmutable(); +$lastMonth = $today->sub(new DateInterval('P30D')); + +$messages = $mailbox->getMessages( + new Ddeboer\Imap\Search\Date\Since($lastMonth), + \SORTDATE, // Sort criteria + true // Descending order +); +``` + +#### Unknown search criterion: OR + +Note that PHP imap library relies on the `c-client` library available at https://www.washington.edu/imap/ +which doesn't fully support some IMAP4 search criteria like `OR`. If you want those unsupported criteria, +you need to manually patch the latest version (`imap-2007f` of 23-Jul-2011 at the time of this commit) +and recompile PHP onto your patched `c-client` library. + +By the way most of the common search criteria are available and functioning, browse them in `./src/Search`. + +References: + +1. https://stackoverflow.com/questions/36356715/imap-search-unknown-search-criterion-or +1. imap-2007f.tar.gz: `./src/c-client/mail.c` and `./docs/internal.txt` + +#### Message Properties and Operations + +Get message number and unique [message id](https://en.wikipedia.org/wiki/Message-ID) +in the form <...>: + +```php +$message->getNumber(); +$message->getId(); +``` + +Get other message properties: + +```php +$message->getSubject(); +$message->getFrom(); // Message\EmailAddress +$message->getTo(); // array of Message\EmailAddress +$message->getDate(); // DateTimeImmutable +$message->isAnswered(); +$message->isDeleted(); +$message->isDraft(); +$message->isSeen(); +``` + +Get message headers as a [\Ddeboer\Imap\Message\Headers](/src/Ddeboer/Imap/Message/Headers.php) object: + +```php +$message->getHeaders(); +``` + +Get message body as HTML or plain text: + +```php +$message->getBodyHtml(); // Content of text/html part, if present +$message->getBodyText(); // Content of text/plain part, if present +``` + +Reading the message body keeps the message as unseen. +If you want to mark the message as seen: + +```php +$message->markAsSeen(); +``` + +Or you can set, or clear, any [flag](https://secure.php.net/manual/en/function.imap-setflag-full.php): + +```php +$message->setFlag('\\Seen \\Flagged'); +$message->clearFlag('\\Flagged'); +``` + +Move a message to another mailbox: + +```php +$mailbox = $connection->getMailbox('another-mailbox'); +$message->move($mailbox); +$connection->expunge(); +``` + +Deleting messages: + +```php +$mailbox->getMessage(1)->delete(); +$mailbox->getMessage(2)->delete(); +$connection->expunge(); +``` + +### Message Attachments + +Get message attachments (both inline and attached) and iterate over them: + +```php +$attachments = $message->getAttachments(); + +foreach ($attachments as $attachment) { + // $attachment is instance of \Ddeboer\Imap\Message\Attachment +} +``` + +Download a message attachment to a local file: + +```php +// getDecodedContent() decodes the attachmentโ€™s contents automatically: +file_put_contents( + '/my/local/dir/' . $attachment->getFilename(), + $attachment->getDecodedContent() +); +``` + +### Embedded Messages + +Check if attachment is embedded message and get it: + +```php +$attachments = $message->getAttachments(); + +foreach ($attachments as $attachment) { + if ($attachment->isEmbeddedMessage()) { + $embeddedMessage = $attachment->getEmbeddedMessage(); + // $embeddedMessage is instance of \Ddeboer\Imap\Message\EmbeddedMessage + } +} +``` + +An EmbeddedMessage has the same API as a normal Message, apart from flags +and operations like copy, move or delete. + +### Timeouts + +The IMAP extension provides the [imap_timeout](https://secure.php.net/manual/en/function.imap-timeout.php) +function to adjust the timeout seconds for various operations. + +However the extension's implementation doesn't link the functionality to a +specific context or connection, instead they are global. So in order to not +affect functionalities outside this library, we had to choose whether wrap +every `imap_*` call around an optional user-provided timeout or leave this +task to the user. + +Because of the heterogeneous world of IMAP servers and the high complexity +burden cost for such a little gain of the former, we chose the latter. + +## Mock the library + +Mockability is granted by interfaces present for each API. +Dig into [MockabilityTest](tests/MockabilityTest.php) for an example of a +mocked workflow. + +## Running the Tests + +This library is functionally tested on [Travis CI](https://travis-ci.org/ddeboer/imap) +against a local Dovecot server. + +If you have your own IMAP (test) account, you can run the tests locally by +providing your IMAP credentials: + +```bash +$ composer install +$ IMAP_SERVER_NAME="my.imap.server.com" IMAP_SERVER_PORT="60993" IMAP_USERNAME="johndoe" IMAP_PASSWORD="p4ssword" vendor/bin/phpunit +``` + +You can also copy `phpunit.xml.dist` file to a custom `phpunit.xml` and put +these environment variables in it: + +```xml + + + + + ./tests/ + + + + + ./src + + + + + + + + + +``` + +**WARNING** Tests create new mailboxes without removing them. + +### Running Tests using Docker + +If you have Docker installed you can run the tests locally with the following command: + +``` +$ docker-compose run tests +``` diff --git a/data/web/inc/lib/vendor/ddeboer/imap/composer.json b/data/web/inc/lib/vendor/ddeboer/imap/composer.json new file mode 100644 index 00000000..2286f310 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/composer.json @@ -0,0 +1,47 @@ +{ + "name": "ddeboer/imap", + "description": "Object-oriented IMAP for PHP", + "keywords": [ + "email", + "mail", + "imap" + ], + "license": "MIT", + "authors": [ + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com" + }, + { + "name": "Community contributors", + "homepage": "https://github.com/ddeboer/imap/graphs/contributors" + } + ], + "require": { + "php": "^7.1", + "ext-iconv": "*", + "ext-imap": "*", + "ext-mbstring": "*" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.13", + "phpstan/phpstan": "^0.9.1", + "phpstan/phpstan-phpunit": "^0.9.3", + "phpunit/phpunit": "^7.4", + "zendframework/zend-mail": "^2.10" + }, + "autoload": { + "psr-4": { + "Ddeboer\\Imap\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Ddeboer\\Imap\\Tests\\": "tests/" + } + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php new file mode 100644 index 00000000..a12ec789 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php @@ -0,0 +1,215 @@ +resource = $resource; + $this->server = $server; + } + + /** + * Get IMAP resource. + * + * @return ImapResourceInterface + */ + public function getResource(): ImapResourceInterface + { + return $this->resource; + } + + /** + * Delete all messages marked for deletion. + * + * @return bool + */ + public function expunge(): bool + { + return \imap_expunge($this->resource->getStream()); + } + + /** + * Close connection. + * + * @param int $flag + * + * @return bool + */ + public function close(int $flag = 0): bool + { + return \imap_close($this->resource->getStream(), $flag); + } + + /** + * Get a list of mailboxes (also known as folders). + * + * @return MailboxInterface[] + */ + public function getMailboxes(): array + { + $this->initMailboxNames(); + + if (null === $this->mailboxes) { + $this->mailboxes = []; + foreach ($this->mailboxNames as $mailboxName => $mailboxInfo) { + $this->mailboxes[(string) $mailboxName] = $this->getMailbox((string) $mailboxName); + } + } + + return $this->mailboxes; + } + + /** + * Check that a mailbox with the given name exists. + * + * @param string $name Mailbox name + * + * @return bool + */ + public function hasMailbox(string $name): bool + { + $this->initMailboxNames(); + + return isset($this->mailboxNames[$name]); + } + + /** + * Get a mailbox by its name. + * + * @param string $name Mailbox name + * + * @throws MailboxDoesNotExistException If mailbox does not exist + * + * @return MailboxInterface + */ + public function getMailbox(string $name): MailboxInterface + { + if (false === $this->hasMailbox($name)) { + throw new MailboxDoesNotExistException(\sprintf('Mailbox name "%s" does not exist', $name)); + } + + return new Mailbox($this->resource, $name, $this->mailboxNames[$name]); + } + + /** + * Count number of messages not in any mailbox. + * + * @return int + */ + public function count() + { + return \imap_num_msg($this->resource->getStream()); + } + + /** + * Check if the connection is still active. + * + * @throws InvalidResourceException If connection was closed + * + * @return bool + */ + public function ping(): bool + { + return \imap_ping($this->resource->getStream()); + } + + /** + * Create mailbox. + * + * @param string $name + * + * @throws CreateMailboxException + * + * @return MailboxInterface + */ + public function createMailbox(string $name): MailboxInterface + { + if (false === \imap_createmailbox($this->resource->getStream(), $this->server . \mb_convert_encoding($name, 'UTF7-IMAP', 'UTF-8'))) { + throw new CreateMailboxException(\sprintf('Can not create "%s" mailbox at "%s"', $name, $this->server)); + } + + $this->mailboxNames = $this->mailboxes = null; + $this->resource->clearLastMailboxUsedCache(); + + return $this->getMailbox($name); + } + + /** + * Create mailbox. + * + * @param MailboxInterface $mailbox + * + * @throws DeleteMailboxException + */ + public function deleteMailbox(MailboxInterface $mailbox): void + { + if (false === \imap_deletemailbox($this->resource->getStream(), $mailbox->getFullEncodedName())) { + throw new DeleteMailboxException(\sprintf('Mailbox "%s" could not be deleted', $mailbox->getName())); + } + + $this->mailboxes = $this->mailboxNames = null; + $this->resource->clearLastMailboxUsedCache(); + } + + /** + * Get mailbox names. + */ + private function initMailboxNames(): void + { + if (null !== $this->mailboxNames) { + return; + } + + $this->mailboxNames = []; + $mailboxesInfo = \imap_getmailboxes($this->resource->getStream(), $this->server, '*'); + if (!\is_array($mailboxesInfo)) { + throw new ImapGetmailboxesException('imap_getmailboxes failed'); + } + + foreach ($mailboxesInfo as $mailboxInfo) { + $name = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP'); + $this->mailboxNames[$name] = $mailboxInfo; + } + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php new file mode 100644 index 00000000..ac181657 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php @@ -0,0 +1,82 @@ + 'E_ERROR', + \E_WARNING => 'E_WARNING', + \E_PARSE => 'E_PARSE', + \E_NOTICE => 'E_NOTICE', + \E_CORE_ERROR => 'E_CORE_ERROR', + \E_CORE_WARNING => 'E_CORE_WARNING', + \E_COMPILE_ERROR => 'E_COMPILE_ERROR', + \E_COMPILE_WARNING => 'E_COMPILE_WARNING', + \E_USER_ERROR => 'E_USER_ERROR', + \E_USER_WARNING => 'E_USER_WARNING', + \E_USER_NOTICE => 'E_USER_NOTICE', + \E_STRICT => 'E_STRICT', + \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', + \E_DEPRECATED => 'E_DEPRECATED', + \E_USER_DEPRECATED => 'E_USER_DEPRECATED', + ]; + + /** + * @param string $message The exception message + * @param int $code The exception code + * @param \Throwable $previous The previous exception + */ + final public function __construct(string $message, int $code = 0, \Throwable $previous = null) + { + $errorType = ''; + if (\is_int($code) && isset(self::$errorLabels[$code])) { + $errorType = \sprintf('[%s] ', self::$errorLabels[$code]); + } + + $joinString = "\n- "; + $alerts = \imap_alerts(); + $errors = \imap_errors(); + $completeMessage = \sprintf( + "%s%s\nimap_alerts (%s):%s\nimap_errors (%s):%s", + $errorType, + $message, + $alerts ? \count($alerts) : 0, + $alerts ? $joinString . \implode($joinString, $alerts) : '', + $errors ? \count($errors) : 0, + $errors ? $joinString . \implode($joinString, $errors) : '' + ); + + parent::__construct($completeMessage, $code, $previous); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php new file mode 100644 index 00000000..c0e93d00 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php @@ -0,0 +1,9 @@ +resource = $resource; + $this->mailbox = $mailbox; + } + + /** + * Get IMAP resource stream. + * + * @throws InvalidResourceException + * + * @return resource + */ + public function getStream() + { + if (false === \is_resource($this->resource) || 'imap' !== \get_resource_type($this->resource)) { + throw new InvalidResourceException('Supplied resource is not a valid imap resource'); + } + + $this->initMailbox(); + + return $this->resource; + } + + /** + * Clear last mailbox used cache. + */ + public function clearLastMailboxUsedCache(): void + { + self::$lastMailboxUsedCache = null; + } + + /** + * If connection is not currently in this mailbox, switch it to this mailbox. + */ + private function initMailbox(): void + { + if (null === $this->mailbox || $this->isMailboxOpen()) { + return; + } + + \imap_reopen($this->resource, $this->mailbox->getFullEncodedName()); + + if ($this->isMailboxOpen()) { + return; + } + + throw new ReopenMailboxException(\sprintf('Cannot reopen mailbox "%s"', $this->mailbox->getName())); + } + + /** + * Check whether the current mailbox is open. + * + * @return bool + */ + private function isMailboxOpen(): bool + { + $currentMailboxName = $this->mailbox->getFullEncodedName(); + if ($currentMailboxName === self::$lastMailboxUsedCache) { + return true; + } + + self::$lastMailboxUsedCache = null; + $check = \imap_check($this->resource); + $return = false !== $check && $check->Mailbox === $currentMailboxName; + + if (true === $return) { + self::$lastMailboxUsedCache = $currentMailboxName; + } + + return $return; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php new file mode 100644 index 00000000..03c16f7e --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php @@ -0,0 +1,20 @@ +resource = new ImapResource($resource->getStream(), $this); + $this->name = $name; + $this->info = $info; + } + + /** + * Get mailbox decoded name. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get mailbox encoded path. + * + * @return string + */ + public function getEncodedName(): string + { + return \preg_replace('/^{.+}/', '', $this->info->name); + } + + /** + * Get mailbox encoded full name. + * + * @return string + */ + public function getFullEncodedName(): string + { + return $this->info->name; + } + + /** + * Get mailbox attributes. + * + * @return int + */ + public function getAttributes(): int + { + return $this->info->attributes; + } + + /** + * Get mailbox delimiter. + * + * @return string + */ + public function getDelimiter(): string + { + return $this->info->delimiter; + } + + /** + * Get number of messages in this mailbox. + * + * @return int + */ + public function count() + { + return \imap_num_msg($this->resource->getStream()); + } + + /** + * Get Mailbox status. + * + * @param null|int $flags + * + * @return \stdClass + */ + public function getStatus(int $flags = null): \stdClass + { + return \imap_status($this->resource->getStream(), $this->getFullEncodedName(), $flags ?? \SA_ALL); + } + + /** + * Bulk Set Flag for Messages. + * + * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft + * @param array|MessageIterator|string $numbers Message numbers + * + * @return bool + */ + public function setFlag(string $flag, $numbers): bool + { + return \imap_setflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID); + } + + /** + * Bulk Clear Flag for Messages. + * + * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft + * @param array|MessageIterator|string $numbers Message numbers + * + * @return bool + */ + public function clearFlag(string $flag, $numbers): bool + { + return \imap_clearflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID); + } + + /** + * Get message ids. + * + * @param ConditionInterface $search Search expression (optional) + * + * @return MessageIteratorInterface + */ + public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false): MessageIteratorInterface + { + if (null === $search) { + $search = new All(); + } + $query = $search->toString(); + + // We need to clear the stack to know whether imap_last_error() + // is related to this imap_search + \imap_errors(); + + if (null !== $sortCriteria) { + $messageNumbers = \imap_sort($this->resource->getStream(), $sortCriteria, $descending ? 1 : 0, \SE_UID, $query); + } else { + $messageNumbers = \imap_search($this->resource->getStream(), $query, \SE_UID); + } + if (false === $messageNumbers) { + if (false !== \imap_last_error()) { + throw new InvalidSearchCriteriaException(\sprintf('Invalid search criteria [%s]', $query)); + } + + // imap_search can also return false + $messageNumbers = []; + } + + return new MessageIterator($this->resource, $messageNumbers); + } + + /** + * Get message iterator for a sequence. + * + * @param string $sequence Message numbers + * + * @return MessageIteratorInterface + */ + public function getMessageSequence(string $sequence): MessageIteratorInterface + { + \imap_errors(); + + $overview = \imap_fetch_overview($this->resource->getStream(), $sequence, FT_UID); + if (empty($overview)) { + if (false !== \imap_last_error()) { + throw new InvalidSearchCriteriaException(\sprintf('Invalid sequence [%s]', $sequence)); + } + + $messageNumbers = []; + } else { + $messageNumbers = \array_column($overview, 'uid'); + } + + return new MessageIterator($this->resource, $messageNumbers); + } + + /** + * Get a message by message number. + * + * @param int $number Message number + * + * @return MessageInterface + */ + public function getMessage(int $number): MessageInterface + { + return new Message($this->resource, $number); + } + + /** + * Get messages in this mailbox. + * + * @return MessageIteratorInterface + */ + public function getIterator(): MessageIteratorInterface + { + return $this->getMessages(); + } + + /** + * Add a message to the mailbox. + * + * @param string $message + * @param null|string $options + * @param null|DateTimeInterface $internalDate + * + * @return bool + */ + public function addMessage(string $message, string $options = null, DateTimeInterface $internalDate = null): bool + { + $arguments = [ + $this->resource->getStream(), + $this->getFullEncodedName(), + $message, + ]; + if (null !== $options) { + $arguments[] = $options; + if (null !== $internalDate) { + $arguments[] = $internalDate->format('d-M-Y H:i:s O'); + } + } + + return \imap_append(...$arguments); + } + + /** + * Returns a tree of threaded message for the current Mailbox. + * + * @return array + */ + public function getThread(): array + { + \set_error_handler(function () {}); + + $tree = \imap_thread($this->resource->getStream()); + + \restore_error_handler(); + + return false !== $tree ? $tree : []; + } + + /** + * Bulk move messages. + * + * @param array|MessageIterator|string $numbers Message numbers + * @param MailboxInterface $mailbox Destination Mailbox to move the messages to + * + * @throws \Ddeboer\Imap\Exception\MessageMoveException + */ + public function move($numbers, MailboxInterface $mailbox): void + { + if (!\imap_mail_move($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) { + throw new MessageMoveException(\sprintf('Messages cannot be moved to "%s"', $mailbox->getName())); + } + } + + /** + * Bulk copy messages. + * + * @param array|MessageIterator|string $numbers Message numbers + * @param MailboxInterface $mailbox Destination Mailbox to copy the messages to + * + * @throws \Ddeboer\Imap\Exception\MessageCopyException + */ + public function copy($numbers, MailboxInterface $mailbox): void + { + if (!\imap_mail_copy($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) { + throw new MessageCopyException(\sprintf('Messages cannot be copied to "%s"', $mailbox->getName())); + } + } + + /** + * Prepare message ids for the use with bulk functions. + * + * @param array|MessageIterator|string $messageIds Message numbers + * + * @return string + */ + private function prepareMessageIds($messageIds): string + { + if ($messageIds instanceof MessageIterator) { + $messageIds = $messageIds->getArrayCopy(); + } + + if (\is_array($messageIds)) { + $messageIds = \implode(',', $messageIds); + } + + return (string) $messageIds; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php new file mode 100644 index 00000000..59477a41 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php @@ -0,0 +1,150 @@ +structureLoaded) { + return; + } + $this->structureLoaded = true; + + $messageNumber = $this->getNumber(); + + $errorMessage = null; + $errorNumber = 0; + \set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) { + $errorMessage = $message; + $errorNumber = $nr; + }); + + $structure = \imap_fetchstructure( + $this->resource->getStream(), + $messageNumber, + \FT_UID + ); + + \restore_error_handler(); + + if (!$structure instanceof \stdClass) { + throw new MessageStructureException(\sprintf( + 'Message "%s" structure is empty: %s', + $messageNumber, + $errorMessage + ), $errorNumber); + } + + $this->setStructure($structure); + } + + /** + * Ensure message exists. + * + * @param int $messageNumber + */ + protected function assertMessageExists(int $messageNumber): void + { + if (true === $this->messageNumberVerified) { + return; + } + $this->messageNumberVerified = true; + + $msgno = \imap_msgno($this->resource->getStream(), $messageNumber); + if (\is_numeric($msgno) && $msgno > 0) { + return; + } + + throw new MessageDoesNotExistException(\sprintf( + 'Message "%s" does not exist', + $messageNumber + )); + } + + /** + * Get raw message headers. + * + * @return string + */ + public function getRawHeaders(): string + { + if (null === $this->rawHeaders) { + $this->rawHeaders = \imap_fetchheader($this->resource->getStream(), $this->getNumber(), \FT_UID); + } + + return $this->rawHeaders; + } + + /** + * Get the raw message, including all headers, parts, etc. unencoded and unparsed. + * + * @return string the raw message + */ + public function getRawMessage(): string + { + if (null === $this->rawMessage) { + $this->rawMessage = $this->doGetContent(''); + } + + return $this->rawMessage; + } + + /** + * Get message headers. + * + * @return Message\Headers + */ + public function getHeaders(): Message\Headers + { + if (null === $this->headers) { + // imap_headerinfo is much faster than imap_fetchheader + // imap_headerinfo returns only a subset of all mail headers, + // but it does include the message flags. + $headers = \imap_headerinfo($this->resource->getStream(), \imap_msgno($this->resource->getStream(), $this->getNumber())); + if (false === $headers) { + // @see https://github.com/ddeboer/imap/issues/358 + throw new InvalidHeadersException(\sprintf('Message "%s" has invalid headers', $this->getNumber())); + } + $this->headers = new Message\Headers($headers); + } + + return $this->headers; + } + + /** + * Clearmessage headers. + */ + private function clearHeaders(): void + { + $this->headers = null; + } + + /** + * Get message recent flag value (from headers). + * + * @return null|string + */ + public function isRecent(): ?string + { + return $this->getHeaders()->get('recent'); + } + + /** + * Get message unseen flag value (from headers). + * + * @return bool + */ + public function isUnseen(): bool + { + return 'U' === $this->getHeaders()->get('unseen'); + } + + /** + * Get message flagged flag value (from headers). + * + * @return bool + */ + public function isFlagged(): bool + { + return 'F' === $this->getHeaders()->get('flagged'); + } + + /** + * Get message answered flag value (from headers). + * + * @return bool + */ + public function isAnswered(): bool + { + return 'A' === $this->getHeaders()->get('answered'); + } + + /** + * Get message deleted flag value (from headers). + * + * @return bool + */ + public function isDeleted(): bool + { + return 'D' === $this->getHeaders()->get('deleted'); + } + + /** + * Get message draft flag value (from headers). + * + * @return bool + */ + public function isDraft(): bool + { + return 'X' === $this->getHeaders()->get('draft'); + } + + /** + * Has the message been marked as read? + * + * @return bool + */ + public function isSeen(): bool + { + return 'N' !== $this->getHeaders()->get('recent') && 'U' !== $this->getHeaders()->get('unseen'); + } + + /** + * Mark message as seen. + * + * @return bool + * + * @deprecated since version 1.1, to be removed in 2.0 + */ + public function maskAsSeen(): bool + { + \trigger_error(\sprintf('%s is deprecated and will be removed in 2.0. Use %s::markAsSeen instead.', __METHOD__, __CLASS__), \E_USER_DEPRECATED); + + return $this->markAsSeen(); + } + + /** + * Mark message as seen. + * + * @return bool + */ + public function markAsSeen(): bool + { + return $this->setFlag('\\Seen'); + } + + /** + * Move message to another mailbox. + * + * @param MailboxInterface $mailbox + * + * @throws MessageCopyException + */ + public function copy(MailboxInterface $mailbox): void + { + // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header + $this->clearHeaders(); + + if (!\imap_mail_copy($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) { + throw new MessageCopyException(\sprintf('Message "%s" cannot be copied to "%s"', $this->getNumber(), $mailbox->getName())); + } + } + + /** + * Move message to another mailbox. + * + * @param MailboxInterface $mailbox + * + * @throws MessageMoveException + */ + public function move(MailboxInterface $mailbox): void + { + // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header + $this->clearHeaders(); + + if (!\imap_mail_move($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) { + throw new MessageMoveException(\sprintf('Message "%s" cannot be moved to "%s"', $this->getNumber(), $mailbox->getName())); + } + } + + /** + * Delete message. + * + * @throws MessageDeleteException + */ + public function delete(): void + { + // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header + $this->clearHeaders(); + + if (!\imap_delete($this->resource->getStream(), $this->getNumber(), \FT_UID)) { + throw new MessageDeleteException(\sprintf('Message "%s" cannot be deleted', $this->getNumber())); + } + } + + /** + * Set Flag Message. + * + * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft + * + * @return bool + */ + public function setFlag(string $flag): bool + { + $result = \imap_setflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID); + + $this->clearHeaders(); + + return $result; + } + + /** + * Clear Flag Message. + * + * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft + * + * @return bool + */ + public function clearFlag(string $flag): bool + { + $result = \imap_clearflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID); + + $this->clearHeaders(); + + return $result; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php new file mode 100644 index 00000000..a7fdb02e --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php @@ -0,0 +1,292 @@ + + * + * @return null|string + */ + final public function getId(): ?string + { + return $this->getHeaders()->get('message_id'); + } + + /** + * Get message sender (from headers). + * + * @return null|EmailAddress + */ + final public function getFrom(): ?EmailAddress + { + $from = $this->getHeaders()->get('from'); + + return null !== $from ? $this->decodeEmailAddress($from[0]) : null; + } + + /** + * Get To recipients. + * + * @return EmailAddress[] Empty array in case message has no To: recipients + */ + final public function getTo(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('to') ?: []); + } + + /** + * Get Cc recipients. + * + * @return EmailAddress[] Empty array in case message has no CC: recipients + */ + final public function getCc(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('cc') ?: []); + } + + /** + * Get Bcc recipients. + * + * @return EmailAddress[] Empty array in case message has no BCC: recipients + */ + final public function getBcc(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('bcc') ?: []); + } + + /** + * Get Reply-To recipients. + * + * @return EmailAddress[] Empty array in case message has no Reply-To: recipients + */ + final public function getReplyTo(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('reply_to') ?: []); + } + + /** + * Get Sender. + * + * @return EmailAddress[] Empty array in case message has no Sender: recipients + */ + final public function getSender(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('sender') ?: []); + } + + /** + * Get Return-Path. + * + * @return EmailAddress[] Empty array in case message has no Return-Path: recipients + */ + final public function getReturnPath(): array + { + return $this->decodeEmailAddresses($this->getHeaders()->get('return_path') ?: []); + } + + /** + * Get date (from headers). + * + * @return null|\DateTimeImmutable + */ + final public function getDate(): ?\DateTimeImmutable + { + $dateHeader = $this->getHeaders()->get('date'); + if (null === $dateHeader) { + return null; + } + + $alteredValue = $dateHeader; + $alteredValue = \str_replace(',', '', $alteredValue); + $alteredValue = \preg_replace('/^[a-zA-Z]+ ?/', '', $alteredValue); + $alteredValue = \preg_replace('/ +\(.*\)/', '', $alteredValue); + $alteredValue = \preg_replace('/\bUT\b/', 'UTC', $alteredValue); + if (0 === \preg_match('/\d\d:\d\d:\d\d.* [\+\-]\d\d:?\d\d/', $alteredValue)) { + $alteredValue .= ' +0000'; + } + + try { + $date = new \DateTimeImmutable($alteredValue); + } catch (\Throwable $ex) { + throw new InvalidDateHeaderException(\sprintf('Invalid Date header found: "%s"', $dateHeader), 0, $ex); + } + + return $date; + } + + /** + * Get message size (from headers). + * + * @return null|int|string + */ + final public function getSize() + { + return $this->getHeaders()->get('size'); + } + + /** + * Get message subject (from headers). + * + * @return null|string + */ + final public function getSubject(): ?string + { + return $this->getHeaders()->get('subject'); + } + + /** + * Get message In-Reply-To (from headers). + * + * @return array + */ + final public function getInReplyTo(): array + { + $inReplyTo = $this->getHeaders()->get('in_reply_to'); + + return null !== $inReplyTo ? \explode(' ', $inReplyTo) : []; + } + + /** + * Get message References (from headers). + * + * @return array + */ + final public function getReferences(): array + { + $references = $this->getHeaders()->get('references'); + + return null !== $references ? \explode(' ', $references) : []; + } + + /** + * Get body HTML. + * + * @return null|string + */ + final public function getBodyHtml(): ?string + { + $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $part) { + if (self::SUBTYPE_HTML === $part->getSubtype()) { + return $part->getDecodedContent(); + } + } + + // If message has no parts and is HTML, return content of message itself. + if (self::SUBTYPE_HTML === $this->getSubtype()) { + return $this->getDecodedContent(); + } + + return null; + } + + /** + * Get body text. + * + * @return null|string + */ + final public function getBodyText(): ?string + { + $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $part) { + if (self::SUBTYPE_PLAIN === $part->getSubtype()) { + return $part->getDecodedContent(); + } + } + + // If message has no parts, return content of message itself. + if (self::SUBTYPE_PLAIN === $this->getSubtype()) { + return $this->getDecodedContent(); + } + + return null; + } + + /** + * Get attachments (if any) linked to this e-mail. + * + * @return AttachmentInterface[] + */ + final public function getAttachments(): array + { + if (null === $this->attachments) { + static $gatherAttachments; + if (null === $gatherAttachments) { + $gatherAttachments = static function (PartInterface $part) use (&$gatherAttachments): array { + $attachments = []; + foreach ($part->getParts() as $childPart) { + if ($childPart instanceof Attachment) { + $attachments[] = $childPart; + } + if ($childPart->hasChildren()) { + $attachments = \array_merge($attachments, $gatherAttachments($childPart)); + } + } + + return $attachments; + }; + } + + $this->attachments = $gatherAttachments($this); + } + + return $this->attachments; + } + + /** + * Does this message have attachments? + * + * @return bool + */ + final public function hasAttachments(): bool + { + return \count($this->getAttachments()) > 0; + } + + /** + * @param array $addresses Addesses + * + * @return array + */ + private function decodeEmailAddresses(array $addresses): array + { + $return = []; + foreach ($addresses as $address) { + if (isset($address->mailbox)) { + $return[] = $this->decodeEmailAddress($address); + } + } + + return $return; + } + + /** + * @param \stdClass $value + * + * @return EmailAddress + */ + private function decodeEmailAddress(\stdClass $value): EmailAddress + { + return new EmailAddress($value->mailbox, $value->host, $value->personal); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php new file mode 100644 index 00000000..4be6738c --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php @@ -0,0 +1,578 @@ + self::TYPE_TEXT, + \TYPEMULTIPART => self::TYPE_MULTIPART, + \TYPEMESSAGE => self::TYPE_MESSAGE, + \TYPEAPPLICATION => self::TYPE_APPLICATION, + \TYPEAUDIO => self::TYPE_AUDIO, + \TYPEIMAGE => self::TYPE_IMAGE, + \TYPEVIDEO => self::TYPE_VIDEO, + \TYPEMODEL => self::TYPE_MODEL, + \TYPEOTHER => self::TYPE_OTHER, + ]; + + /** + * @var array + */ + private static $encodingsMap = [ + \ENC7BIT => self::ENCODING_7BIT, + \ENC8BIT => self::ENCODING_8BIT, + \ENCBINARY => self::ENCODING_BINARY, + \ENCBASE64 => self::ENCODING_BASE64, + \ENCQUOTEDPRINTABLE => self::ENCODING_QUOTED_PRINTABLE, + ]; + + /** + * @var array + */ + private static $attachmentKeys = [ + 'name' => true, + 'filename' => true, + 'name*' => true, + 'filename*' => true, + ]; + + /** + * Constructor. + * + * @param ImapResourceInterface $resource IMAP resource + * @param int $messageNumber Message number + * @param string $partNumber Part number + * @param \stdClass $structure Part structure + */ + public function __construct( + ImapResourceInterface $resource, + int $messageNumber, + string $partNumber, + \stdClass $structure + ) { + $this->resource = $resource; + $this->messageNumber = $messageNumber; + $this->partNumber = $partNumber; + $this->setStructure($structure); + } + + /** + * Get message number (from headers). + * + * @return int + */ + final public function getNumber(): int + { + $this->assertMessageExists($this->messageNumber); + + return $this->messageNumber; + } + + /** + * Ensure message exists. + * + * @param int $messageNumber + */ + protected function assertMessageExists(int $messageNumber): void + { + } + + /** + * @param \stdClass $structure Part structure + */ + final protected function setStructure(\stdClass $structure): void + { + $this->structure = $structure; + } + + /** + * Part structure. + * + * @return \stdClass + */ + final public function getStructure(): \stdClass + { + $this->lazyLoadStructure(); + + return $this->structure; + } + + /** + * Lazy load structure. + */ + protected function lazyLoadStructure(): void + { + } + + /** + * Part parameters. + * + * @return Parameters + */ + final public function getParameters(): Parameters + { + $this->lazyParseStructure(); + + return $this->parameters; + } + + /** + * Part charset. + * + * @return null|string + */ + final public function getCharset(): ?string + { + $this->lazyParseStructure(); + + return $this->parameters->get('charset') ?: null; + } + + /** + * Part type. + * + * @return null|string + */ + final public function getType(): ?string + { + $this->lazyParseStructure(); + + return $this->type; + } + + /** + * Part subtype. + * + * @return null|string + */ + final public function getSubtype(): ?string + { + $this->lazyParseStructure(); + + return $this->subtype; + } + + /** + * Part encoding. + * + * @return null|string + */ + final public function getEncoding(): ?string + { + $this->lazyParseStructure(); + + return $this->encoding; + } + + /** + * Part disposition. + * + * @return null|string + */ + final public function getDisposition(): ?string + { + $this->lazyParseStructure(); + + return $this->disposition; + } + + /** + * Part bytes. + * + * @return null|int|string + */ + final public function getBytes() + { + $this->lazyParseStructure(); + + return $this->bytes; + } + + /** + * Part lines. + * + * @return null|string + */ + final public function getLines(): ?string + { + $this->lazyParseStructure(); + + return $this->lines; + } + + /** + * Get raw part content. + * + * @return string + */ + final public function getContent(): string + { + if (null === $this->content) { + $this->content = $this->doGetContent($this->getContentPartNumber()); + } + + return $this->content; + } + + /** + * Get content part number. + * + * @return string + */ + protected function getContentPartNumber(): string + { + return $this->partNumber; + } + + /** + * Get part number. + * + * @return string + */ + final public function getPartNumber(): string + { + return $this->partNumber; + } + + /** + * Get decoded part content. + * + * @return string + */ + final public function getDecodedContent(): string + { + if (null === $this->decodedContent) { + if (self::ENCODING_UNKNOWN === $this->getEncoding()) { + throw new UnexpectedEncodingException('Cannot decode a content with an uknown encoding'); + } + + $content = $this->getContent(); + if (self::ENCODING_BASE64 === $this->getEncoding()) { + $content = \base64_decode($content); + } elseif (self::ENCODING_QUOTED_PRINTABLE === $this->getEncoding()) { + $content = \quoted_printable_decode($content); + } + + if (false === $content) { + throw new UnexpectedEncodingException('Cannot decode content'); + } + + // If this part is a text part, convert its charset to UTF-8. + // We don't want to decode an attachment's charset. + if (!$this instanceof Attachment && null !== $this->getCharset() && self::TYPE_TEXT === $this->getType()) { + $content = Transcoder::decode($content, $this->getCharset()); + } + + $this->decodedContent = $content; + } + + return $this->decodedContent; + } + + /** + * Get raw message content. + * + * @param string $partNumber + * + * @return string + */ + final protected function doGetContent(string $partNumber): string + { + return \imap_fetchbody( + $this->resource->getStream(), + $this->getNumber(), + $partNumber, + \FT_UID | \FT_PEEK + ); + } + + /** + * Get an array of all parts for this message. + * + * @return PartInterface[] + */ + final public function getParts(): array + { + $this->lazyParseStructure(); + + return $this->parts; + } + + /** + * Get current child part. + * + * @return mixed + */ + final public function current() + { + $this->lazyParseStructure(); + + return $this->parts[$this->key]; + } + + /** + * Get current child part. + * + * @return mixed + */ + final public function getChildren() + { + return $this->current(); + } + + /** + * Get current child part. + * + * @return bool + */ + final public function hasChildren() + { + $this->lazyParseStructure(); + + return \count($this->parts) > 0; + } + + /** + * Get current part key. + * + * @return int + */ + final public function key() + { + return $this->key; + } + + /** + * Move to next part. + * + * @return int + */ + final public function next() + { + ++$this->key; + } + + /** + * Reset part key. + * + * @return int + */ + final public function rewind() + { + $this->key = 0; + } + + /** + * Check if current part is a valid one. + * + * @return bool + */ + final public function valid() + { + $this->lazyParseStructure(); + + return isset($this->parts[$this->key]); + } + + /** + * Parse part structure. + */ + private function lazyParseStructure(): void + { + if (true === $this->structureParsed) { + return; + } + $this->structureParsed = true; + + $this->lazyLoadStructure(); + + $this->type = self::$typesMap[$this->structure->type] ?? self::TYPE_UNKNOWN; + + // In our context, \ENCOTHER is as useful as an uknown encoding + $this->encoding = self::$encodingsMap[$this->structure->encoding] ?? self::ENCODING_UNKNOWN; + $this->subtype = $this->structure->subtype; + + foreach (['disposition', 'bytes', 'description'] as $optional) { + if (isset($this->structure->{$optional})) { + $this->{$optional} = $this->structure->{$optional}; + } + } + + $this->parameters = new Parameters(); + if ($this->structure->ifparameters) { + $this->parameters->add($this->structure->parameters); + } + + if ($this->structure->ifdparameters) { + $this->parameters->add($this->structure->dparameters); + } + + // When the message is not multipart and the body is the attachment content + // Prevents infinite recursion + if (self::isAttachment($this->structure) && !$this instanceof Attachment) { + $this->parts[] = new Attachment($this->resource, $this->getNumber(), '1', $this->structure); + } + + if (isset($this->structure->parts)) { + $parts = $this->structure->parts; + // https://secure.php.net/manual/en/function.imap-fetchbody.php#89002 + if ($this instanceof Attachment && $this->isEmbeddedMessage() && 1 === \count($parts) && \TYPEMULTIPART === $parts[0]->type) { + $parts = $parts[0]->parts; + } + foreach ($parts as $key => $partStructure) { + $partNumber = (!$this instanceof Message) ? $this->partNumber . '.' : ''; + $partNumber .= (string) ($key + 1); + + $newPartClass = self::isAttachment($partStructure) + ? Attachment::class + : SimplePart::class + ; + + $this->parts[] = new $newPartClass($this->resource, $this->getNumber(), $partNumber, $partStructure); + } + } + } + + /** + * Check if the given part is an attachment. + * + * @param \stdClass $part + * + * @return bool + */ + private static function isAttachment(\stdClass $part): bool + { + if (isset(self::$typesMap[$part->type]) && self::TYPE_MULTIPART === self::$typesMap[$part->type]) { + return false; + } + + // Attachment with correct Content-Disposition header + if ($part->ifdisposition) { + if ('attachment' === \strtolower($part->disposition)) { + return true; + } + + if ( + 'inline' === \strtolower($part->disposition) + && self::SUBTYPE_PLAIN !== \strtoupper($part->subtype) + && self::SUBTYPE_HTML !== \strtoupper($part->subtype) + ) { + return true; + } + } + + // Attachment without Content-Disposition header + if ($part->ifparameters) { + foreach ($part->parameters as $parameter) { + if (isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) { + return true; + } + } + } + + /* + if ($part->ifdparameters) { + foreach ($part->dparameters as $parameter) { + if (isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) { + return true; + } + } + } + */ + + return false; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php new file mode 100644 index 00000000..35655fdf --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php @@ -0,0 +1,64 @@ +getParameters()->get('filename') + ?: $this->getParameters()->get('name'); + } + + /** + * Get attachment file size. + * + * @return int Number of bytes + */ + public function getSize() + { + return $this->getParameters()->get('size'); + } + + /** + * Is this attachment also an Embedded Message? + * + * @return bool + */ + public function isEmbeddedMessage(): bool + { + return self::TYPE_MESSAGE === $this->getType(); + } + + /** + * Return embedded message. + * + * @throws NotEmbeddedMessageException + * + * @return EmbeddedMessageInterface + */ + public function getEmbeddedMessage(): EmbeddedMessageInterface + { + if (!$this->isEmbeddedMessage()) { + throw new NotEmbeddedMessageException(\sprintf( + 'Attachment "%s" in message "%s" is not embedded message', + $this->getPartNumber(), + $this->getNumber() + )); + } + + return new EmbeddedMessage($this->resource, $this->getNumber(), $this->getPartNumber(), $this->getStructure()->parts[0]); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php new file mode 100644 index 00000000..595971b9 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php @@ -0,0 +1,39 @@ + + * + * @return null|string + */ + public function getId(): ?string; + + /** + * Get message sender (from headers). + * + * @return null|EmailAddress + */ + public function getFrom(): ?EmailAddress; + + /** + * Get To recipients. + * + * @return EmailAddress[] Empty array in case message has no To: recipients + */ + public function getTo(): array; + + /** + * Get Cc recipients. + * + * @return EmailAddress[] Empty array in case message has no CC: recipients + */ + public function getCc(): array; + + /** + * Get Bcc recipients. + * + * @return EmailAddress[] Empty array in case message has no BCC: recipients + */ + public function getBcc(): array; + + /** + * Get Reply-To recipients. + * + * @return EmailAddress[] Empty array in case message has no Reply-To: recipients + */ + public function getReplyTo(): array; + + /** + * Get Sender. + * + * @return EmailAddress[] Empty array in case message has no Sender: recipients + */ + public function getSender(): array; + + /** + * Get Return-Path. + * + * @return EmailAddress[] Empty array in case message has no Return-Path: recipients + */ + public function getReturnPath(): array; + + /** + * Get date (from headers). + * + * @return null|\DateTimeImmutable + */ + public function getDate(): ?\DateTimeImmutable; + + /** + * Get message size (from headers). + * + * @return null|int|string + */ + public function getSize(); + + /** + * Get message subject (from headers). + * + * @return null|string + */ + public function getSubject(): ?string; + + /** + * Get message In-Reply-To (from headers). + * + * @return array + */ + public function getInReplyTo(): array; + + /** + * Get message References (from headers). + * + * @return array + */ + public function getReferences(): array; + + /** + * Get body HTML. + * + * @return null|string Null if message has no HTML message part + */ + public function getBodyHtml(): ?string; + + /** + * Get body text. + * + * @return null|string + */ + public function getBodyText(): ?string; + + /** + * Get attachments (if any) linked to this e-mail. + * + * @return AttachmentInterface[] + */ + public function getAttachments(): array; + + /** + * Does this message have attachments? + * + * @return bool + */ + public function hasAttachments(): bool; +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php new file mode 100644 index 00000000..3f3788a4 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php @@ -0,0 +1,94 @@ +mailbox = $mailbox; + $this->hostname = $hostname; + $this->name = $name; + + if (null !== $hostname) { + $this->address = $mailbox . '@' . $hostname; + } + } + + /** + * @return null|string + */ + public function getAddress() + { + return $this->address; + } + + /** + * Returns address with person name. + * + * @return string + */ + public function getFullAddress(): string + { + $address = \sprintf('%s@%s', $this->mailbox, $this->hostname); + if (null !== $this->name) { + $address = \sprintf('"%s" <%s>', \addcslashes($this->name, '"'), $address); + } + + return $address; + } + + /** + * @return string + */ + public function getMailbox(): string + { + return $this->mailbox; + } + + /** + * @return null|string + */ + public function getHostname() + { + return $this->hostname; + } + + /** + * @return null|string + */ + public function getName() + { + return $this->name; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php new file mode 100644 index 00000000..1dfb8fd6 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php @@ -0,0 +1,81 @@ +headers) { + $this->headers = new Headers(\imap_rfc822_parse_headers($this->getRawHeaders())); + } + + return $this->headers; + } + + /** + * Get raw message headers. + * + * @return string + */ + public function getRawHeaders(): string + { + if (null === $this->rawHeaders) { + $rawHeaders = \explode("\r\n\r\n", $this->getRawMessage(), 2); + $this->rawHeaders = \current($rawHeaders); + } + + return $this->rawHeaders; + } + + /** + * Get the raw message, including all headers, parts, etc. unencoded and unparsed. + * + * @return string the raw message + */ + public function getRawMessage(): string + { + if (null === $this->rawMessage) { + $this->rawMessage = $this->doGetContent($this->getPartNumber()); + } + + return $this->rawMessage; + } + + /** + * Get content part number. + * + * @return string + */ + protected function getContentPartNumber(): string + { + $partNumber = $this->getPartNumber(); + if (0 === \count($this->getParts())) { + $partNumber .= '.1'; + } + + return $partNumber; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php new file mode 100644 index 00000000..c685edf9 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php @@ -0,0 +1,9 @@ + $value) { + $this[$key] = $this->parseHeader($key, $value); + } + } + + /** + * Get header. + * + * @param string $key + * + * @return null|string + */ + public function get(string $key) + { + return parent::get(\strtolower($key)); + } + + /** + * Parse header. + * + * @param string $key + * @param mixed $value + * + * @return mixed + */ + private function parseHeader(string $key, $value) + { + switch ($key) { + case 'msgno': + return (int) $value; + case 'from': + case 'to': + case 'cc': + case 'bcc': + case 'reply_to': + case 'sender': + case 'return_path': + foreach ($value as $address) { + if (isset($address->mailbox)) { + $address->host = $address->host ?? null; + $address->personal = isset($address->personal) ? $this->decode($address->personal) : null; + } + } + + return $value; + case 'date': + case 'subject': + return $this->decode($value); + } + + return $value; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php new file mode 100644 index 00000000..bb2a66cb --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php @@ -0,0 +1,86 @@ + 'name', + 'filename*' => 'filename', + ]; + + /** + * @param array $parameters + */ + public function __construct(array $parameters = []) + { + parent::__construct(); + + $this->add($parameters); + } + + /** + * @param array $parameters + */ + public function add(array $parameters = []): void + { + foreach ($parameters as $parameter) { + $key = \strtolower($parameter->attribute); + if (isset(self::$attachmentCustomKeys[$key])) { + $key = self::$attachmentCustomKeys[$key]; + } + $value = $this->decode($parameter->value); + $this[$key] = $value; + } + } + + /** + * @param string $key + * + * @return mixed + */ + public function get(string $key) + { + return $this[$key] ?? null; + } + + /** + * Decode value. + * + * @param string $value + * + * @return string + */ + final protected function decode(string $value): string + { + $parts = \imap_mime_header_decode($value); + if (!\is_array($parts)) { + return $value; + } + + $decoded = ''; + foreach ($parts as $part) { + $text = $part->text; + if ('default' !== $part->charset) { + $text = Transcoder::decode($text, $part->charset); + } + // RFC2231 + if (1 === \preg_match('/^(?[^\']+)\'[^\']*?\'(?.+)$/', $text, $matches)) { + $hasInvalidChars = \preg_match('#[^%a-zA-Z0-9\-_\.\+]#', $matches['urltext']); + $hasEscapedChars = \preg_match('#%[a-zA-Z0-9]{2}#', $matches['urltext']); + if (!$hasInvalidChars && $hasEscapedChars) { + $text = Transcoder::decode(\urldecode($matches['urltext']), $matches['encoding']); + } + } + + $decoded .= $text; + } + + return $decoded; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php new file mode 100644 index 00000000..d5f63699 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php @@ -0,0 +1,130 @@ + 'Shift_JIS', + '129' => 'EUC-KR', + '134' => 'GB2312', + '136' => 'Big5', + '161' => 'windows-1253', + '162' => 'windows-1254', + '177' => 'windows-1255', + '178' => 'windows-1256', + '186' => 'windows-1257', + '204' => 'windows-1251', + '222' => 'windows-874', + '238' => 'windows-1250', + '5601' => 'EUC-KR', + '646' => 'us-ascii', + '850' => 'IBM850', + '852' => 'IBM852', + '855' => 'IBM855', + '857' => 'IBM857', + '862' => 'IBM862', + '864' => 'IBM864', + '864i' => 'IBM864i', + '866' => 'IBM866', + 'ansi-1251' => 'windows-1251', + 'ansi_x3.4-1968' => 'us-ascii', + 'arabic' => 'ISO-8859-6', + 'ascii' => 'us-ascii', + 'asmo-708' => 'ISO-8859-6', + 'big5-hkscs' => 'Big5', + 'chinese' => 'GB2312', + 'cn-big5' => 'Big5', + 'cns11643' => 'x-euc-tw', + 'cp-866' => 'IBM866', + 'cp1250' => 'windows-1250', + 'cp1251' => 'windows-1251', + 'cp1252' => 'windows-1252', + 'cp1253' => 'windows-1253', + 'cp1254' => 'windows-1254', + 'cp1255' => 'windows-1255', + 'cp1256' => 'windows-1256', + 'cp1257' => 'windows-1257', + 'cp1258' => 'windows-1258', + 'cp819' => 'ISO-8859-1', + 'cp850' => 'IBM850', + 'cp852' => 'IBM852', + 'cp855' => 'IBM855', + 'cp857' => 'IBM857', + 'cp862' => 'IBM862', + 'cp864' => 'IBM864', + 'cp864i' => 'IBM864i', + 'cp866' => 'IBM866', + 'cp932' => 'Shift_JIS', + 'csbig5' => 'Big5', + 'cseucjpkdfmtjapanese' => 'EUC-JP', + 'cseuckr' => 'EUC-KR', + 'cseucpkdfmtjapanese' => 'EUC-JP', + 'csgb2312' => 'GB2312', + 'csibm850' => 'IBM850', + 'csibm852' => 'IBM852', + 'csibm855' => 'IBM855', + 'csibm857' => 'IBM857', + 'csibm862' => 'IBM862', + 'csibm864' => 'IBM864', + 'csibm864i' => 'IBM864i', + 'csibm866' => 'IBM866', + 'csiso103t618bit' => 'T.61-8bit', + 'csiso111ecmacyrillic' => 'ISO-IR-111', + 'csiso2022jp' => 'ISO-2022-JP', + 'csiso2022jp2' => 'ISO-2022-JP', + 'csiso2022kr' => 'ISO-2022-KR', + 'csiso58gb231280' => 'GB2312', + 'csiso88596e' => 'ISO-8859-6-E', + 'csiso88596i' => 'ISO-8859-6-I', + 'csiso88598e' => 'ISO-8859-8-E', + 'csiso88598i' => 'ISO-8859-8-I', + 'csisolatin1' => 'ISO-8859-1', + 'csisolatin2' => 'ISO-8859-2', + 'csisolatin3' => 'ISO-8859-3', + 'csisolatin4' => 'ISO-8859-4', + 'csisolatin5' => 'ISO-8859-9', + 'csisolatin6' => 'ISO-8859-10', + 'csisolatin9' => 'ISO-8859-15', + 'csisolatinarabic' => 'ISO-8859-6', + 'csisolatincyrillic' => 'ISO-8859-5', + 'csisolatingreek' => 'ISO-8859-7', + 'csisolatinhebrew' => 'ISO-8859-8', + 'cskoi8r' => 'KOI8-R', + 'csksc56011987' => 'EUC-KR', + 'csmacintosh' => 'x-mac-roman', + 'csshiftjis' => 'Shift_JIS', + 'csueckr' => 'EUC-KR', + 'csunicode' => 'UTF-16BE', + 'csunicode11' => 'UTF-16BE', + 'csunicode11utf7' => 'UTF-7', + 'csunicodeascii' => 'UTF-16BE', + 'csunicodelatin1' => 'UTF-16BE', + 'csviqr' => 'VIQR', + 'csviscii' => 'VISCII', + 'cyrillic' => 'ISO-8859-5', + 'dos-874' => 'windows-874', + 'ecma-114' => 'ISO-8859-6', + 'ecma-118' => 'ISO-8859-7', + 'ecma-cyrillic' => 'ISO-IR-111', + 'elot_928' => 'ISO-8859-7', + 'gb_2312' => 'GB2312', + 'gb_2312-80' => 'GB2312', + 'gbk' => 'x-gbk', + 'greek' => 'ISO-8859-7', + 'greek8' => 'ISO-8859-7', + 'hebrew' => 'ISO-8859-8', + 'ibm-864' => 'IBM864', + 'ibm-864i' => 'IBM864i', + 'ibm819' => 'ISO-8859-1', + 'ibm874' => 'windows-874', + 'iso-10646' => 'UTF-16BE', + 'iso-10646-j-1' => 'UTF-16BE', + 'iso-10646-ucs-2' => 'UTF-16BE', + 'iso-10646-ucs-4' => 'UTF-32BE', + 'iso-10646-ucs-basic' => 'UTF-16BE', + 'iso-10646-unicode-latin1' => 'UTF-16BE', + 'iso-2022-cn-ext' => 'ISO-2022-CN', + 'iso-2022-jp-2' => 'ISO-2022-JP', + 'iso-8859-8i' => 'ISO-8859-8-I', + 'iso-ir-100' => 'ISO-8859-1', + 'iso-ir-101' => 'ISO-8859-2', + 'iso-ir-103' => 'T.61-8bit', + 'iso-ir-109' => 'ISO-8859-3', + 'iso-ir-110' => 'ISO-8859-4', + 'iso-ir-126' => 'ISO-8859-7', + 'iso-ir-127' => 'ISO-8859-6', + 'iso-ir-138' => 'ISO-8859-8', + 'iso-ir-144' => 'ISO-8859-5', + 'iso-ir-148' => 'ISO-8859-9', + 'iso-ir-149' => 'EUC-KR', + 'iso-ir-157' => 'ISO-8859-10', + 'iso-ir-58' => 'GB2312', + 'iso8859-1' => 'ISO-8859-1', + 'iso8859-10' => 'ISO-8859-10', + 'iso8859-11' => 'ISO-8859-11', + 'iso8859-13' => 'ISO-8859-13', + 'iso8859-14' => 'ISO-8859-14', + 'iso8859-15' => 'ISO-8859-15', + 'iso8859-2' => 'ISO-8859-2', + 'iso8859-3' => 'ISO-8859-3', + 'iso8859-4' => 'ISO-8859-4', + 'iso8859-5' => 'ISO-8859-5', + 'iso8859-6' => 'ISO-8859-6', + 'iso8859-7' => 'ISO-8859-7', + 'iso8859-8' => 'ISO-8859-8', + 'iso8859-9' => 'ISO-8859-9', + 'iso88591' => 'ISO-8859-1', + 'iso885910' => 'ISO-8859-10', + 'iso885911' => 'ISO-8859-11', + 'iso885912' => 'ISO-8859-12', + 'iso885913' => 'ISO-8859-13', + 'iso885914' => 'ISO-8859-14', + 'iso885915' => 'ISO-8859-15', + 'iso88592' => 'ISO-8859-2', + 'iso88593' => 'ISO-8859-3', + 'iso88594' => 'ISO-8859-4', + 'iso88595' => 'ISO-8859-5', + 'iso88596' => 'ISO-8859-6', + 'iso88597' => 'ISO-8859-7', + 'iso88598' => 'ISO-8859-8', + 'iso88599' => 'ISO-8859-9', + 'iso_8859-1' => 'ISO-8859-1', + 'iso_8859-15' => 'ISO-8859-15', + 'iso_8859-1:1987' => 'ISO-8859-1', + 'iso_8859-2' => 'ISO-8859-2', + 'iso_8859-2:1987' => 'ISO-8859-2', + 'iso_8859-3' => 'ISO-8859-3', + 'iso_8859-3:1988' => 'ISO-8859-3', + 'iso_8859-4' => 'ISO-8859-4', + 'iso_8859-4:1988' => 'ISO-8859-4', + 'iso_8859-5' => 'ISO-8859-5', + 'iso_8859-5:1988' => 'ISO-8859-5', + 'iso_8859-6' => 'ISO-8859-6', + 'iso_8859-6:1987' => 'ISO-8859-6', + 'iso_8859-7' => 'ISO-8859-7', + 'iso_8859-7:1987' => 'ISO-8859-7', + 'iso_8859-8' => 'ISO-8859-8', + 'iso_8859-8:1988' => 'ISO-8859-8', + 'iso_8859-9' => 'ISO-8859-9', + 'iso_8859-9:1989' => 'ISO-8859-9', + 'koi' => 'KOI8-R', + 'koi8' => 'KOI8-R', + 'koi8-ru' => 'KOI8-U', + 'koi8_r' => 'KOI8-R', + 'korean' => 'EUC-KR', + 'ks_c_5601-1987' => 'EUC-KR', + 'ks_c_5601-1989' => 'EUC-KR', + 'ksc5601' => 'EUC-KR', + 'ksc_5601' => 'EUC-KR', + 'l1' => 'ISO-8859-1', + 'l2' => 'ISO-8859-2', + 'l3' => 'ISO-8859-3', + 'l4' => 'ISO-8859-4', + 'l5' => 'ISO-8859-9', + 'l6' => 'ISO-8859-10', + 'l9' => 'ISO-8859-15', + 'latin1' => 'ISO-8859-1', + 'latin2' => 'ISO-8859-2', + 'latin3' => 'ISO-8859-3', + 'latin4' => 'ISO-8859-4', + 'latin5' => 'ISO-8859-9', + 'latin6' => 'ISO-8859-10', + 'logical' => 'ISO-8859-8-I', + 'mac' => 'x-mac-roman', + 'macintosh' => 'x-mac-roman', + 'ms932' => 'Shift_JIS', + 'ms_kanji' => 'Shift_JIS', + 'shift-jis' => 'Shift_JIS', + 'sjis' => 'Shift_JIS', + 'sun_eu_greek' => 'ISO-8859-7', + 't.61' => 'T.61-8bit', + 'tis620' => 'TIS-620', + 'unicode-1-1-utf-7' => 'UTF-7', + 'unicode-1-1-utf-8' => 'UTF-8', + 'unicode-2-0-utf-7' => 'UTF-7', + 'visual' => 'ISO-8859-8', + 'windows-31j' => 'Shift_JIS', + 'windows-949' => 'EUC-KR', + 'x-cp1250' => 'windows-1250', + 'x-cp1251' => 'windows-1251', + 'x-cp1252' => 'windows-1252', + 'x-cp1253' => 'windows-1253', + 'x-cp1254' => 'windows-1254', + 'x-cp1255' => 'windows-1255', + 'x-cp1256' => 'windows-1256', + 'x-cp1257' => 'windows-1257', + 'x-cp1258' => 'windows-1258', + 'x-euc-jp' => 'EUC-JP', + 'x-iso-10646-ucs-2-be' => 'UTF-16BE', + 'x-iso-10646-ucs-2-le' => 'UTF-16LE', + 'x-iso-10646-ucs-4-be' => 'UTF-32BE', + 'x-iso-10646-ucs-4-le' => 'UTF-32LE', + 'x-sjis' => 'Shift_JIS', + 'x-unicode-2-0-utf-7' => 'UTF-7', + 'x-x-big5' => 'Big5', + 'zh_cn.euc' => 'GB2312', + 'zh_tw-big5' => 'Big5', + 'zh_tw-euc' => 'x-euc-tw', + ]; + + /** + * Decode text to UTF-8. + * + * @param string $text Text to decode + * @param string $fromCharset Original charset + * + * @return string + */ + public static function decode(string $text, string $fromCharset): string + { + static $utf8Aliases = [ + 'unicode-1-1-utf-8' => true, + 'utf8' => true, + 'utf-8' => true, + 'UTF8' => true, + 'UTF-8' => true, + ]; + + if (isset($utf8Aliases[$fromCharset])) { + return $text; + } + + $originalFromCharset = $fromCharset; + $lowercaseFromCharset = \strtolower($fromCharset); + if (isset(self::$charsetAliases[$lowercaseFromCharset])) { + $fromCharset = self::$charsetAliases[$lowercaseFromCharset]; + } + + \set_error_handler(function () {}); + + $iconvDecodedText = \iconv($fromCharset, 'UTF-8', $text); + if (false === $iconvDecodedText) { + $iconvDecodedText = \iconv($originalFromCharset, 'UTF-8', $text); + } + + \restore_error_handler(); + + if (false !== $iconvDecodedText) { + return $iconvDecodedText; + } + + $errorMessage = null; + $errorNumber = 0; + \set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) { + $errorMessage = $message; + $errorNumber = $nr; + }); + + $decodedText = \mb_convert_encoding($text, 'UTF-8', $fromCharset); + + \restore_error_handler(); + + if (null !== $errorMessage) { + throw new UnsupportedCharsetException(\sprintf( + 'Unsupported charset "%s"%s: %s', + $originalFromCharset, + ($fromCharset !== $originalFromCharset) ? \sprintf(' (alias found: "%s")', $fromCharset) : '', + $errorMessage + ), $errorNumber); + } + + return $decodedText; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php new file mode 100644 index 00000000..d14ce716 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php @@ -0,0 +1,120 @@ +resource = $resource; + + parent::__construct($messageNumbers); + } + + /** + * Get current message. + * + * @return MessageInterface + */ + public function current(): MessageInterface + { + $current = parent::current(); + if (!\is_int($current)) { + throw new Exception\OutOfBoundsException(\sprintf( + 'The current value "%s" isn\'t an integer and doesn\'t represent a message;' + . ' try to cycle this "%s" with a native php function like foreach or with the method getArrayCopy(),' + . ' or check it by calling the methods valid().', + \is_object($current) ? \get_class($current) : \gettype($current), + static::class + )); + } + + return new Message($this->resource, $current); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php new file mode 100644 index 00000000..f1b9fd92 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php @@ -0,0 +1,15 @@ +date = $date; + $this->dateFormat = $dateFormat; + } + + /** + * Converts the condition to a string that can be sent to the IMAP server. + * + * @return string + */ + final public function toString(): string + { + return \sprintf('%s "%s"', $this->getKeyword(), $this->date->format($this->dateFormat)); + } + + /** + * Returns the keyword that the condition represents. + * + * @return string + */ + abstract protected function getKeyword(): string; +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php new file mode 100644 index 00000000..833ea3c3 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php @@ -0,0 +1,46 @@ +text = $text; + } + + /** + * Converts the condition to a string that can be sent to the IMAP server. + * + * @return string + */ + final public function toString(): string + { + return \sprintf('%s "%s"', $this->getKeyword(), $this->text); + } + + /** + * Returns the keyword that the condition represents. + * + * @return string + */ + abstract protected function getKeyword(): string; +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php new file mode 100644 index 00000000..e4c0a97d --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php @@ -0,0 +1,18 @@ +addCondition($condition); + } + } + + /** + * Adds a new condition to the expression. + * + * @param ConditionInterface $condition the condition to be added + */ + private function addCondition(ConditionInterface $condition) + { + $this->conditions[] = $condition; + } + + /** + * Returns the keyword that the condition represents. + * + * @return string + */ + public function toString(): string + { + $conditions = \array_map(function (ConditionInterface $condition) { + return $condition->toString(); + }, $this->conditions); + + return \sprintf('( %s )', \implode(' OR ', $conditions)); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php new file mode 100644 index 00000000..72da06db --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php @@ -0,0 +1,34 @@ +expression = $expression; + } + + /** + * @return string + */ + public function toString(): string + { + return $this->expression; + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php new file mode 100644 index 00000000..90ec5579 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php @@ -0,0 +1,24 @@ +conditions[] = $condition; + + return $this; + } + + /** + * Converts the expression to a string that can be sent to the IMAP server. + * + * @return string + */ + public function toString(): string + { + $conditions = \array_map(function (ConditionInterface $condition) { + return $condition->toString(); + }, $this->conditions); + + return \implode(' ', $conditions); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php b/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php new file mode 100644 index 00000000..361ca2aa --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php @@ -0,0 +1,138 @@ +hostname = $hostname; + $this->port = $port; + $this->flags = $flags ? '/' . \ltrim($flags, '/') : ''; + $this->parameters = $parameters; + $this->options = $options; + $this->retries = $retries; + } + + /** + * Authenticate connection. + * + * @param string $username Username + * @param string $password Password + * + * @throws AuthenticationFailedException + * + * @return ConnectionInterface + */ + public function authenticate(string $username, string $password): ConnectionInterface + { + $errorMessage = null; + $errorNumber = 0; + \set_error_handler(function ($nr, $message) use (&$errorMessage, &$errorNumber) { + $errorMessage = $message; + $errorNumber = $nr; + }); + + $resource = \imap_open( + $this->getServerString(), + $username, + $password, + $this->options, + $this->retries, + $this->parameters + ); + + \restore_error_handler(); + + if (false === $resource || null !== $errorMessage) { + throw new AuthenticationFailedException(\sprintf( + 'Authentication failed for user "%s"%s', + $username, + null !== $errorMessage ? ': ' . $errorMessage : '' + ), $errorNumber); + } + + $check = \imap_check($resource); + $mailbox = $check->Mailbox; + $connection = \substr($mailbox, 0, \strpos($mailbox, '}') + 1); + + // These are necessary to get rid of PHP throwing IMAP errors + \imap_errors(); + \imap_alerts(); + + return new Connection(new ImapResource($resource), $connection); + } + + /** + * Glues hostname, port and flags and returns result. + * + * @return string + */ + private function getServerString(): string + { + return \sprintf( + '{%s%s%s}', + $this->hostname, + '' !== $this->port ? ':' . $this->port : '', + $this->flags + ); + } +} diff --git a/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php b/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php new file mode 100644 index 00000000..f67dd6c8 --- /dev/null +++ b/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php @@ -0,0 +1,21 @@ +minify(); +} catch (Exception $e) { + fwrite(STDERR, $e->getMessage(), PHP_EOL); + exit(1); +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/bin/minifyjs b/data/web/inc/lib/vendor/matthiasmullie/minify/bin/minifyjs new file mode 100755 index 00000000..4cbe63ff --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/bin/minifyjs @@ -0,0 +1,45 @@ +#!/usr/bin/env php +minify(); +} catch (Exception $e) { + fwrite(STDERR, $e->getMessage(), PHP_EOL); + exit(1); +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json b/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json new file mode 100644 index 00000000..6d81b4f9 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/composer.json @@ -0,0 +1,38 @@ +{ + "name": "matthiasmullie/minify", + "type": "library", + "description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.", + "keywords": ["minify", "minifier", "css", "js", "javascript"], + "homepage": "http://www.minifier.org", + "license": "MIT", + "authors": [ + { + "name": "Matthias Mullie", + "homepage": "http://www.mullie.eu", + "email": "minify@mullie.eu", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.0", + "ext-pcre": "*", + "matthiasmullie/path-converter": "~1.1" + }, + "require-dev": { + "matthiasmullie/scrapbook": "~1.0", + "phpunit/phpunit": "~4.8", + "friendsofphp/php-cs-fixer": "~2.0" + }, + "suggest": { + "psr/cache-implementation": "Cache implementation to use with Minify::cache" + }, + "autoload": { + "psr-4": { + "MatthiasMullie\\Minify\\": "src/" + } + }, + "bin": [ + "bin/minifycss", + "bin/minifyjs" + ] +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_after.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_after.txt new file mode 100644 index 00000000..5c8cba7f --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_after.txt @@ -0,0 +1,7 @@ +in +public +extends +private +protected +implements +instanceof \ No newline at end of file diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_before.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_before.txt new file mode 100644 index 00000000..5abf3579 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_before.txt @@ -0,0 +1,26 @@ +do +in +let +new +var +case +else +enum +void +with +class +const +yield +delete +export +import +public +static +typeof +extends +package +private +function +protected +implements +instanceof \ No newline at end of file diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_reserved.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_reserved.txt new file mode 100644 index 00000000..2a3ad3c0 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/keywords_reserved.txt @@ -0,0 +1,63 @@ +do +if +in +for +let +new +try +var +case +else +enum +eval +null +this +true +void +with +break +catch +class +const +false +super +throw +while +yield +delete +export +import +public +return +static +switch +typeof +default +extends +finally +package +private +continue +debugger +function +arguments +interface +protected +implements +instanceof +abstract +boolean +byte +char +double +final +float +goto +int +long +native +short +synchronized +throws +transient +volatile \ No newline at end of file diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators.txt new file mode 100644 index 00000000..e66229ae --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators.txt @@ -0,0 +1,46 @@ ++ +- +* +/ +% += ++= +-= +*= +/= +%= +<<= +>>= +>>>= +&= +^= +|= +& +| +^ +~ +<< +>> +>>> +== +=== +!= +!== +> +< +>= +<= +&& +|| +! +. +[ +] +? +: +, +; +( +) +{ +} \ No newline at end of file diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_after.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_after.txt new file mode 100644 index 00000000..71a9b709 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_after.txt @@ -0,0 +1,43 @@ ++ +- +* +/ +% += ++= +-= +*= +/= +%= +<<= +>>= +>>>= +&= +^= +|= +& +| +^ +<< +>> +>>> +== +=== +!= +!== +> +< +>= +<= +&& +|| +. +[ +] +? +: +, +; +( +) +} \ No newline at end of file diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_before.txt b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_before.txt new file mode 100644 index 00000000..ff50d870 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/data/js/operators_before.txt @@ -0,0 +1,43 @@ ++ +- +* +/ +% += ++= +-= +*= +/= +%= +<<= +>>= +>>>= +&= +^= +|= +& +| +^ +~ +<< +>> +>>> +== +=== +!= +!== +> +< +>= +<= +&& +|| +! +. +[ +? +: +, +; +( +{ diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/docker-compose.yml b/data/web/inc/lib/vendor/matthiasmullie/minify/docker-compose.yml new file mode 100644 index 00000000..5413e24b --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/docker-compose.yml @@ -0,0 +1,31 @@ +version: '2.1' +services: + php: + build: + context: . + dockerfile: Dockerfile + volumes: + - ./src:/var/www/src + - ./data:/var/www/data + - ./tests:/var/www/tests + - ./phpunit.xml.dist:/var/www/phpunit.xml.dist + '7.2': + extends: php + build: + args: + version: 7.2-cli + '7.1': + extends: php + build: + args: + version: 7.1-cli + '7.0': + extends: php + build: + args: + version: 7.0-cli + '5.6': + extends: php + build: + args: + version: 5.6-cli diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php new file mode 100644 index 00000000..e5a46690 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/CSS.php @@ -0,0 +1,751 @@ + + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ + +namespace MatthiasMullie\Minify; + +use MatthiasMullie\Minify\Exceptions\FileImportException; +use MatthiasMullie\PathConverter\ConverterInterface; +use MatthiasMullie\PathConverter\Converter; + +/** + * CSS minifier + * + * Please report bugs on https://github.com/matthiasmullie/minify/issues + * + * @package Minify + * @author Matthias Mullie + * @author Tijs Verkoyen + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +class CSS extends Minify +{ + /** + * @var int maximum inport size in kB + */ + protected $maxImportSize = 5; + + /** + * @var string[] valid import extensions + */ + protected $importExtensions = array( + 'gif' => 'data:image/gif', + 'png' => 'data:image/png', + 'jpe' => 'data:image/jpeg', + 'jpg' => 'data:image/jpeg', + 'jpeg' => 'data:image/jpeg', + 'svg' => 'data:image/svg+xml', + 'woff' => 'data:application/x-font-woff', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'xbm' => 'image/x-xbitmap', + ); + + /** + * Set the maximum size if files to be imported. + * + * Files larger than this size (in kB) will not be imported into the CSS. + * Importing files into the CSS as data-uri will save you some connections, + * but we should only import relatively small decorative images so that our + * CSS file doesn't get too bulky. + * + * @param int $size Size in kB + */ + public function setMaxImportSize($size) + { + $this->maxImportSize = $size; + } + + /** + * Set the type of extensions to be imported into the CSS (to save network + * connections). + * Keys of the array should be the file extensions & respective values + * should be the data type. + * + * @param string[] $extensions Array of file extensions + */ + public function setImportExtensions(array $extensions) + { + $this->importExtensions = $extensions; + } + + /** + * Move any import statements to the top. + * + * @param string $content Nearly finished CSS content + * + * @return string + */ + protected function moveImportsToTop($content) + { + if (preg_match_all('/(;?)(@import (?url\()?(?P["\']?).+?(?P=quotes)(?(url)\)));?/', $content, $matches)) { + // remove from content + foreach ($matches[0] as $import) { + $content = str_replace($import, '', $content); + } + + // add to top + $content = implode(';', $matches[2]).';'.trim($content, ';'); + } + + return $content; + } + + /** + * Combine CSS from import statements. + * + * @import's will be loaded and their content merged into the original file, + * to save HTTP requests. + * + * @param string $source The file to combine imports for + * @param string $content The CSS content to combine imports for + * @param string[] $parents Parent paths, for circular reference checks + * + * @return string + * + * @throws FileImportException + */ + protected function combineImports($source, $content, $parents) + { + $importRegexes = array( + // @import url(xxx) + '/ + # import statement + @import + + # whitespace + \s+ + + # open url() + url\( + + # (optional) open path enclosure + (?P["\']?) + + # fetch path + (?P.+?) + + # (optional) close path enclosure + (?P=quotes) + + # close url() + \) + + # (optional) trailing whitespace + \s* + + # (optional) media statement(s) + (?P[^;]*) + + # (optional) trailing whitespace + \s* + + # (optional) closing semi-colon + ;? + + /ix', + + // @import 'xxx' + '/ + + # import statement + @import + + # whitespace + \s+ + + # open path enclosure + (?P["\']) + + # fetch path + (?P.+?) + + # close path enclosure + (?P=quotes) + + # (optional) trailing whitespace + \s* + + # (optional) media statement(s) + (?P[^;]*) + + # (optional) trailing whitespace + \s* + + # (optional) closing semi-colon + ;? + + /ix', + ); + + // find all relative imports in css + $matches = array(); + foreach ($importRegexes as $importRegex) { + if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) { + $matches = array_merge($matches, $regexMatches); + } + } + + $search = array(); + $replace = array(); + + // loop the matches + foreach ($matches as $match) { + // get the path for the file that will be imported + $importPath = dirname($source).'/'.$match['path']; + + // only replace the import with the content if we can grab the + // content of the file + if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) { + continue; + } + + // check if current file was not imported previously in the same + // import chain. + if (in_array($importPath, $parents)) { + throw new FileImportException('Failed to import file "'.$importPath.'": circular reference detected.'); + } + + // grab referenced file & minify it (which may include importing + // yet other @import statements recursively) + $minifier = new static($importPath); + $minifier->setMaxImportSize($this->maxImportSize); + $minifier->setImportExtensions($this->importExtensions); + $importContent = $minifier->execute($source, $parents); + + // check if this is only valid for certain media + if (!empty($match['media'])) { + $importContent = '@media '.$match['media'].'{'.$importContent.'}'; + } + + // add to replacement array + $search[] = $match[0]; + $replace[] = $importContent; + } + + // replace the import statements + return str_replace($search, $replace, $content); + } + + /** + * Import files into the CSS, base64-ized. + * + * @url(image.jpg) images will be loaded and their content merged into the + * original file, to save HTTP requests. + * + * @param string $source The file to import files for + * @param string $content The CSS content to import files for + * + * @return string + */ + protected function importFiles($source, $content) + { + $regex = '/url\((["\']?)(.+?)\\1\)/i'; + if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { + $search = array(); + $replace = array(); + + // loop the matches + foreach ($matches as $match) { + $extension = substr(strrchr($match[2], '.'), 1); + if ($extension && !array_key_exists($extension, $this->importExtensions)) { + continue; + } + + // get the path for the file that will be imported + $path = $match[2]; + $path = dirname($source).'/'.$path; + + // only replace the import with the content if we're able to get + // the content of the file, and it's relatively small + if ($this->canImportFile($path) && $this->canImportBySize($path)) { + // grab content && base64-ize + $importContent = $this->load($path); + $importContent = base64_encode($importContent); + + // build replacement + $search[] = $match[0]; + $replace[] = 'url('.$this->importExtensions[$extension].';base64,'.$importContent.')'; + } + } + + // replace the import statements + $content = str_replace($search, $replace, $content); + } + + return $content; + } + + /** + * Minify the data. + * Perform CSS optimizations. + * + * @param string[optional] $path Path to write the data to + * @param string[] $parents Parent paths, for circular reference checks + * + * @return string The minified data + */ + public function execute($path = null, $parents = array()) + { + $content = ''; + + // loop CSS data (raw data and files) + foreach ($this->data as $source => $css) { + /* + * Let's first take out strings & comments, since we can't just + * remove whitespace anywhere. If whitespace occurs inside a string, + * we should leave it alone. E.g.: + * p { content: "a test" } + */ + $this->extractStrings(); + $this->stripComments(); + $this->extractCalcs(); + $css = $this->replace($css); + + $css = $this->stripWhitespace($css); + $css = $this->shortenColors($css); + $css = $this->shortenZeroes($css); + $css = $this->shortenFontWeights($css); + $css = $this->stripEmptyTags($css); + + // restore the string we've extracted earlier + $css = $this->restoreExtractedData($css); + + $source = is_int($source) ? '' : $source; + $parents = $source ? array_merge($parents, array($source)) : $parents; + $css = $this->combineImports($source, $css, $parents); + $css = $this->importFiles($source, $css); + + /* + * If we'll save to a new path, we'll have to fix the relative paths + * to be relative no longer to the source file, but to the new path. + * If we don't write to a file, fall back to same path so no + * conversion happens (because we still want it to go through most + * of the move code, which also addresses url() & @import syntax...) + */ + $converter = $this->getPathConverter($source, $path ?: $source); + $css = $this->move($converter, $css); + + // combine css + $content .= $css; + } + + $content = $this->moveImportsToTop($content); + + return $content; + } + + /** + * Moving a css file should update all relative urls. + * Relative references (e.g. ../images/image.gif) in a certain css file, + * will have to be updated when a file is being saved at another location + * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper). + * + * @param ConverterInterface $converter Relative path converter + * @param string $content The CSS content to update relative urls for + * + * @return string + */ + protected function move(ConverterInterface $converter, $content) + { + /* + * Relative path references will usually be enclosed by url(). @import + * is an exception, where url() is not necessary around the path (but is + * allowed). + * This *could* be 1 regular expression, where both regular expressions + * in this array are on different sides of a |. But we're using named + * patterns in both regexes, the same name on both regexes. This is only + * possible with a (?J) modifier, but that only works after a fairly + * recent PCRE version. That's why I'm doing 2 separate regular + * expressions & combining the matches after executing of both. + */ + $relativeRegexes = array( + // url(xxx) + '/ + # open url() + url\( + + \s* + + # open path enclosure + (?P["\'])? + + # fetch path + (?P.+?) + + # close path enclosure + (?(quotes)(?P=quotes)) + + \s* + + # close url() + \) + + /ix', + + // @import "xxx" + '/ + # import statement + @import + + # whitespace + \s+ + + # we don\'t have to check for @import url(), because the + # condition above will already catch these + + # open path enclosure + (?P["\']) + + # fetch path + (?P.+?) + + # close path enclosure + (?P=quotes) + + /ix', + ); + + // find all relative urls in css + $matches = array(); + foreach ($relativeRegexes as $relativeRegex) { + if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) { + $matches = array_merge($matches, $regexMatches); + } + } + + $search = array(); + $replace = array(); + + // loop all urls + foreach ($matches as $match) { + // determine if it's a url() or an @import match + $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url'); + + $url = $match['path']; + if ($this->canImportByPath($url)) { + // attempting to interpret GET-params makes no sense, so let's discard them for awhile + $params = strrchr($url, '?'); + $url = $params ? substr($url, 0, -strlen($params)) : $url; + + // fix relative url + $url = $converter->convert($url); + + // now that the path has been converted, re-apply GET-params + $url .= $params; + } + + /* + * Urls with control characters above 0x7e should be quoted. + * According to Mozilla's parser, whitespace is only allowed at the + * end of unquoted urls. + * Urls with `)` (as could happen with data: uris) should also be + * quoted to avoid being confused for the url() closing parentheses. + * And urls with a # have also been reported to cause issues. + * Urls with quotes inside should also remain escaped. + * + * @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation + * @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378 + * @see https://github.com/matthiasmullie/minify/issues/193 + */ + $url = trim($url); + if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) { + $url = $match['quotes'] . $url . $match['quotes']; + } + + // build replacement + $search[] = $match[0]; + if ($type === 'url') { + $replace[] = 'url('.$url.')'; + } elseif ($type === 'import') { + $replace[] = '@import "'.$url.'"'; + } + } + + // replace urls + return str_replace($search, $replace, $content); + } + + /** + * Shorthand hex color codes. + * #FF0000 -> #F00. + * + * @param string $content The CSS content to shorten the hex color codes for + * + * @return string + */ + protected function shortenColors($content) + { + $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content); + + // remove alpha channel if it's pointless... + $content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content); + $content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content); + + $colors = array( + // we can shorten some even more by replacing them with their color name + '#F0FFFF' => 'azure', + '#F5F5DC' => 'beige', + '#A52A2A' => 'brown', + '#FF7F50' => 'coral', + '#FFD700' => 'gold', + '#808080' => 'gray', + '#008000' => 'green', + '#4B0082' => 'indigo', + '#FFFFF0' => 'ivory', + '#F0E68C' => 'khaki', + '#FAF0E6' => 'linen', + '#800000' => 'maroon', + '#000080' => 'navy', + '#808000' => 'olive', + '#CD853F' => 'peru', + '#FFC0CB' => 'pink', + '#DDA0DD' => 'plum', + '#800080' => 'purple', + '#F00' => 'red', + '#FA8072' => 'salmon', + '#A0522D' => 'sienna', + '#C0C0C0' => 'silver', + '#FFFAFA' => 'snow', + '#D2B48C' => 'tan', + '#FF6347' => 'tomato', + '#EE82EE' => 'violet', + '#F5DEB3' => 'wheat', + // or the other way around + 'WHITE' => '#fff', + 'BLACK' => '#000', + ); + + return preg_replace_callback( + '/(?<=[: ])('.implode(array_keys($colors), '|').')(?=[; }])/i', + function ($match) use ($colors) { + return $colors[strtoupper($match[0])]; + }, + $content + ); + } + + /** + * Shorten CSS font weights. + * + * @param string $content The CSS content to shorten the font weights for + * + * @return string + */ + protected function shortenFontWeights($content) + { + $weights = array( + 'normal' => 400, + 'bold' => 700, + ); + + $callback = function ($match) use ($weights) { + return $match[1].$weights[$match[2]]; + }; + + return preg_replace_callback('/(font-weight\s*:\s*)('.implode('|', array_keys($weights)).')(?=[;}])/', $callback, $content); + } + + /** + * Shorthand 0 values to plain 0, instead of e.g. -0em. + * + * @param string $content The CSS content to shorten the zero values for + * + * @return string + */ + protected function shortenZeroes($content) + { + // we don't want to strip units in `calc()` expressions: + // `5px - 0px` is valid, but `5px - 0` is not + // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but + // `10 * 0` is invalid + // we've extracted calcs earlier, so we don't need to worry about this + + // reusable bits of code throughout these regexes: + // before & after are used to make sure we don't match lose unintended + // 0-like values (e.g. in #000, or in http://url/1.0) + // units can be stripped from 0 values, or used to recognize non 0 + // values (where wa may be able to strip a .0 suffix) + $before = '(?<=[:(, ])'; + $after = '(?=[ ,);}])'; + $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)'; + + // strip units after zeroes (0px -> 0) + // NOTE: it should be safe to remove all units for a 0 value, but in + // practice, Webkit (especially Safari) seems to stumble over at least + // 0%, potentially other units as well. Only stripping 'px' for now. + // @see https://github.com/matthiasmullie/minify/issues/60 + $content = preg_replace('/'.$before.'(-?0*(\.0+)?)(?<=0)px'.$after.'/', '\\1', $content); + + // strip 0-digits (.0 -> 0) + $content = preg_replace('/'.$before.'\.0+'.$units.'?'.$after.'/', '0\\1', $content); + // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px + $content = preg_replace('/'.$before.'(-?[0-9]+\.[0-9]+)0+'.$units.'?'.$after.'/', '\\1\\2', $content); + // strip trailing 0: 50.00 -> 50, 50.00px -> 50px + $content = preg_replace('/'.$before.'(-?[0-9]+)\.0+'.$units.'?'.$after.'/', '\\1\\2', $content); + // strip leading 0: 0.1 -> .1, 01.1 -> 1.1 + $content = preg_replace('/'.$before.'(-?)0+([0-9]*\.[0-9]+)'.$units.'?'.$after.'/', '\\1\\2\\3', $content); + + // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0) + $content = preg_replace('/'.$before.'-?0+'.$units.'?'.$after.'/', '0\\1', $content); + + // IE doesn't seem to understand a unitless flex-basis value (correct - + // it goes against the spec), so let's add it in again (make it `%`, + // which is only 1 char: 0%, 0px, 0 anything, it's all just the same) + // @see https://developer.mozilla.org/nl/docs/Web/CSS/flex + $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content); + $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content); + + return $content; + } + + /** + * Strip empty tags from source code. + * + * @param string $content + * + * @return string + */ + protected function stripEmptyTags($content) + { + $content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content); + $content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content); + + return $content; + } + + /** + * Strip comments from source code. + */ + protected function stripComments() + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier) { + $count = count($minifier->extracted); + $placeholder = '/*'.$count.'*/'; + $minifier->extracted[$placeholder] = $match[0]; + + return $placeholder; + }; + $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); + + $this->registerPattern('/\/\*.*?\*\//s', ''); + } + + /** + * Strip whitespace. + * + * @param string $content The CSS content to strip the whitespace for + * + * @return string + */ + protected function stripWhitespace($content) + { + // remove leading & trailing whitespace + $content = preg_replace('/^\s*/m', '', $content); + $content = preg_replace('/\s*$/m', '', $content); + + // replace newlines with a single space + $content = preg_replace('/\s+/', ' ', $content); + + // remove whitespace around meta characters + // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex + $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content); + $content = preg_replace('/([\[(:>\+])\s+/', '$1', $content); + $content = preg_replace('/\s+([\]\)>\+])/', '$1', $content); + $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content); + + // whitespace around + and - can only be stripped inside some pseudo- + // classes, like `:nth-child(3+2n)` + // not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or + // selectors like `div.weird- p` + $pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type'); + $content = preg_replace('/:('.implode('|', $pseudos).')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content); + + // remove semicolon/whitespace followed by closing bracket + $content = str_replace(';}', '}', $content); + + return trim($content); + } + + /** + * Replace all `calc()` occurrences. + */ + protected function extractCalcs() + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier) { + $length = strlen($match[1]); + $expr = ''; + $opened = 0; + + for ($i = 0; $i < $length; $i++) { + $char = $match[1][$i]; + $expr .= $char; + if ($char === '(') { + $opened++; + } elseif ($char === ')' && --$opened === 0) { + break; + } + } + $rest = str_replace($expr, '', $match[1]); + $expr = trim(substr($expr, 1, -1)); + + $count = count($minifier->extracted); + $placeholder = 'calc('.$count.')'; + $minifier->extracted[$placeholder] = 'calc('.$expr.')'; + + return $placeholder.$rest; + }; + + $this->registerPattern('/calc(\(.+?)(?=$|;|calc\()/', $callback); + } + + /** + * Check if file is small enough to be imported. + * + * @param string $path The path to the file + * + * @return bool + */ + protected function canImportBySize($path) + { + return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024; + } + + /** + * Check if file a file can be imported, going by the path. + * + * @param string $path + * + * @return bool + */ + protected function canImportByPath($path) + { + return preg_match('/^(data:|https?:|\\/)/', $path) === 0; + } + + /** + * Return a converter to update relative paths to be relative to the new + * destination. + * + * @param string $source + * @param string $target + * + * @return ConverterInterface + */ + protected function getPathConverter($source, $target) + { + return new Converter($source, $target); + } +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exception.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exception.php new file mode 100644 index 00000000..d03898f0 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exception.php @@ -0,0 +1,20 @@ + + */ +namespace MatthiasMullie\Minify; + +/** + * Base Exception Class + * @deprecated Use Exceptions\BasicException instead + * + * @package Minify + * @author Matthias Mullie + */ +abstract class Exception extends \Exception +{ +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/BasicException.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/BasicException.php new file mode 100644 index 00000000..af5e81bc --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/BasicException.php @@ -0,0 +1,23 @@ + + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +namespace MatthiasMullie\Minify\Exceptions; + +use MatthiasMullie\Minify\Exception; + +/** + * Basic Exception Class + * + * @package Minify\Exception + * @author Matthias Mullie + */ +abstract class BasicException extends Exception +{ +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/FileImportException.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/FileImportException.php new file mode 100644 index 00000000..912a2c90 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/FileImportException.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +namespace MatthiasMullie\Minify\Exceptions; + +/** + * File Import Exception Class + * + * @package Minify\Exception + * @author Matthias Mullie + */ +class FileImportException extends BasicException +{ +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/IOException.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/IOException.php new file mode 100644 index 00000000..b172eb48 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/Exceptions/IOException.php @@ -0,0 +1,21 @@ + + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +namespace MatthiasMullie\Minify\Exceptions; + +/** + * IO Exception Class + * + * @package Minify\Exception + * @author Matthias Mullie + */ +class IOException extends BasicException +{ +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php b/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php new file mode 100644 index 00000000..92389cdd --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/minify/src/JS.php @@ -0,0 +1,612 @@ + + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +namespace MatthiasMullie\Minify; + +/** + * JavaScript Minifier Class + * + * Please report bugs on https://github.com/matthiasmullie/minify/issues + * + * @package Minify + * @author Matthias Mullie + * @author Tijs Verkoyen + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +class JS extends Minify +{ + /** + * Var-matching regex based on http://stackoverflow.com/a/9337047/802993. + * + * Note that regular expressions using that bit must have the PCRE_UTF8 + * pattern modifier (/u) set. + * + * @var string + */ + const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b'; + + /** + * Full list of JavaScript reserved words. + * Will be loaded from /data/js/keywords_reserved.txt. + * + * @see https://mathiasbynens.be/notes/reserved-keywords + * + * @var string[] + */ + protected $keywordsReserved = array(); + + /** + * List of JavaScript reserved words that accept a + * after them. Some end of lines are not the end of a statement, like with + * these keywords. + * + * E.g.: we shouldn't insert a ; after this else + * else + * console.log('this is quite fine') + * + * Will be loaded from /data/js/keywords_before.txt + * + * @var string[] + */ + protected $keywordsBefore = array(); + + /** + * List of JavaScript reserved words that accept a + * before them. Some end of lines are not the end of a statement, like when + * continued by one of these keywords on the newline. + * + * E.g.: we shouldn't insert a ; before this instanceof + * variable + * instanceof String + * + * Will be loaded from /data/js/keywords_after.txt + * + * @var string[] + */ + protected $keywordsAfter = array(); + + /** + * List of all JavaScript operators. + * + * Will be loaded from /data/js/operators.txt + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators + * + * @var string[] + */ + protected $operators = array(); + + /** + * List of JavaScript operators that accept a after + * them. Some end of lines are not the end of a statement, like with these + * operators. + * + * Note: Most operators are fine, we've only removed ++ and --. + * ++ & -- have to be joined with the value they're in-/decrementing. + * + * Will be loaded from /data/js/operators_before.txt + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators + * + * @var string[] + */ + protected $operatorsBefore = array(); + + /** + * List of JavaScript operators that accept a before + * them. Some end of lines are not the end of a statement, like when + * continued by one of these operators on the newline. + * + * Note: Most operators are fine, we've only removed ), ], ++, --, ! and ~. + * There can't be a newline separating ! or ~ and whatever it is negating. + * ++ & -- have to be joined with the value they're in-/decrementing. + * ) & ] are "special" in that they have lots or usecases. () for example + * is used for function calls, for grouping, in if () and for (), ... + * + * Will be loaded from /data/js/operators_after.txt + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators + * + * @var string[] + */ + protected $operatorsAfter = array(); + + /** + * {@inheritdoc} + */ + public function __construct() + { + call_user_func_array(array('parent', '__construct'), func_get_args()); + + $dataDir = __DIR__.'/../data/js/'; + $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES; + $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options); + $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options); + $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options); + $this->operators = file($dataDir.'operators.txt', $options); + $this->operatorsBefore = file($dataDir.'operators_before.txt', $options); + $this->operatorsAfter = file($dataDir.'operators_after.txt', $options); + } + + /** + * Minify the data. + * Perform JS optimizations. + * + * @param string[optional] $path Path to write the data to + * + * @return string The minified data + */ + public function execute($path = null) + { + $content = ''; + + /* + * Let's first take out strings, comments and regular expressions. + * All of these can contain JS code-like characters, and we should make + * sure any further magic ignores anything inside of these. + * + * Consider this example, where we should not strip any whitespace: + * var str = "a test"; + * + * Comments will be removed altogether, strings and regular expressions + * will be replaced by placeholder text, which we'll restore later. + */ + $this->extractStrings('\'"`'); + $this->stripComments(); + $this->extractRegex(); + + // loop files + foreach ($this->data as $source => $js) { + // take out strings, comments & regex (for which we've registered + // the regexes just a few lines earlier) + $js = $this->replace($js); + + $js = $this->propertyNotation($js); + $js = $this->shortenBools($js); + $js = $this->stripWhitespace($js); + + // combine js: separating the scripts by a ; + $content .= $js.";"; + } + + // clean up leftover `;`s from the combination of multiple scripts + $content = ltrim($content, ';'); + $content = (string) substr($content, 0, -1); + + /* + * Earlier, we extracted strings & regular expressions and replaced them + * with placeholder text. This will restore them. + */ + $content = $this->restoreExtractedData($content); + + return $content; + } + + /** + * Strip comments from source code. + */ + protected function stripComments() + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier) { + $count = count($minifier->extracted); + $placeholder = '/*'.$count.'*/'; + $minifier->extracted[$placeholder] = $match[0]; + + return $placeholder; + }; + // multi-line comments + $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback); + $this->registerPattern('/\/\*.*?\*\//s', ''); + + // single-line comments + $this->registerPattern('/\/\/.*$/m', ''); + } + + /** + * JS can have /-delimited regular expressions, like: /ab+c/.match(string). + * + * The content inside the regex can contain characters that may be confused + * for JS code: e.g. it could contain whitespace it needs to match & we + * don't want to strip whitespace in there. + * + * The regex can be pretty simple: we don't have to care about comments, + * (which also use slashes) because stripComments() will have stripped those + * already. + * + * This method will replace all string content with simple REGEX# + * placeholder text, so we've rid all regular expressions from characters + * that may be misinterpreted. Original regex content will be saved in + * $this->extracted and after doing all other minifying, we can restore the + * original content via restoreRegex() + */ + protected function extractRegex() + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier) { + $count = count($minifier->extracted); + $placeholder = '"'.$count.'"'; + $minifier->extracted[$placeholder] = $match[0]; + + return $placeholder; + }; + + // match all chars except `/` and `\` + // `\` is allowed though, along with whatever char follows (which is the + // one being escaped) + // this should allow all chars, except for an unescaped `/` (= the one + // closing the regex) + // then also ignore bare `/` inside `[]`, where they don't need to be + // escaped: anything inside `[]` can be ignored safely + $pattern = '\\/(?!\*)(?:[^\\[\\/\\\\\n\r]++|(?:\\\\.)++|(?:\\[(?:[^\\]\\\\\n\r]++|(?:\\\\.)++)++\\])++)++\\/[gimuy]*'; + + // a regular expression can only be followed by a few operators or some + // of the RegExp methods (a `\` followed by a variable or value is + // likely part of a division, not a regex) + $keywords = array('do', 'in', 'new', 'else', 'throw', 'yield', 'delete', 'return', 'typeof'); + $before = '([=:,;\+\-\*\/\}\(\{\[&\|!]|^|'.implode('|', $keywords).')\s*'; + $propertiesAndMethods = array( + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Properties_2 + 'constructor', + 'flags', + 'global', + 'ignoreCase', + 'multiline', + 'source', + 'sticky', + 'unicode', + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#Methods_2 + 'compile(', + 'exec(', + 'test(', + 'toSource(', + 'toString(', + ); + $delimiters = array_fill(0, count($propertiesAndMethods), '/'); + $propertiesAndMethods = array_map('preg_quote', $propertiesAndMethods, $delimiters); + $after = '(?=\s*([\.,;\)\}&\|+]|\/\/|$|\.('.implode('|', $propertiesAndMethods).')))'; + $this->registerPattern('/'.$before.'\K'.$pattern.$after.'/', $callback); + + // regular expressions following a `)` are rather annoying to detect... + // quite often, `/` after `)` is a division operator & if it happens to + // be followed by another one (or a comment), it is likely to be + // confused for a regular expression + // however, it's perfectly possible for a regex to follow a `)`: after + // a single-line `if()`, `while()`, ... statement, for example + // since, when they occur like that, they're always the start of a + // statement, there's only a limited amount of ways they can be useful: + // by calling the regex methods directly + // if a regex following `)` is not followed by `.`, + // it's quite likely not a regex + $before = '\)\s*'; + $after = '(?=\s*\.('.implode('|', $propertiesAndMethods).'))'; + $this->registerPattern('/'.$before.'\K'.$pattern.$after.'/', $callback); + + // 1 more edge case: a regex can be followed by a lot more operators or + // keywords if there's a newline (ASI) in between, where the operator + // actually starts a new statement + // (https://github.com/matthiasmullie/minify/issues/56) + $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/'); + $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/'); + $after = '(?=\s*\n\s*('.implode('|', $operators).'))'; + $this->registerPattern('/'.$pattern.$after.'/', $callback); + } + + /** + * Strip whitespace. + * + * We won't strip *all* whitespace, but as much as possible. The thing that + * we'll preserve are newlines we're unsure about. + * JavaScript doesn't require statements to be terminated with a semicolon. + * It will automatically fix missing semicolons with ASI (automatic semi- + * colon insertion) at the end of line causing errors (without semicolon.) + * + * Because it's sometimes hard to tell if a newline is part of a statement + * that should be terminated or not, we'll just leave some of them alone. + * + * @param string $content The content to strip the whitespace for + * + * @return string + */ + protected function stripWhitespace($content) + { + // uniform line endings, make them all line feed + $content = str_replace(array("\r\n", "\r"), "\n", $content); + + // collapse all non-line feed whitespace into a single space + $content = preg_replace('/[^\S\n]+/', ' ', $content); + + // strip leading & trailing whitespace + $content = str_replace(array(" \n", "\n "), "\n", $content); + + // collapse consecutive line feeds into just 1 + $content = preg_replace('/\n+/', "\n", $content); + + $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/'); + $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/'); + $operators = $this->getOperatorsForRegex($this->operators, '/'); + $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/'); + $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/'); + + // strip whitespace that ends in (or next line begin with) an operator + // that allows statements to be broken up over multiple lines + unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']); + $content = preg_replace( + array( + '/('.implode('|', $operatorsBefore).')\s+/', + '/\s+('.implode('|', $operatorsAfter).')/', + ), + '\\1', + $content + ); + + // make sure + and - can't be mistaken for, or joined into ++ and -- + $content = preg_replace( + array( + '/(?%&|', $delimiter); + $operators['='] = '(?keywordsReserved; + $callback = function ($match) use ($minifier, $keywords) { + $property = trim($minifier->extracted[$match[1]], '\'"'); + + /* + * Check if the property is a reserved keyword. In this context (as + * property of an object literal/array) it shouldn't matter, but IE8 + * freaks out with "Expected identifier". + */ + if (in_array($property, $keywords)) { + return $match[0]; + } + + /* + * See if the property is in a variable-like format (e.g. + * array['key-here'] can't be replaced by array.key-here since '-' + * is not a valid character there. + */ + if (!preg_match('/^'.$minifier::REGEX_VARIABLE.'$/u', $property)) { + return $match[0]; + } + + return '.'.$property; + }; + + /* + * Figure out if previous character is a variable name (of the array + * we want to use property notation on) - this is to make sure + * standalone ['value'] arrays aren't confused for keys-of-an-array. + * We can (and only have to) check the last character, because PHP's + * regex implementation doesn't allow unfixed-length look-behind + * assertions. + */ + preg_match('/(\[[^\]]+\])[^\]]*$/', static::REGEX_VARIABLE, $previousChar); + $previousChar = $previousChar[1]; + + /* + * Make sure word preceding the ['value'] is not a keyword, e.g. + * return['x']. Because -again- PHP's regex implementation doesn't allow + * unfixed-length look-behind assertions, I'm just going to do a lot of + * separate look-behind assertions, one for each keyword. + */ + $keywords = $this->getKeywordsForRegex($keywords); + $keywords = '(? + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +namespace MatthiasMullie\Minify; + +use MatthiasMullie\Minify\Exceptions\IOException; +use Psr\Cache\CacheItemInterface; + +/** + * Abstract minifier class. + * + * Please report bugs on https://github.com/matthiasmullie/minify/issues + * + * @package Minify + * @author Matthias Mullie + * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved + * @license MIT License + */ +abstract class Minify +{ + /** + * The data to be minified. + * + * @var string[] + */ + protected $data = array(); + + /** + * Array of patterns to match. + * + * @var string[] + */ + protected $patterns = array(); + + /** + * This array will hold content of strings and regular expressions that have + * been extracted from the JS source code, so we can reliably match "code", + * without having to worry about potential "code-like" characters inside. + * + * @var string[] + */ + public $extracted = array(); + + /** + * Init the minify class - optionally, code may be passed along already. + */ + public function __construct(/* $data = null, ... */) + { + // it's possible to add the source through the constructor as well ;) + if (func_num_args()) { + call_user_func_array(array($this, 'add'), func_get_args()); + } + } + + /** + * Add a file or straight-up code to be minified. + * + * @param string|string[] $data + * + * @return static + */ + public function add($data /* $data = null, ... */) + { + // bogus "usage" of parameter $data: scrutinizer warns this variable is + // not used (we're using func_get_args instead to support overloading), + // but it still needs to be defined because it makes no sense to have + // this function without argument :) + $args = array($data) + func_get_args(); + + // this method can be overloaded + foreach ($args as $data) { + if (is_array($data)) { + call_user_func_array(array($this, 'add'), $data); + continue; + } + + // redefine var + $data = (string) $data; + + // load data + $value = $this->load($data); + $key = ($data != $value) ? $data : count($this->data); + + // replace CR linefeeds etc. + // @see https://github.com/matthiasmullie/minify/pull/139 + $value = str_replace(array("\r\n", "\r"), "\n", $value); + + // store data + $this->data[$key] = $value; + } + + return $this; + } + + /** + * Minify the data & (optionally) saves it to a file. + * + * @param string[optional] $path Path to write the data to + * + * @return string The minified data + */ + public function minify($path = null) + { + $content = $this->execute($path); + + // save to path + if ($path !== null) { + $this->save($content, $path); + } + + return $content; + } + + /** + * Minify & gzip the data & (optionally) saves it to a file. + * + * @param string[optional] $path Path to write the data to + * @param int[optional] $level Compression level, from 0 to 9 + * + * @return string The minified & gzipped data + */ + public function gzip($path = null, $level = 9) + { + $content = $this->execute($path); + $content = gzencode($content, $level, FORCE_GZIP); + + // save to path + if ($path !== null) { + $this->save($content, $path); + } + + return $content; + } + + /** + * Minify the data & write it to a CacheItemInterface object. + * + * @param CacheItemInterface $item Cache item to write the data to + * + * @return CacheItemInterface Cache item with the minifier data + */ + public function cache(CacheItemInterface $item) + { + $content = $this->execute(); + $item->set($content); + + return $item; + } + + /** + * Minify the data. + * + * @param string[optional] $path Path to write the data to + * + * @return string The minified data + */ + abstract public function execute($path = null); + + /** + * Load data. + * + * @param string $data Either a path to a file or the content itself + * + * @return string + */ + protected function load($data) + { + // check if the data is a file + if ($this->canImportFile($data)) { + $data = file_get_contents($data); + + // strip BOM, if any + if (substr($data, 0, 3) == "\xef\xbb\xbf") { + $data = substr($data, 3); + } + } + + return $data; + } + + /** + * Save to file. + * + * @param string $content The minified data + * @param string $path The path to save the minified data to + * + * @throws IOException + */ + protected function save($content, $path) + { + $handler = $this->openFileForWriting($path); + + $this->writeToFile($handler, $content); + + @fclose($handler); + } + + /** + * Register a pattern to execute against the source content. + * + * @param string $pattern PCRE pattern + * @param string|callable $replacement Replacement value for matched pattern + */ + protected function registerPattern($pattern, $replacement = '') + { + // study the pattern, we'll execute it more than once + $pattern .= 'S'; + + $this->patterns[] = array($pattern, $replacement); + } + + /** + * We can't "just" run some regular expressions against JavaScript: it's a + * complex language. E.g. having an occurrence of // xyz would be a comment, + * unless it's used within a string. Of you could have something that looks + * like a 'string', but inside a comment. + * The only way to accurately replace these pieces is to traverse the JS one + * character at a time and try to find whatever starts first. + * + * @param string $content The content to replace patterns in + * + * @return string The (manipulated) content + */ + protected function replace($content) + { + $processed = ''; + $positions = array_fill(0, count($this->patterns), -1); + $matches = array(); + + while ($content) { + // find first match for all patterns + foreach ($this->patterns as $i => $pattern) { + list($pattern, $replacement) = $pattern; + + // we can safely ignore patterns for positions we've unset earlier, + // because we know these won't show up anymore + if (array_key_exists($i, $positions) == false) { + continue; + } + + // no need to re-run matches that are still in the part of the + // content that hasn't been processed + if ($positions[$i] >= 0) { + continue; + } + + $match = null; + if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE)) { + $matches[$i] = $match; + + // we'll store the match position as well; that way, we + // don't have to redo all preg_matches after changing only + // the first (we'll still know where those others are) + $positions[$i] = $match[0][1]; + } else { + // if the pattern couldn't be matched, there's no point in + // executing it again in later runs on this same content; + // ignore this one until we reach end of content + unset($matches[$i], $positions[$i]); + } + } + + // no more matches to find: everything's been processed, break out + if (!$matches) { + $processed .= $content; + break; + } + + // see which of the patterns actually found the first thing (we'll + // only want to execute that one, since we're unsure if what the + // other found was not inside what the first found) + $discardLength = min($positions); + $firstPattern = array_search($discardLength, $positions); + $match = $matches[$firstPattern][0][0]; + + // execute the pattern that matches earliest in the content string + list($pattern, $replacement) = $this->patterns[$firstPattern]; + $replacement = $this->replacePattern($pattern, $replacement, $content); + + // figure out which part of the string was unmatched; that's the + // part we'll execute the patterns on again next + $content = (string) substr($content, $discardLength); + $unmatched = (string) substr($content, strpos($content, $match) + strlen($match)); + + // move the replaced part to $processed and prepare $content to + // again match batch of patterns against + $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched)); + $content = $unmatched; + + // first match has been replaced & that content is to be left alone, + // the next matches will start after this replacement, so we should + // fix their offsets + foreach ($positions as $i => $position) { + $positions[$i] -= $discardLength + strlen($match); + } + } + + return $processed; + } + + /** + * This is where a pattern is matched against $content and the matches + * are replaced by their respective value. + * This function will be called plenty of times, where $content will always + * move up 1 character. + * + * @param string $pattern Pattern to match + * @param string|callable $replacement Replacement value + * @param string $content Content to match pattern against + * + * @return string + */ + protected function replacePattern($pattern, $replacement, $content) + { + if (is_callable($replacement)) { + return preg_replace_callback($pattern, $replacement, $content, 1, $count); + } else { + return preg_replace($pattern, $replacement, $content, 1, $count); + } + } + + /** + * Strings are a pattern we need to match, in order to ignore potential + * code-like content inside them, but we just want all of the string + * content to remain untouched. + * + * This method will replace all string content with simple STRING# + * placeholder text, so we've rid all strings from characters that may be + * misinterpreted. Original string content will be saved in $this->extracted + * and after doing all other minifying, we can restore the original content + * via restoreStrings(). + * + * @param string[optional] $chars + * @param string[optional] $placeholderPrefix + */ + protected function extractStrings($chars = '\'"', $placeholderPrefix = '') + { + // PHP only supports $this inside anonymous functions since 5.4 + $minifier = $this; + $callback = function ($match) use ($minifier, $placeholderPrefix) { + // check the second index here, because the first always contains a quote + if ($match[2] === '') { + /* + * Empty strings need no placeholder; they can't be confused for + * anything else anyway. + * But we still needed to match them, for the extraction routine + * to skip over this particular string. + */ + return $match[0]; + } + + $count = count($minifier->extracted); + $placeholder = $match[1].$placeholderPrefix.$count.$match[1]; + $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1]; + + return $placeholder; + }; + + /* + * The \\ messiness explained: + * * Don't count ' or " as end-of-string if it's escaped (has backslash + * in front of it) + * * Unless... that backslash itself is escaped (another leading slash), + * in which case it's no longer escaping the ' or " + * * So there can be either no backslash, or an even number + * * multiply all of that times 4, to account for the escaping that has + * to be done to pass the backslash into the PHP string without it being + * considered as escape-char (times 2) and to get it in the regex, + * escaped (times 2) + */ + $this->registerPattern('/(['.$chars.'])(.*?(?extracted. + * + * @param string $content + * + * @return string + */ + protected function restoreExtractedData($content) + { + if (!$this->extracted) { + // nothing was extracted, nothing to restore + return $content; + } + + $content = strtr($content, $this->extracted); + + $this->extracted = array(); + + return $content; + } + + /** + * Check if the path is a regular file and can be read. + * + * @param string $path + * + * @return bool + */ + protected function canImportFile($path) + { + $parsed = parse_url($path); + if ( + // file is elsewhere + isset($parsed['host']) || + // file responds to queries (may change, or need to bypass cache) + isset($parsed['query']) + ) { + return false; + } + + return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path); + } + + /** + * Attempts to open file specified by $path for writing. + * + * @param string $path The path to the file + * + * @return resource Specifier for the target file + * + * @throws IOException + */ + protected function openFileForWriting($path) + { + if (($handler = @fopen($path, 'w')) === false) { + throw new IOException('The file "'.$path.'" could not be opened for writing. Check if PHP has enough permissions.'); + } + + return $handler; + } + + /** + * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions. + * + * @param resource $handler The resource to write to + * @param string $content The content to write + * @param string $path The path to the file (for exception printing only) + * + * @throws IOException + */ + protected function writeToFile($handler, $content, $path = '') + { + if (($result = @fwrite($handler, $content)) === false || ($result < strlen($content))) { + throw new IOException('The file "'.$path.'" could not be written to. Check your disk space and file permissions.'); + } + } +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/path-converter/LICENSE b/data/web/inc/lib/vendor/matthiasmullie/path-converter/LICENSE new file mode 100644 index 00000000..491295ad --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/path-converter/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2015 Matthias Mullie + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/data/web/inc/lib/vendor/matthiasmullie/path-converter/composer.json b/data/web/inc/lib/vendor/matthiasmullie/path-converter/composer.json new file mode 100644 index 00000000..1cb6a4c5 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/path-converter/composer.json @@ -0,0 +1,28 @@ +{ + "name": "matthiasmullie/path-converter", + "type": "library", + "description": "Relative path converter", + "keywords": ["relative", "path", "converter", "paths"], + "homepage": "http://github.com/matthiasmullie/path-converter", + "license": "MIT", + "authors": [ + { + "name": "Matthias Mullie", + "homepage": "http://www.mullie.eu", + "email": "pathconverter@mullie.eu", + "role": "Developer" + } + ], + "require": { + "php": ">=5.3.0", + "ext-pcre": "*" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "autoload": { + "psr-4": { + "MatthiasMullie\\PathConverter\\": "src/" + } + } +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/Converter.php b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/Converter.php new file mode 100644 index 00000000..519d3c84 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/Converter.php @@ -0,0 +1,196 @@ + + * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved + * @license MIT License + */ +class Converter implements ConverterInterface +{ + /** + * @var string + */ + protected $from; + + /** + * @var string + */ + protected $to; + + /** + * @param string $from The original base path (directory, not file!) + * @param string $to The new base path (directory, not file!) + * @param string $root Root directory (defaults to `getcwd`) + */ + public function __construct($from, $to, $root = '') + { + $shared = $this->shared($from, $to); + if ($shared === '') { + // when both paths have nothing in common, one of them is probably + // absolute while the other is relative + $root = $root ?: getcwd(); + $from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root.'/'.$from); + $to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root.'/'.$to); + + // or traveling the tree via `..` + // attempt to resolve path, or assume it's fine if it doesn't exist + $from = @realpath($from) ?: $from; + $to = @realpath($to) ?: $to; + } + + $from = $this->dirname($from); + $to = $this->dirname($to); + + $from = $this->normalize($from); + $to = $this->normalize($to); + + $this->from = $from; + $this->to = $to; + } + + /** + * Normalize path. + * + * @param string $path + * + * @return string + */ + protected function normalize($path) + { + // deal with different operating systems' directory structure + $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/'); + + /* + * Example: + * /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif + * to + * /home/forkcms/frontend/core/layout/images/img.gif + */ + do { + $path = preg_replace('/[^\/]+(? $chunk) { + if (isset($path2[$i]) && $path1[$i] == $path2[$i]) { + $shared[] = $chunk; + } else { + break; + } + } + + return implode('/', $shared); + } + + /** + * Convert paths relative from 1 file to another. + * + * E.g. + * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css + * should become: + * ../../core/layout/images/img.gif relative to + * /home/forkcms/frontend/cache/minified_css + * + * @param string $path The relative path that needs to be converted + * + * @return string The new relative path + */ + public function convert($path) + { + // quit early if conversion makes no sense + if ($this->from === $this->to) { + return $path; + } + + $path = $this->normalize($path); + // if we're not dealing with a relative path, just return absolute + if (strpos($path, '/') === 0) { + return $path; + } + + // normalize paths + $path = $this->normalize($this->from.'/'.$path); + + // strip shared ancestor paths + $shared = $this->shared($path, $this->to); + $path = mb_substr($path, mb_strlen($shared)); + $to = mb_substr($this->to, mb_strlen($shared)); + + // add .. for every directory that needs to be traversed to new path + $to = str_repeat('../', count(array_filter(explode('/', $to)))); + + return $to.ltrim($path, '/'); + } + + /** + * Attempt to get the directory name from a path. + * + * @param string $path + * + * @return string + */ + protected function dirname($path) + { + if (@is_file($path)) { + return dirname($path); + } + + if (@is_dir($path)) { + return rtrim($path, '/'); + } + + // no known file/dir, start making assumptions + + // ends in / = dir + if (mb_substr($path, -1) === '/') { + return rtrim($path, '/'); + } + + // has a dot in the name, likely a file + if (preg_match('/.*\..*$/', basename($path)) !== 0) { + return dirname($path); + } + + // you're on your own here! + return $path; + } +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/ConverterInterface.php b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/ConverterInterface.php new file mode 100644 index 00000000..dc1b7657 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/ConverterInterface.php @@ -0,0 +1,24 @@ + + * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved + * @license MIT License + */ +interface ConverterInterface +{ + /** + * Convert file paths. + * + * @param string $path The path to be converted + * + * @return string The new path + */ + public function convert($path); +} diff --git a/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/NoConverter.php b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/NoConverter.php new file mode 100644 index 00000000..2fcfd0f2 --- /dev/null +++ b/data/web/inc/lib/vendor/matthiasmullie/path-converter/src/NoConverter.php @@ -0,0 +1,23 @@ + + * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved + * @license MIT License + */ +class NoConverter implements ConverterInterface +{ + /** + * {@inheritdoc} + */ + public function convert($path) + { + return $path; + } +} diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/LICENSE b/data/web/inc/lib/vendor/paragonie/random_compat/LICENSE new file mode 100644 index 00000000..45c7017d --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Paragon Initiative Enterprises + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/build-phar.sh b/data/web/inc/lib/vendor/paragonie/random_compat/build-phar.sh new file mode 100755 index 00000000..b4a5ba31 --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/build-phar.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) ) + +php -dphar.readonly=0 "$basedir/other/build_phar.php" $* \ No newline at end of file diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/composer.json b/data/web/inc/lib/vendor/paragonie/random_compat/composer.json new file mode 100644 index 00000000..1fa8de9f --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/composer.json @@ -0,0 +1,34 @@ +{ + "name": "paragonie/random_compat", + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "random", + "polyfill", + "pseudorandom" + ], + "license": "MIT", + "type": "library", + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "support": { + "issues": "https://github.com/paragonie/random_compat/issues", + "email": "info@paragonie.com", + "source": "https://github.com/paragonie/random_compat" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "vimeo/psalm": "^1", + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + } +} diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey b/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey new file mode 100644 index 00000000..eb50ebfc --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm +pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p ++h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc +-----END PUBLIC KEY----- diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc b/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc new file mode 100644 index 00000000..6a1d7f30 --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.22 (MingW32) + +iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip +QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg +1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW +NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA +NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV +JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74= +=B6+8 +-----END PGP SIGNATURE----- diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/lib/random.php b/data/web/inc/lib/vendor/paragonie/random_compat/lib/random.php new file mode 100644 index 00000000..c7731a56 --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/lib/random.php @@ -0,0 +1,32 @@ +buildFromDirectory(dirname(__DIR__).'/lib'); +rename( + dirname(__DIR__).'/lib/index.php', + dirname(__DIR__).'/lib/random.php' +); + +/** + * If we pass an (optional) path to a private key as a second argument, we will + * sign the Phar with OpenSSL. + * + * If you leave this out, it will produce an unsigned .phar! + */ +if ($argc > 1) { + if (!@is_readable($argv[1])) { + echo 'Could not read the private key file:', $argv[1], "\n"; + exit(255); + } + $pkeyFile = file_get_contents($argv[1]); + + $private = openssl_get_privatekey($pkeyFile); + if ($private !== false) { + $pkey = ''; + openssl_pkey_export($private, $pkey); + $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey); + + /** + * Save the corresponding public key to the file + */ + if (!@is_readable($dist.'/random_compat.phar.pubkey')) { + $details = openssl_pkey_get_details($private); + file_put_contents( + $dist.'/random_compat.phar.pubkey', + $details['key'] + ); + } + } else { + echo 'An error occurred reading the private key from OpenSSL.', "\n"; + exit(255); + } +} diff --git a/data/web/inc/lib/vendor/paragonie/random_compat/psalm-autoload.php b/data/web/inc/lib/vendor/paragonie/random_compat/psalm-autoload.php new file mode 100644 index 00000000..d71d1b81 --- /dev/null +++ b/data/web/inc/lib/vendor/paragonie/random_compat/psalm-autoload.php @@ -0,0 +1,9 @@ + + + + + + + + + + + + + + + diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/ISSUE_TEMPLATE.md b/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 97776f1c..00000000 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1 +0,0 @@ -Non-security issues and pull requests are no longer being accepted for the legacy PHPMailer 5.2 branch. Migrate to PHPMailer 6.0 (or later) and report your issue there. \ No newline at end of file diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/PULL_REQUEST_TEMPLATE.md b/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 97776f1c..00000000 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1 +0,0 @@ -Non-security issues and pull requests are no longer being accepted for the legacy PHPMailer 5.2 branch. Migrate to PHPMailer 6.0 (or later) and report your issue there. \ No newline at end of file diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/LICENSE b/data/web/inc/lib/vendor/phpmailer/phpmailer/LICENSE index 8e0763d1..f166cc57 100644 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/LICENSE +++ b/data/web/inc/lib/vendor/phpmailer/phpmailer/LICENSE @@ -1,8 +1,8 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -10,7 +10,7 @@ as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. - + Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a @@ -111,8 +111,8 @@ modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE + + GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other @@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. - + 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an @@ -158,7 +158,7 @@ Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - + 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 @@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. - + Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. @@ -267,7 +267,7 @@ Library will still fall under Section 6.) distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. - + 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work @@ -312,7 +312,7 @@ of these things: from a designated place, offer equivalent access to copy the above specified materials from the same place. - e) verify that the user has already received a copy of these + e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the @@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. - + 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined @@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. - + 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or @@ -422,7 +422,7 @@ conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. - + 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is @@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. @@ -455,8 +455,8 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - + END OF TERMS AND CONDITIONS + How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest @@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. @@ -499,6 +499,4 @@ necessary. Here is a sample; alter the names: , 1 April 1990 Ty Coon, President of Vice -That's all there is to it! - - +That's all there is to it! \ No newline at end of file diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION b/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION index f0fb1a22..32779c18 100644 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION +++ b/data/web/inc/lib/vendor/phpmailer/phpmailer/VERSION @@ -1 +1 @@ -5.2.26 +5.2.27 \ No newline at end of file diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.phpmailer.php b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.phpmailer.php index 99f9092c..12a95875 100644 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.phpmailer.php +++ b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.phpmailer.php @@ -31,7 +31,7 @@ class PHPMailer * The PHPMailer Version number. * @var string */ - public $Version = '5.2.26'; + public $Version = '5.2.27'; /** * Email priority. @@ -1296,9 +1296,12 @@ class PHPMailer // Sign with DKIM if enabled if (!empty($this->DKIM_domain) - && !empty($this->DKIM_selector) - && (!empty($this->DKIM_private_string) - || (!empty($this->DKIM_private) && file_exists($this->DKIM_private)) + and !empty($this->DKIM_selector) + and (!empty($this->DKIM_private_string) + or (!empty($this->DKIM_private) + and self::isPermittedPath($this->DKIM_private) + and file_exists($this->DKIM_private) + ) ) ) { $header_dkim = $this->DKIM_Add( @@ -1463,6 +1466,18 @@ class PHPMailer return true; } + /** + * Check whether a file path is of a permitted type. + * Used to reject URLs and phar files from functions that access local file paths, + * such as addAttachment. + * @param string $path A relative or absolute path to a file. + * @return bool + */ + protected static function isPermittedPath($path) + { + return !preg_match('#^[a-z]+://#i', $path); + } + /** * Send mail using the PHP mail() function. * @param string $header The message headers @@ -1791,7 +1806,7 @@ class PHPMailer // There is no English translation file if ($langcode != 'en') { // Make sure language file path is readable - if (!is_readable($lang_file)) { + if (!self::isPermittedPath($lang_file) or !is_readable($lang_file)) { $foundlang = false; } else { // Overwrite language-specific strings. @@ -2499,6 +2514,8 @@ class PHPMailer * Add an attachment from a path on the filesystem. * Never use a user-supplied path to a file! * Returns false if the file could not be found or read. + * Explicitly *does not* support passing URLs; PHPMailer is not an HTTP client. + * If you need to do that, fetch the resource yourself and pass it in via a local file or string. * @param string $path Path to the attachment. * @param string $name Overrides the attachment name. * @param string $encoding File encoding (see $Encoding). @@ -2510,7 +2527,7 @@ class PHPMailer public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') { try { - if (!@is_file($path)) { + if (!self::isPermittedPath($path) or !@is_file($path)) { throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE); } @@ -2691,7 +2708,7 @@ class PHPMailer protected function encodeFile($path, $encoding = 'base64') { try { - if (!is_readable($path)) { + if (!self::isPermittedPath($path) or !file_exists($path)) { throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE); } $magic_quotes = get_magic_quotes_runtime(); @@ -3035,7 +3052,7 @@ class PHPMailer */ public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') { - if (!@is_file($path)) { + if (!self::isPermittedPath($path) or !@is_file($path)) { $this->setError($this->lang('file_access') . $path); return false; } diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.pop3.php b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.pop3.php index f833ac61..5a458e5d 100644 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.pop3.php +++ b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.pop3.php @@ -34,7 +34,7 @@ class POP3 * @var string * @access public */ - public $Version = '5.2.26'; + public $Version = '5.2.27'; /** * Default POP3 port number. diff --git a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.smtp.php b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.smtp.php index be6ddce4..118cb20f 100644 --- a/data/web/inc/lib/vendor/phpmailer/phpmailer/class.smtp.php +++ b/data/web/inc/lib/vendor/phpmailer/phpmailer/class.smtp.php @@ -30,7 +30,7 @@ class SMTP * The PHPMailer SMTP version number. * @var string */ - const VERSION = '5.2.26'; + const VERSION = '5.2.27'; /** * SMTP line break constant. @@ -81,7 +81,7 @@ class SMTP * @deprecated Use the `VERSION` constant instead * @see SMTP::VERSION */ - public $Version = '5.2.26'; + public $Version = '5.2.27'; /** * SMTP server port number. diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/.travis.yml b/data/web/inc/lib/vendor/yubico/u2flib-server/.travis.yml index b4282b2c..beade3b0 100644 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/.travis.yml +++ b/data/web/inc/lib/vendor/yubico/u2flib-server/.travis.yml @@ -3,6 +3,7 @@ sudo: false php: - 7.0 - 7.1 + - 7.2 - hhvm matrix: include: @@ -15,6 +16,7 @@ before_script: - composer install script: + - ./vendor/bin/psalm - ./vendor/phpunit/phpunit/phpunit -c phpunit.xml after_success: diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/NEWS b/data/web/inc/lib/vendor/yubico/u2flib-server/NEWS index a8f97ae7..496175ed 100644 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/NEWS +++ b/data/web/inc/lib/vendor/yubico/u2flib-server/NEWS @@ -1,5 +1,11 @@ php-u2flib-server NEWS -- History of user-visible changes. +* Version 1.0.2 (released 2018-09-07) + ** Additional error checks. + ** Add user presence check. + ** Support single files for attestation root. + ** Type safety, CSPRNG, avoid chr(). + * Version 1.0.1 (released 2017-05-09) ** Move examples to phps so they don't execute by default ** Use common challenge for multiple registrations diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/composer.json b/data/web/inc/lib/vendor/yubico/u2flib-server/composer.json index 5b3a970d..3f2d9eab 100644 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/composer.json +++ b/data/web/inc/lib/vendor/yubico/u2flib-server/composer.json @@ -5,12 +5,14 @@ "license":"BSD-2-Clause", "require": { "ext-openssl":"*", + "paragonie/random_compat": ">= 1", "php": ">=5.6" }, "autoload": { "classmap": ["src/"] }, "require-dev": { - "phpunit/phpunit": "~5.7" + "phpunit/phpunit": "~5.7", + "vimeo/psalm": "^0|^1|^2" } } diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/psalm.xml b/data/web/inc/lib/vendor/yubico/u2flib-server/psalm.xml new file mode 100644 index 00000000..6b6234cf --- /dev/null +++ b/data/web/inc/lib/vendor/yubico/u2flib-server/psalm.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/src/u2flib_server/U2F.php b/data/web/inc/lib/vendor/yubico/u2flib-server/src/u2flib_server/U2F.php index a11c78fb..8583fff2 100644 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/src/u2flib_server/U2F.php +++ b/data/web/inc/lib/vendor/yubico/u2flib-server/src/u2flib_server/U2F.php @@ -32,6 +32,12 @@ namespace u2flib_server; /** Constant for the version of the u2f protocol */ const U2F_VERSION = "U2F_V2"; +/** Constant for the type value in registration clientData */ +const REQUEST_TYPE_REGISTER = "navigator.id.finishEnrollment"; + +/** Constant for the type value in authentication clientData */ +const REQUEST_TYPE_AUTHENTICATE = "navigator.id.getAssertion"; + /** Error for the authentication message not matching any outstanding * authentication request */ const ERR_NO_MATCHING_REQUEST = 1; @@ -69,6 +75,15 @@ const ERR_BAD_UA_RETURNING = 10; /** Error old OpenSSL version */ const ERR_OLD_OPENSSL = 11; +/** Error for the origin not matching the appId */ +const ERR_NO_MATCHING_ORIGIN = 12; + +/** Error for the type in clientData being invalid */ +const ERR_BAD_TYPE = 13; + +/** Error for bad user presence byte value */ +const ERR_BAD_USER_PRESENCE = 14; + /** @internal */ const PUBKEY_LEN = 65; @@ -160,6 +175,14 @@ class U2F throw new Error('Registration challenge does not match', ERR_UNMATCHED_CHALLENGE ); } + if(isset($cli->typ) && $cli->typ !== REQUEST_TYPE_REGISTER) { + throw new Error('ClientData type is invalid', ERR_BAD_TYPE); + } + + if(isset($cli->origin) && $cli->origin !== $request->appId) { + throw new Error('App ID does not match the origin', ERR_NO_MATCHING_ORIGIN); + } + $registration = new Registration(); $offs = 1; $pubKey = substr($rawReg, $offs, PUBKEY_LEN); @@ -199,7 +222,7 @@ class U2F } $signature = substr($rawReg, $offs); - $dataToVerify = chr(0); + $dataToVerify = pack('C', 0); $dataToVerify .= hash('sha256', $request->appId, true); $dataToVerify .= hash('sha256', $clientData, true); $dataToVerify .= $kh; @@ -227,6 +250,7 @@ class U2F if( !is_object( $reg ) ) { throw new \InvalidArgumentException('$registrations of getAuthenticateData() method only accepts array of object.'); } + /** @var Registration $reg */ $sig = new SignRequest(); $sig->appId = $this->appId; @@ -269,6 +293,11 @@ class U2F $clientData = $this->base64u_decode($response->clientData); $decodedClient = json_decode($clientData); + + if(isset($decodedClient->typ) && $decodedClient->typ !== REQUEST_TYPE_AUTHENTICATE) { + throw new Error('ClientData type is invalid', ERR_BAD_TYPE); + } + foreach ($requests as $req) { if( !is_object( $req ) ) { throw new \InvalidArgumentException('$requests of doAuthenticate() method only accepts array of object.'); @@ -283,6 +312,9 @@ class U2F if($req === null) { throw new Error('No matching request found', ERR_NO_MATCHING_REQUEST ); } + if(isset($decodedClient->origin) && $decodedClient->origin !== $req->appId) { + throw new Error('App ID does not match the origin', ERR_NO_MATCHING_ORIGIN); + } foreach ($registrations as $reg) { if( !is_object( $reg ) ) { throw new \InvalidArgumentException('$registrations of doAuthenticate() method only accepts array of object.'); @@ -308,12 +340,16 @@ class U2F $signature = substr($signData, 5); if(openssl_verify($dataToVerify, $signature, $pemKey, 'sha256') === 1) { + $upb = unpack("Cupb", substr($signData, 0, 1)); + if($upb['upb'] !== 1) { + throw new Error('User presence byte value is invalid', ERR_BAD_USER_PRESENCE ); + } $ctr = unpack("Nctr", substr($signData, 1, 4)); $counter = $ctr['ctr']; /* TODO: wrap-around should be handled somehow.. */ if($counter > $reg->counter) { $reg->counter = $counter; - return $reg; + return self::castObjectToRegistration($reg); } else { throw new Error('Counter too low.', ERR_COUNTER_TOO_LOW ); } @@ -322,6 +358,28 @@ class U2F } } + /** + * @param object $object + * @return Registration + */ + protected static function castObjectToRegistration($object) + { + $reg = new Registration(); + if (property_exists($object, 'publicKey')) { + $reg->publicKey = $object->publicKey; + } + if (property_exists($object, 'certificate')) { + $reg->certificate = $object->certificate; + } + if (property_exists($object, 'counter')) { + $reg->counter = $object->counter; + } + if (property_exists($object, 'keyHandle')) { + $reg->keyHandle = $object->keyHandle; + } + return $reg; + } + /** * @return array */ @@ -329,13 +387,15 @@ class U2F { $files = array(); $dir = $this->attestDir; - if($dir && $handle = opendir($dir)) { + if($dir !== null && is_dir($dir) && $handle = opendir($dir)) { while(false !== ($entry = readdir($handle))) { if(is_file("$dir/$entry")) { $files[] = "$dir/$entry"; } } closedir($handle); + } elseif (is_file("$dir")) { + $files[] = "$dir"; } return $files; } @@ -395,11 +455,7 @@ class U2F */ private function createChallenge() { - $challenge = openssl_random_pseudo_bytes(32, $crypto_strong ); - if( $crypto_strong !== true ) { - throw new Error('Unable to obtain a good source of randomness', ERR_BAD_RANDOM); - } - + $challenge = random_bytes(32); $challenge = $this->base64u_encode( $challenge ); return $challenge; @@ -413,7 +469,7 @@ class U2F */ private function fixSignatureUnusedBits($cert) { - if(in_array(hash('sha256', $cert), $this->FIXCERTS)) { + if(in_array(hash('sha256', $cert), $this->FIXCERTS, true)) { $cert[strlen($cert) - 257] = "\0"; } return $cert; @@ -427,13 +483,13 @@ class U2F */ class RegisterRequest { - /** Protocol version */ + /** @var string Protocol version */ public $version = U2F_VERSION; - /** Registration challenge */ + /** @var string Registration challenge */ public $challenge; - /** Application id */ + /** @var string Application id */ public $appId; /** @@ -455,17 +511,17 @@ class RegisterRequest */ class SignRequest { - /** Protocol version */ + /** @var string Protocol version */ public $version = U2F_VERSION; - /** Authentication challenge */ - public $challenge; + /** @var string Authentication challenge */ + public $challenge = ''; - /** Key handle of a registered authenticator */ - public $keyHandle; + /** @var string Key handle of a registered authenticator */ + public $keyHandle = ''; - /** Application id */ - public $appId; + /** @var string Application id */ + public $appId = ''; } /** @@ -475,16 +531,16 @@ class SignRequest */ class Registration { - /** The key handle of the registered authenticator */ - public $keyHandle; + /** @var string The key handle of the registered authenticator */ + public $keyHandle = ''; - /** The public key of the registered authenticator */ - public $publicKey; + /** @var string The public key of the registered authenticator */ + public $publicKey = ''; - /** The attestation certificate of the registered authenticator */ - public $certificate; + /** @var string The attestation certificate of the registered authenticator */ + public $certificate = ''; - /** The counter associated with this registration */ + /** @var int The counter associated with this registration */ public $counter = -1; } diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/tests/certs/yubico-u2f-ca-1.pem b/data/web/inc/lib/vendor/yubico/u2flib-server/tests/certs/yubico-u2f-ca-1.pem deleted file mode 100644 index 15a1dc28..00000000 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/tests/certs/yubico-u2f-ca-1.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ -dWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw -MDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290 -IENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk -5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep -8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw -nebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT -9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw -LvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ -hjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN -BgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4 -MYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt -hX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k -LVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U -sG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc -U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw== ------END CERTIFICATE----- diff --git a/data/web/inc/lib/vendor/yubico/u2flib-server/tests/u2flib_test.php b/data/web/inc/lib/vendor/yubico/u2flib-server/tests/u2flib_test.php deleted file mode 100644 index 56af62bf..00000000 --- a/data/web/inc/lib/vendor/yubico/u2flib-server/tests/u2flib_test.php +++ /dev/null @@ -1,296 +0,0 @@ -u2f = new u2flib_server\U2F("http://demo.example.com"); - } - - public function testGetRegisterData() { - list($reg, $signData) = $this->u2f->getRegisterData(); - $this->assertJsonStringEqualsJsonString(json_encode(array()), json_encode($signData)); - $this->assertEquals('U2F_V2', $reg->version); - $this->assertObjectHasAttribute('challenge', $reg); - $this->assertEquals('http://demo.example.com', $reg->appId); - } - - public function testDoRegister() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9", "errorCode": 0 }'); - $reg = $this->u2f->doRegister($req, $resp); - $this->assertEquals('CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w', $reg->keyHandle); - $this->assertEquals('BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y/yaFORPUe3c=', $reg->publicKey); - $this->assertEquals('MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp/VRZHOwd2NZNzpnB9ePNKvUaWCGK/gN+cynnYFdwJ75iSgMVYb/RnFcdPwnsBzBU68hbhTnu/FvJxWo7rZJ2q7qXpA10eLVXJr4/4oSXEk9I/0IIHqOP98Ck/fAoI5gYI7ygndyqoPJ/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh/h7oKEKamCWk19dJp5jHQmumkHlvQhH/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg/0J+xOb4zl6a1z65nae4OTj7628/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==', $reg->certificate); - $this->assertLessThan(0, $reg->counter); - } - - public function testDoRegisterNoCert() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $reg = $this->u2f->doRegister($req, $resp, false); - $this->assertEquals('CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w', $reg->keyHandle); - $this->assertEquals('BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y/yaFORPUe3c=', $reg->publicKey); - $this->assertEquals('', $reg->certificate); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_ATTESTATION_VERIFICATION - */ - public function testDoRegisterAttestFail() { - $this->u2f = new u2flib_server\U2F("http://demo.example.com", __DIR__ . "/../tests/certs"); - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp, true); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_ATTESTATION_SIGNATURE - */ - public function testDoRegisterFail2() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8NwW=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp, false); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_UNMATCHED_CHALLENGE - */ - public function testDoRegisterFail() { - $req = json_decode('{"version":"U2F_V2","challenge":"YKA0X075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp, false); - } - - public function testDoRegisterAttest() { - $this->u2f = new u2flib_server\U2F("http://demo.example.com", __DIR__ . "/../tests/certs"); - $req = json_decode('{"version":"U2F_V2","challenge":"5CBRhGBb2CXSum71GNREBGft7yz9g1jZO7JTkHGFsVY","appId":"http:\/\/demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQRX1gfcG-ofTlk9rjB9spsIMrmT9ba0DLto5fzk8FDB05ModNU2sWAqoQRemYiUrILQdbNGpN_aHA0_oq8kcd_XQCK-Ut0PWaOtz43t0aAV04U788e-dvpeqLtHxtINjgmutKM8_GJQ7F-3W0dogUjSANuRYRdkkSEHPcVdLSkpyfowggIbMIIBBaADAgECAgRAxBIlMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTA4NjU5MTUyNTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABK2iSVV7KGNEdPE-oHGvobNnHVw6ZZ6vB3jNIYB1C4t32OucHzMweHqM5CAMSMDHtfp1vuJYaiQSk7jb6M48WtejEjAQMA4GCisGAQQBgsQKAQEEADALBgkqhkiG9w0BAQsDggEBAVg0BoEHEEp4LJLYPYFACRGS8WZiXkCA8crYLgGnzvfKXwPwyKJlUzYxxv5xoRrl5zjkIUXhZ4mnHZVsnj9EY_VGDuRRzKX7YtxTZpFZn7ej3abjLhckTkkQ_AhUkmP7VuK2AWLgYsS8ejGUqughBsKvh_84uxTAEr5BS-OGg2yi7UIjd8W0nOCc6EN8d_8wCiPOjt2Y_-TKpLLTXKszk4UnWNzRdxBThmBBprJBZbF1VyVRvJm5yRLBpth3G8KMvrt4Nu3Ecoj_Q154IJpWe1Dp1upDFLOG9nWCRQk25Y264k9BDISfqs-wHvUjIo2iDnKl5UVoauTWaT7M6KuEwl4wRAIgYUVjS_yTwJAtF35glSbf9Et-5tJzlHOeAqmbACd6pwsCIE0MkTR5XNQoO4XqDaUZCXmadWu8yU1gfE7AJI9JUUcc", "clientData": "eyAiY2hhbGxlbmdlIjogIjVDQlJoR0JiMkNYU3VtNzFHTlJFQkdmdDd5ejlnMWpaTzdKVGtIR0ZzVlkiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $reg = $this->u2f->doRegister($req, $resp, true); - $this->assertEquals('Ir5S3Q9Zo63Pje3RoBXThTvzx752-l6ou0fG0g2OCa60ozz8YlDsX7dbR2iBSNIA25FhF2SRIQc9xV0tKSnJ-g', $reg->keyHandle); - $this->assertEquals('BFfWB9wb6h9OWT2uMH2ymwgyuZP1trQMu2jl/OTwUMHTkyh01TaxYCqhBF6ZiJSsgtB1s0ak39ocDT+iryRx39c=', $reg->publicKey); - $this->assertEquals('MIICGzCCAQWgAwIBAgIEQMQSJTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDEwODY1OTE1MjUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoklVeyhjRHTxPqBxr6GzZx1cOmWerwd4zSGAdQuLd9jrnB8zMHh6jOQgDEjAx7X6db7iWGokEpO42+jOPFrXoxIwEDAOBgorBgEEAYLECgEBBAAwCwYJKoZIhvcNAQELA4IBAQBYNAaBBxBKeCyS2D2BQAkRkvFmYl5AgPHK2C4Bp873yl8D8MiiZVM2Mcb+caEa5ec45CFF4WeJpx2VbJ4/RGP1Rg7kUcyl+2LcU2aRWZ+3o92m4y4XJE5JEPwIVJJj+1bitgFi4GLEvHoxlKroIQbCr4f/OLsUwBK+QUvjhoNsou1CI3fFtJzgnOhDfHf/MAojzo7dmP/kyqSy01yrM5OFJ1jc0XcQU4ZgQaayQWWxdVclUbyZuckSwabYdxvCjL67eDbtxHKI/0NeeCCaVntQ6dbqQxSzhvZ1gkUJNuWNuuJPQQyEn6rPsB71IyKNog5ypeVFaGrk1mk+zOirhMJe', $reg->certificate); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_PUBKEY_DECODE - */ - public function testDoRegisterBadKeyInCert() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABdsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_PUBKEY_DECODE - */ - public function testDoRegisterBadKey() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQMtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $request of doRegister() method only accepts object. - */ - public function testDoRegisterInvalidRequest() { - $req = 'request'; - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $response of doRegister() method only accepts object. - */ - public function testDoRegisterInvalidResponse() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = 'response'; - $this->u2f->doRegister($req, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_BAD_UA_RETURNING - */ - public function testDoRegisterUAError() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{"errorCode": "4"}'); - $this->u2f->doRegister($req, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $include_cert of doRegister() method only accepts boolean. - */ - public function testDoRegisterInvalidInclude_cert() { - $req = json_decode('{"version":"U2F_V2","challenge":"yKA0x075tjJ-GE7fKTfnzTOSaNUOWQxRd9TWz5aFOg8","appId":"http://demo.example.com"}'); - $resp = json_decode('{ "registrationData": "BQQtEmhWVgvbh-8GpjsHbj_d5FB9iNoRL8mNEq34-ANufKWUpVdIj6BSB_m3eMoZ3GqnaDy3RA5eWP8mhTkT1Ht3QAk1GsmaPIQgXgvrBkCQoQtMFvmwYPfW5jpRgoMPFxquHS7MTt8lofZkWAK2caHD-YQQdaRBgd22yWIjPuWnHOcwggLiMIHLAgEBMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBDQTAeFw0xNDA1MTUxMjU4NTRaFw0xNDA2MTQxMjU4NTRaMB0xGzAZBgNVBAMTEll1YmljbyBVMkYgVGVzdCBFRTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsK2_Uhx1zOY9ym4eglBg2U5idUGU-dJK8mGr6tmUQflaNxkQo6IOc-kV4T6L44BXrVeqN-dpCPr-KKlLYw650wDQYJKoZIhvcNAQELBQADggIBAJVAa1Bhfa2Eo7TriA_jMA8togoA2SUE7nL6Z99YUQ8LRwKcPkEpSpOsKYWJLaR6gTIoV3EB76hCiBaWN5HV3-CPyTyNsM2JcILsedPGeHMpMuWrbL1Wn9VFkc7B3Y1k3OmcH1480q9RpYIYr-A35zKedgV3AnvmJKAxVhv9GcVx0_CewHMFTryFuFOe78W8nFajutknarupekDXR4tVcmvj_ihJcST0j_Qggeo4_3wKT98CgjmBgjvKCd3Kqg8n9aSDVWyaOZsVOhZj3Fv5rFu895--D4qiPDETozJIyliH-HugoQpqYJaTX10mnmMdCa6aQeW9CEf-5QmbIP0S4uZAf7pKYTNmDQ5z27DVopqaFw00MIVqQkae_zSPX4dsNeeoTTXrwUGqitLaGap5ol81LKD9JdP3nSUYLfq0vLsHNDyNgb306TfbOenRRVsgQS8tJyLcknSKktWD_Qn7E5vjOXprXPrmdp7g5OPvrbz9QkWa1JTRfo2n2AXV02LPFc-UfR9bWCBEIJBxvmbpmqt0MnBTHWnth2b0CU_KJTDCY3kAPLGbOT8A4KiI73pRW-e9SWTaQXskw3Ei_dHRILM_l9OXsqoYHJ4Dd3tbfvmjoNYggSw4j50l3unI9d1qR5xlBFpW5sLr8gKX4bnY4SR2nyNiOQNLyPc0B0nW502aMEUCIQDTGOX-i_QrffJDY8XvKbPwMuBVrOSO-ayvTnWs_WSuDQIgZ7fMAvD_Ezyy5jg6fQeuOkoJi8V2naCtzV-HTly8Nww=", "clientData": "eyAiY2hhbGxlbmdlIjogInlLQTB4MDc1dGpKLUdFN2ZLVGZuelRPU2FOVU9XUXhSZDlUV3o1YUZPZzgiLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5maW5pc2hFbnJvbGxtZW50IiB9" }'); - $this->u2f->doRegister($req, $resp, 'bar'); - } - - public function testGetAuthenticateData() { - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg=="}')); - $data = $this->u2f->getAuthenticateData($regs); - $inst = $data[0]; - $this->assertEquals("U2F_V2", $inst->version); - $this->assertObjectHasAttribute("challenge", $inst); - $this->assertEquals('CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w', $inst->keyHandle); - $this->assertEquals('http://demo.example.com', $inst->appId); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $registrations of getAuthenticateData() method only accepts array of object. - */ - public function testGetAuthenticateDataInvalidRegistrations2() { - $regs = array('YubiKey NEO', 'YubiKey Standard'); - $data = $this->u2f->getAuthenticateData($regs); - } - - public function testDoAuthenticate() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":3}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w", "errorCode": 0 }'); - $data = $this->u2f->doAuthenticate($reqs, $regs, $resp); - $this->assertEquals(4, $data->counter); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_COUNTER_TOO_LOW - */ - public function testDoAuthenticateCtrFail() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":5}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_AUTHENTICATION_FAILURE - */ - public function testDoAuthenticateFail() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg=="}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAnG==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_NO_MATCHING_REQUEST - */ - public function testDoAuthenticateWrongReq() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"cTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg=="}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_NO_MATCHING_REGISTRATION - */ - public function testDoAuthenticateWrongReg() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"cTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg=="}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_PUBKEY_DECODE - */ - public function testDoAuthenticateBadKey() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"bC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":3}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $requests of doAuthenticate() method only accepts array of object. - */ - public function testDoAuthenticateInvalidRequests2() { - $reqs = array('YubiKey NEO', 'YubiKey Standard'); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":3}')); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $registrations of doAuthenticate() method only accepts array of object. - */ - public function testDoAuthenticateInvalidRegistrations2() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array('YubiKey NEO', 'YubiKey Standard'); - $resp = json_decode('{ "signatureData": "AQAAAAQwRQIhAI6FSrMD3KUUtkpiP0jpIEakql-HNhwWFngyw553pS1CAiAKLjACPOhxzZXuZsVO8im-HStEcYGC50PKhsGp_SUAng==", "clientData": "eyAiY2hhbGxlbmdlIjogImZFbmM5b1Y3OUVhQmdLNUJvTkVSVTVnUEtNMlhHWVdyejRmVWpnYzBRN2ciLCAib3JpZ2luIjogImh0dHA6XC9cL2RlbW8uZXhhbXBsZS5jb20iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24iIH0=", "keyHandle": "CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w" }'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage $response of doAuthenticate() method only accepts object. - */ - public function testDoAuthenticateInvalidResponse() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":3}')); - $resp = 'Response'; - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } - - /** - * @expectedException u2flib_server\Error - * @expectedExceptionCode u2flib_server\ERR_BAD_UA_RETURNING - */ - public function testDoAuthenticateUAError() { - $reqs = array(json_decode('{"version":"U2F_V2","challenge":"fEnc9oV79EaBgK5BoNERU5gPKM2XGYWrz4fUjgc0Q7g","keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","appId":"http://demo.example.com"}')); - $regs = array(json_decode('{"keyHandle":"CTUayZo8hCBeC-sGQJChC0wW-bBg99bmOlGCgw8XGq4dLsxO3yWh9mRYArZxocP5hBB1pEGB3bbJYiM-5acc5w","publicKey":"BC0SaFZWC9uH7wamOwduP93kUH2I2hEvyY0Srfj4A258pZSlV0iPoFIH+bd4yhncaqdoPLdEDl5Y\/yaFORPUe3c=","certificate":"MIIC4jCBywIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgQ0EwHhcNMTQwNTE1MTI1ODU0WhcNMTQwNjE0MTI1ODU0WjAdMRswGQYDVQQDExJZdWJpY28gVTJGIFRlc3QgRUUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATbCtv1IcdczmPcpuHoJQYNlOYnVBlPnSSvJhq+rZlEH5WjcZEKOiDnPpFeE+i+OAV61XqjfnaQj6\/iipS2MOudMA0GCSqGSIb3DQEBCwUAA4ICAQCVQGtQYX2thKO064gP4zAPLaIKANklBO5y+mffWFEPC0cCnD5BKUqTrCmFiS2keoEyKFdxAe+oQogWljeR1d\/gj8k8jbDNiXCC7HnTxnhzKTLlq2y9Vp\/VRZHOwd2NZNzpnB9ePNKvUaWCGK\/gN+cynnYFdwJ75iSgMVYb\/RnFcdPwnsBzBU68hbhTnu\/FvJxWo7rZJ2q7qXpA10eLVXJr4\/4oSXEk9I\/0IIHqOP98Ck\/fAoI5gYI7ygndyqoPJ\/Wkg1VsmjmbFToWY9xb+axbvPefvg+KojwxE6MySMpYh\/h7oKEKamCWk19dJp5jHQmumkHlvQhH\/uUJmyD9EuLmQH+6SmEzZg0Oc9uw1aKamhcNNDCFakJGnv80j1+HbDXnqE0168FBqorS2hmqeaJfNSyg\/SXT950lGC36tLy7BzQ8jYG99Ok32znp0UVbIEEvLSci3JJ0ipLVg\/0J+xOb4zl6a1z65nae4OTj7628\/UJFmtSU0X6Np9gF1dNizxXPlH0fW1ggRCCQcb5m6ZqrdDJwUx1p7Ydm9AlPyiUwwmN5ADyxmzk\/AOCoiO96UVvnvUlk2kF7JMNxIv3R0SCzP5fTl7KqGByeA3d7W375o6DWIIEsOI+dJd7pyPXdakecZQRaVubC6\/ICl+G52OEkdp8jYjkDS8j3NAdJ1udNmg==", "counter":3}')); - $resp = json_decode('{"errorCode": "5"}'); - $this->u2f->doAuthenticate($reqs, $regs, $resp); - } -} - -?> diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index a5e03672..7c651803 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -1,9 +1,11 @@ add('/web/js/build/' . $js_file); +} + +// Minify CSS +$css_minifier = new Minify\CSS(); +$css_dir = array_diff(scandir('/web/css/build'), array('..', '.')); +foreach ($css_dir as $css_file) { + $css_minifier->add('/web/css/build/' . $css_file); +} + // U2F API + T/HOTP API $u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']); -$tfa = new RobThree\Auth\TwoFactorAuth($OTP_LABEL); +$qrprovider = new RobThree\Auth\Providers\Qr\QRServerProvider(); +$tfa = new RobThree\Auth\TwoFactorAuth($OTP_LABEL, 6, 30, 'sha1', $qrprovider); // Redis $redis = new Redis(); @@ -27,31 +45,40 @@ $redis->connect('redis-mailcow', 6379); // PDO // Calculate offset -$now = new DateTime(); -$mins = $now->getOffset() / 60; -$sgn = ($mins < 0 ? -1 : 1); -$mins = abs($mins); -$hrs = floor($mins / 60); -$mins -= $hrs * 60; -$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); +// $now = new DateTime(); +// $mins = $now->getOffset() / 60; +// $sgn = ($mins < 0 ? -1 : 1); +// $mins = abs($mins); +// $hrs = floor($mins / 60); +// $mins -= $hrs * 60; +// $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); -$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; +$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, - PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "', group_concat_max_len = 3423543543;", + //PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "', group_concat_max_len = 3423543543;", ]; try { $pdo = new PDO($dsn, $database_user, $database_pass, $opt); } catch (PDOException $e) { +// Stop when SQL connection fails ?> -
    Connection to database failed.

    The following error was reported:
    getMessage();?>
    +
    Connection to database failed.

    The following error was reported:
    getMessage();?>
    +
    Connection to dockerapi container failed.

    The following error was reported:
    -
    + 'danger', @@ -64,12 +91,12 @@ function pdo_exception_handler($e) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__), - 'msg' => array('mysql_error', 'unknown error') + 'msg' => 'An unknown error occured: ' . print_r($e, true) ); return false; } } -set_exception_handler('pdo_exception_handler'); +set_exception_handler('exception_handler'); // TODO: Move function function get_remote_ip($anonymize = null) { @@ -99,14 +126,16 @@ function get_remote_ip($anonymize = null) { require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php'; +// IMAP lib +// use Ddeboer\Imap\Server; +// $imap_server = new Server('dovecot', 143, '/imap/tls/novalidate-cert'); + // Set language if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) { if ($DETECT_LANGUAGE && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $header_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); - foreach ($AVAILABLE_LANGUAGES as $available_lang) { - if ($header_lang == $available_lang) { - $_SESSION['mailcow_locale'] = strtolower(trim($header_lang)); - } + $header_lang = strtolower(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)); + if (in_array($header_lang, $AVAILABLE_LANGUAGES)) { + $_SESSION['mailcow_locale'] = $header_lang; } } else { @@ -114,7 +143,7 @@ if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) { } } if (isset($_COOKIE['mailcow_locale'])) { - $_SESSION['mailcow_locale'] = $_COOKIE['mailcow_locale']; + (preg_match('/^[a-z]{2}$/', $_COOKIE['mailcow_locale'])) ? $_SESSION['mailcow_locale'] = $_COOKIE['mailcow_locale'] : setcookie("mailcow_locale", "", time() - 300); } if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) { $_SESSION['mailcow_locale'] = $_GET['lang']; @@ -124,23 +153,34 @@ if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) { require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php'; include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quota_notification.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.dkim.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailq.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php'; -require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.relayhost.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.inc.php'; +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php'; init_db_schema(); if (isset($_SESSION['mailcow_cc_role'])) { - set_acl(); + // if ($_SESSION['mailcow_cc_role'] == 'user') { + // list($master_user, $master_passwd) = explode(':', file_get_contents('/etc/sogo/sieve.creds')); + // $imap_connection = $imap_server->authenticate($_SESSION['mailcow_cc_username'] . '*' . trim($master_user), trim($master_passwd)); + // $master_user = $master_passwd = null; + // } + acl('to_session'); } $UI_TEXTS = customize('get', 'ui_texts'); + diff --git a/data/web/inc/sessions.inc.php b/data/web/inc/sessions.inc.php index a3b81407..ddc997d1 100644 --- a/data/web/inc/sessions.inc.php +++ b/data/web/inc/sessions.inc.php @@ -1,22 +1,31 @@ prepare("SELECT `username`, `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';"); + $stmt = $pdo->prepare("SELECT `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';"); $stmt->execute(array( - ':api_key' => preg_replace('/[^A-Z0-9-]/i', '', $_SERVER['HTTP_X_API_KEY']) + ':api_key' => preg_replace('/[^a-zA-Z0-9-]/', '', $_SERVER['HTTP_X_API_KEY']) )); $api_return = $stmt->fetch(PDO::FETCH_ASSOC); - if (!empty($api_return['username'])) { + if (!empty($api_return['allow_from'])) { $remote = get_remote_ip(false); $allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $api_return['allow_from'])); if (in_array($remote, $allow_from)) { - $_SESSION['mailcow_cc_username'] = $api_return['username']; + $_SESSION['mailcow_cc_username'] = 'API'; $_SESSION['mailcow_cc_role'] = 'admin'; $_SESSION['mailcow_cc_api'] = true; } + else { + $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for API_USER by " . $_SERVER['REMOTE_ADDR']); + error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); + echo json_encode(array( + 'type' => 'error', + 'msg' => 'api access denied for ip ' . $_SERVER['REMOTE_ADDR'] + )); + unset($_POST); + die(); + } + } + else { + $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for API_USER by " . $_SERVER['REMOTE_ADDR']); + error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); + echo json_encode(array( + 'type' => 'error', + 'msg' => 'authentication failed' + )); + unset($_POST); + die(); } } // Update session cookie // setcookie(session_name() ,session_id(), time() + $SESSION_LIFETIME); +// Handle logouts +if (isset($_POST["logout"])) { + if (isset($_SESSION["dual-login"])) { + $_SESSION["mailcow_cc_username"] = $_SESSION["dual-login"]["username"]; + $_SESSION["mailcow_cc_role"] = $_SESSION["dual-login"]["role"]; + unset($_SESSION["dual-login"]); + header("Location: /mailbox"); + exit(); + } + else { + session_regenerate_id(true); + session_unset(); + session_destroy(); + session_write_close(); + header("Location: /"); + } +} + // Check session function session_check() { - if ($_SESSION['mailcow_cc_api'] === true) { + if (isset($_SESSION['mailcow_cc_api']) && $_SESSION['mailcow_cc_api'] === true) { return true; } if (!isset($_SESSION['SESS_REMOTE_UA']) || ($_SESSION['SESS_REMOTE_UA'] != $_SERVER['HTTP_USER_AGENT'])) { @@ -77,21 +124,3 @@ if (isset($_SESSION['mailcow_cc_role']) && session_check() === false) { $_POST = array(); $_FILES = array(); } - -// Handle logouts -if (isset($_POST["logout"])) { - if (isset($_SESSION["dual-login"])) { - $_SESSION["mailcow_cc_username"] = $_SESSION["dual-login"]["username"]; - $_SESSION["mailcow_cc_role"] = $_SESSION["dual-login"]["role"]; - unset($_SESSION["dual-login"]); - header("Location: /mailbox.php"); - exit(); - } - else { - session_regenerate_id(true); - session_unset(); - session_destroy(); - session_write_close(); - header("Location: /"); - } -} diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php index 4df1beca..9b622613 100644 --- a/data/web/inc/triggers.inc.php +++ b/data/web/inc/triggers.inc.php @@ -6,10 +6,18 @@ if (isset($_POST["verify_tfa_login"])) { unset($_SESSION['pending_mailcow_cc_username']); unset($_SESSION['pending_mailcow_cc_role']); unset($_SESSION['pending_tfa_method']); - header("Location: /user.php"); + header("Location: /user"); } } +if (isset($_POST["quick_release"])) { + quarantine('quick_release', $_POST["quick_release"]); +} + +if (isset($_POST["quick_delete"])) { + quarantine('quick_delete', $_POST["quick_delete"]); +} + if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) { $login_user = strtolower(trim($_POST["login_user"])); $as = check_login($login_user, $_POST["pass_user"]); @@ -17,19 +25,19 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) { $_SESSION['mailcow_cc_username'] = $login_user; $_SESSION['mailcow_cc_role'] = "admin"; $_SESSION['mailcow_cc_last_login'] = last_login($login_user); - header("Location: /admin.php"); + header("Location: /admin"); } elseif ($as == "domainadmin") { $_SESSION['mailcow_cc_username'] = $login_user; $_SESSION['mailcow_cc_role'] = "domainadmin"; $_SESSION['mailcow_cc_last_login'] = last_login($login_user); - header("Location: /mailbox.php"); + header("Location: /mailbox"); } elseif ($as == "user") { $_SESSION['mailcow_cc_username'] = $login_user; $_SESSION['mailcow_cc_role'] = "user"; $_SESSION['mailcow_cc_last_login'] = last_login($login_user); - header("Location: /user.php"); + header("Location: /user"); } elseif ($as != "pending") { unset($_SESSION['pending_mailcow_cc_username']); @@ -40,7 +48,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) { } } -if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") { +if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1") { if (isset($_GET["duallogin"])) { $duallogin = html_entity_decode(rawurldecode($_GET["duallogin"])); if (filter_var($duallogin, FILTER_VALIDATE_EMAIL)) { @@ -49,7 +57,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi $_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role']; $_SESSION['mailcow_cc_username'] = $duallogin; $_SESSION['mailcow_cc_role'] = "user"; - header("Location: /user.php"); + header("Location: /user"); } } else { @@ -58,7 +66,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi $_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role']; $_SESSION['mailcow_cc_username'] = $duallogin; $_SESSION['mailcow_cc_role'] = "domainadmin"; - header("Location: /user.php"); + header("Location: /user"); } } } @@ -93,5 +101,8 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi if (isset($_POST["rspamd_ui"])) { rspamd_ui('edit', $_POST); } + if (isset($_POST["mass_send"])) { + sys_mail($_POST); + } } ?> diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 4ac0df47..795fb3f3 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -9,6 +9,7 @@ This file will be reset on upgrades. // SQL database connection variables $database_type = 'mysql'; +$database_sock = '/var/run/mysqld/mysqld.sock'; $database_host = 'mysql'; $database_user = getenv('DBUSER'); $database_pass = getenv('DBPASS'); @@ -26,6 +27,7 @@ if ($https_port === FALSE) { } else { $https_port = substr($_SERVER['HTTP_HOST'], $https_port+1); } + // Alternatively select port here => //$https_port = 1234; // Other settings => @@ -41,18 +43,18 @@ $autodiscover_config = array( // The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable. 'imap' => array( 'server' => $mailcow_hostname, - 'port' => array_pop(explode(':', getenv('IMAPS_PORT'))), - 'tlsport' => array_pop(explode(':', getenv('IMAP_PORT'))), + 'port' => end(explode(':', getenv('IMAPS_PORT'))), + 'tlsport' => end(explode(':', getenv('IMAP_PORT'))), ), 'pop3' => array( 'server' => $mailcow_hostname, - 'port' => array_pop(explode(':', getenv('POPS_PORT'))), - 'tlsport' => array_pop(explode(':', getenv('POP_PORT'))), + 'port' => end(explode(':', getenv('POPS_PORT'))), + 'tlsport' => end(explode(':', getenv('POP_PORT'))), ), 'smtp' => array( 'server' => $mailcow_hostname, - 'port' => array_pop(explode(':', getenv('SMTPS_PORT'))), - 'tlsport' => array_pop(explode(':', getenv('SUBMISSION_PORT'))), + 'port' => end(explode(':', getenv('SMTPS_PORT'))), + 'tlsport' => end(explode(':', getenv('SUBMISSION_PORT'))), ), 'activesync' => array( 'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync', @@ -66,17 +68,16 @@ $autodiscover_config = array( 'port' => $https_port, ), ); -unset($https_port); // If false, we will use DEFAULT_LANG // Uses HTTP_ACCEPT_LANGUAGE header $DETECT_LANGUAGE = true; -// Change default language, "de", "en", "es", "nl", "pt", "ru" +// Change default language, "cs", "de", "en", "es", "nl", "pt", "ru" $DEFAULT_LANG = 'en'; // Available languages -$AVAILABLE_LANGUAGES = array('de', 'en', 'es', 'fr', 'lv', 'nl', 'pl', 'pt', 'ru', 'it', 'ca'); +$AVAILABLE_LANGUAGES = array('cs', 'de', 'en', 'es', 'fr', 'lv', 'nl', 'pl', 'pt', 'ru', 'it', 'ca'); // Change theme (default: lumen) // Needs to be one of those: cerulean, cosmo, cyborg, darkly, flatly, journal, lumen, paper, readable, sandstone, @@ -86,7 +87,12 @@ $AVAILABLE_LANGUAGES = array('de', 'en', 'es', 'fr', 'lv', 'nl', 'pl', 'pt', 'ru $DEFAULT_THEME = 'lumen'; // Password complexity as regular expression -$PASSWD_REGEP = '.{4,}'; +// Min. 6 characters +$PASSWD_REGEP = '.{6,}'; +// Min. 6 characters, which must include at least one uppercase letter, one lowercase letter and one number +// $PASSWD_REGEP = '^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,}$'; +// Min. 6 characters, which must include at least one letter and one number +// $PASSWD_REGEP = '^(?=.*[0-9])(?=.*[A-Za-z]).{6,}$'; // Show DKIM private keys - false by default $SHOW_DKIM_PRIV_KEYS = false; @@ -122,3 +128,25 @@ $DOCKER_TIMEOUT = 60; // Anonymize IPs logged via UI $ANONYMIZE_IPS = true; + +// MAILBOX_DEFAULT_ATTRIBUTES define default attributes for new mailboxes +// These settings will not change existing mailboxes + +// Force incoming TLS for new mailboxes by default +$MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in'] = false; + +// Force outgoing TLS for new mailboxes by default +$MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out'] = false; + +// Force password change on next login (only allows login to mailcow UI) +$MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false; + +// Enable SOGo access (set to false to disable access by default) +$MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true; + +// Send notification when quarantine is not empty (never, hourly, daily, weekly) +$MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'never'; + +// Default mailbox format, should not be changed unless you know exactly, what you do, keep the trailing ":" +// Check dovecot.conf for further changes (e.g. shared namespace) +$MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format'] = 'maildir:'; diff --git a/data/web/index.php b/data/web/index.php index 47339923..19372351 100644 --- a/data/web/index.php +++ b/data/web/index.php @@ -1,19 +1,20 @@ @@ -107,6 +108,6 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
    - add('/web/js/site/index.js'); +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; diff --git a/data/web/js/add.js b/data/web/js/add.js deleted file mode 100644 index cbc1d3f1..00000000 --- a/data/web/js/add.js +++ /dev/null @@ -1,23 +0,0 @@ -$(document).ready(function() { - // Auto-fill domain quota when adding new domain - auto_fill_quota = function(domain) { - $.get("/api/v1/get/domain/" + domain, function(data){ - var result = $.parseJSON(JSON.stringify(data)); - max_new_mailbox_quota = ( result.max_new_mailbox_quota / 1048576); - if (max_new_mailbox_quota != '0') { - $("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB'); - $('#addInputQuota').attr({"disabled": false, "value": "", "type": "number", "max": max_new_mailbox_quota}); - $('#addInputQuota').val(max_new_mailbox_quota); - } - else { - $("#quotaBadge").html('max. ' + max_new_mailbox_quota + ' MiB'); - $('#addInputQuota').attr({"disabled": true, "value": "", "type": "text", "value": "n/a"}); - $('#addInputQuota').val(max_new_mailbox_quota); - } - }); - } - $('#addSelectDomain').on('change', function() { - auto_fill_quota($('#addSelectDomain').val()); - }); - auto_fill_quota($('#addSelectDomain').val()); -}); diff --git a/data/web/js/admin.js b/data/web/js/admin.js deleted file mode 100644 index 24725f60..00000000 --- a/data/web/js/admin.js +++ /dev/null @@ -1,226 +0,0 @@ -// Base64 functions -var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,c,d="",C=0;for(r=Base64._utf8_encode(r);C>2,h=(3&t)<<4|(e=r.charCodeAt(C++))>>4,n=(15&e)<<2|(o=r.charCodeAt(C++))>>6,c=63&o,isNaN(e)?n=c=64:isNaN(o)&&(c=64),d=d+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(c);return d},decode:function(r){var t,e,o,a,h,n,c="",d=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");d>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(d++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(d++))),c+=String.fromCharCode(t),64!=h&&(c+=String.fromCharCode(e)),64!=n&&(c+=String.fromCharCode(o));return c=Base64._utf8_decode(c)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=c1=c2=0;e191&&o<224?(c2=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&c2),e+=2):(c2=r.charCodeAt(e+1),c3=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&c2)<<6|63&c3),e+=3);return t}}; -jQuery(function($){ - // http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery - var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; - function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} - function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e Test' + - ' ' + lang.edit + '' + - ' ' + lang.remove + '' + - ''; - item.chkbox = ''; - }); - } else if (table == 'forwardinghoststable') { - $.each(data, function (i, item) { - item.action = '
    ' + - ' ' + lang.remove + '' + - '
    '; - if (item.keep_spam == "yes") { - item.keep_spam = lang.no; - } - else { - item.keep_spam = lang.yes; - } - item.chkbox = ''; - }); - } else if (table == 'domainadminstable') { - $.each(data, function (i, item) { - item.selected_domains = escapeHtml(item.selected_domains.toString().replace(/,/g, " ")); - item.chkbox = ''; - item.action = ''; - }); - } - return data - }; - // Initial table drawings - draw_domain_admins(); - draw_fwd_hosts(); - draw_relayhosts(); - // Relayhost - $('#testRelayhostModal').on('show.bs.modal', function (e) { - $('#test_relayhost_result').text("-"); - button = $(e.relatedTarget) - if (button != null) { - $('#relayhost_id').val(button.data('relayhost-id')); - } - }) - $('#test_relayhost').on('click', function (e) { - e.preventDefault(); - prev = $('#test_relayhost').text(); - $(this).prop("disabled",true); - $(this).html(' '); - $.ajax({ - type: 'GET', - url: 'inc/ajax/relay_check.php', - dataType: 'text', - data: $('#test_relayhost_form').serialize(), - complete: function (data) { - $('#test_relayhost_result').html(data.responseText); - $('#test_relayhost').prop("disabled",false); - $('#test_relayhost').text(prev); - } - }); - }) - // DKIM private key modal - $('#showDKIMprivKey').on('show.bs.modal', function (e) { - $('#priv_key_pre').text("-"); - p_related = $(e.relatedTarget) - if (p_related != null) { - var decoded_key = Base64.decode((p_related.data('priv-key'))); - $('#priv_key_pre').text(decoded_key); - } - }) - // App links - function add_table_row(table_id) { - var row = $(''); - cols = ''; - cols += ''; - cols += 'Remove row'; - row.append(cols); - table_id.append(row); - } - $('#app_link_table').on('click', 'tr a', function (e) { - e.preventDefault(); - $(this).parents('tr').remove(); - }); - $('#add_app_link_row').click(function() { - add_table_row($('#app_link_table')); - }); -}); -$(window).load(function(){ - initial_width = $("#sidebar-admin").width(); - $("#scrollbox").css("width", initial_width); - if (sessionStorage.scrollTop > 70) { - $('#scrollbox').addClass('scrollboxFixed'); - } - $(window).bind('scroll', function() { - if ($(window).scrollTop() > 70) { - $('#scrollbox').addClass('scrollboxFixed'); - } else { - $('#scrollbox').removeClass('scrollboxFixed'); - } - }); -}); -function resizeScrollbox() { - on_resize_width = $("#sidebar-admin").width(); - $("#scrollbox").removeAttr("style"); - $("#scrollbox").css("width", on_resize_width); -} -$(window).on('resize', resizeScrollbox); -$('a[data-toggle="tab"]').on('shown.bs.tab', resizeScrollbox); diff --git a/data/web/js/bootstrap-slider.min.js b/data/web/js/bootstrap-slider.min.js deleted file mode 100644 index 72363a27..00000000 --- a/data/web/js/bootstrap-slider.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! ======================================================= - VERSION 9.7.2 -========================================================= */ -"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},windowIsDefined="object"===("undefined"==typeof window?"undefined":_typeof(window));!function(a){if("function"==typeof define&&define.amd)define(["jquery"],a);else if("object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports){var b;try{b=require("jquery")}catch(c){b=null}module.exports=a(b)}else window&&(window.Slider=a(window.jQuery))}(function(a){var b="slider",c="bootstrapSlider";windowIsDefined&&!window.console&&(window.console={}),windowIsDefined&&!window.console.log&&(window.console.log=function(){}),windowIsDefined&&!window.console.warn&&(window.console.warn=function(){});var d;return function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function e(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}this._state={value:null,enabled:null,offset:null,size:null,percentage:null,inDrag:!1,over:!1},this.ticksCallbackMap={},this.handleCallbackMap={},"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var e=Object.keys(this.defaultOptions),f=0;f0)for(var s=0;s0){for(this.ticksContainer=document.createElement("div"),this.ticksContainer.className="slider-tick-container",f=0;f0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",f=0;f0&&(this.options.max=Math.max.apply(Math,this.options.ticks),this.options.min=Math.min.apply(Math,this.options.ticks)),Array.isArray(this.options.value)?(this.options.range=!0,this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value,this.options.max]:this._state.value=this.options.value,this.trackLow=k||this.trackLow,this.trackSelection=j||this.trackSelection,this.trackHigh=l||this.trackHigh,"none"===this.options.selection?(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")):("after"===this.options.selection||"before"===this.options.selection)&&(this._removeClass(this.trackLow,"hide"),this._removeClass(this.trackSelection,"hide"),this._removeClass(this.trackHigh,"hide")),this.handle1=m||this.handle1,this.handle2=n||this.handle2,p===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),f=0;f0){for(var d,e,f,g=0,h=1;hthis.options.max?this.options.max:k},toPercentage:function(a){if(this.options.max===this.options.min)return 0;if(this.options.ticks_positions.length>0){for(var b,c,d,e=0,f=0;f0?this.options.ticks[f-1]:0,d=f>0?this.options.ticks_positions[f-1]:0,c=this.options.ticks[f],e=this.options.ticks_positions[f];break}if(f>0){var g=(a-b)/(c-b);return d+g*(e-d)}}return 100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=0===this.options.min?0:Math.log(this.options.min),c=Math.log(this.options.max),d=Math.exp(b+(c-b)*a/100);return d=this.options.min+Math.round((d-this.options.min)/this.options.step)*this.options.step,dthis.options.max?this.options.max:d},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=Math.log(this.options.max),c=0===this.options.min?0:Math.log(this.options.min),d=0===a?0:Math.log(a);return 100*(d-c)/(b-c)}}};d=function(a,b){return e.call(this,a,b),this},d.prototype={_init:function(){},constructor:d,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,handle:"round",reversed:!1,rtl:"auto",enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_positions:[],ticks_labels:[],ticks_snap_bounds:0,ticks_tooltip:!1,scale:"linear",focus:!1,tooltip_position:null,labelledby:null,rangeHighlights:[]},getElement:function(){return this.sliderElem},getValue:function(){return this.options.range?this._state.value:this._state.value[0]},setValue:function(a,b,c){a||(a=0);var d=this.getValue();this._state.value=this._validateInputValue(a);var e=this._applyPrecision.bind(this);this.options.range?(this._state.value[0]=e(this._state.value[0]),this._state.value[1]=e(this._state.value[1]),this._state.value[0]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[0])),this._state.value[1]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[1]))):(this._state.value=e(this._state.value),this._state.value=[Math.max(this.options.min,Math.min(this.options.max,this._state.value))],this._addClass(this.handle2,"hide"),"after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min),this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]),this._toPercentage(this._state.value[1]),100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0,0,100],this._layout();var f=this.options.range?this._state.value:this._state.value[0];return this._setDataVal(f),b===!0&&this._trigger("slide",f),d!==f&&c===!0&&this._trigger("change",{oldValue:d,newValue:f}),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),this.$element.removeData("slider"))},disable:function(){return this._state.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this._state.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this._state.enabled?this.disable():this.enable(),this},isEnabled:function(){return this._state.enabled},on:function(a,b){return this._bindNonQueryEventHandler(a,b),this},off:function(b,c){a?(this.$element.off(b,c),this.$sliderElem.off(b,c)):this._unbindNonQueryEventHandler(b,c)},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(){return this._removeSliderEventHandlers(),e.call(this,this.element,this.options),a&&a.data(this.element,"slider",this),this},relayout:function(){return this._resize(),this._layout(),this},_removeSliderEventHandlers:function(){if(this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.options.ticks_tooltip){for(var a=this.ticksContainer.getElementsByClassName("slider-tick"),b=0;b=0?c:this.attributes["aria-valuenow"].value,e=parseInt(d,10);b.value[0]=e,b.percentage[0]=a.options.ticks_positions[e],a._setToolTipOnMouseOver(b),a._showTooltip()};return b.addEventListener("mouseenter",d,!1),d},addMouseLeave:function(a,b){var c=function(){a._hideTooltip()};return b.addEventListener("mouseleave",c,!1),c}}},_layout:function(){var a;if(a=this.options.reversed?[100-this._state.percentage[0],this.options.range?100-this._state.percentage[1]:this._state.percentage[1]]:[this._state.percentage[0],this._state.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle1.setAttribute("aria-valuenow",this._state.value[0]),isNaN(this.options.formatter(this._state.value[0]))&&this.handle1.setAttribute("aria-valuetext",this.options.formatter(this._state.value[0])),this.handle2.style[this.stylePos]=a[1]+"%",this.handle2.setAttribute("aria-valuenow",this._state.value[1]),isNaN(this.options.formatter(this._state.value[1]))&&this.handle2.setAttribute("aria-valuetext",this.options.formatter(this._state.value[1])),this.rangeHighlightElements.length>0&&Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var b=0;b0){var g,h="vertical"===this.options.orientation?"height":"width";g="vertical"===this.options.orientation?"marginTop":this.options.rtl?"marginRight":"marginLeft";var i=this._state.size/(this.options.ticks.length-1);if(this.tickLabelContainer){var j=0;if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[g]=-i/2+"px"),j=this.tickLabelContainer.offsetHeight;else for(k=0;kj&&(j=this.tickLabelContainer.childNodes[k].offsetHeight);"horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=j+"px")}for(var k=0;k=a[0]&&l<=a[1]&&this._addClass(this.ticks[k],"in-selection"):"after"===this.options.selection&&l>=a[0]?this._addClass(this.ticks[k],"in-selection"):"before"===this.options.selection&&l<=a[0]&&this._addClass(this.ticks[k],"in-selection"),this.tickLabels[k]&&(this.tickLabels[k].style[h]=i+"px","vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[k]?(this.tickLabels[k].style.position="absolute",this.tickLabels[k].style[this.stylePos]=l+"%",this.tickLabels[k].style[g]=-i/2+"px"):"vertical"===this.options.orientation&&(this.options.rtl?this.tickLabels[k].style.marginRight=this.sliderElem.offsetWidth+"px":this.tickLabels[k].style.marginLeft=this.sliderElem.offsetWidth+"px",this.tickLabelContainer.style[g]=this.sliderElem.offsetWidth/2*-1+"px"))}}var m;if(this.options.range){m=this.options.formatter(this._state.value),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetWidth/2+"px");var n=this.options.formatter(this._state.value[0]);this._setText(this.tooltipInner_min,n);var o=this.options.formatter(this._state.value[1]);this._setText(this.tooltipInner_max,o),this.tooltip_min.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip_min,"margin-"+this.stylePos,-this.tooltip_min.offsetHeight/2+"px"):this._css(this.tooltip_min,"margin-"+this.stylePos,-this.tooltip_min.offsetWidth/2+"px"),this.tooltip_max.style[this.stylePos]=a[1]+"%","vertical"===this.options.orientation?this._css(this.tooltip_max,"margin-"+this.stylePos,-this.tooltip_max.offsetHeight/2+"px"):this._css(this.tooltip_max,"margin-"+this.stylePos,-this.tooltip_max.offsetWidth/2+"px")}else m=this.options.formatter(this._state.value[0]),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetWidth/2+"px");if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{"right"===this.stylePos?this.trackLow.style.right="0":this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%","right"===this.stylePos?this.trackSelection.style.right=Math.min(a[0],a[1])+"%":this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%","right"===this.stylePos?this.trackHigh.style.left="0":this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var p=this.tooltip_min.getBoundingClientRect(),q=this.tooltip_max.getBoundingClientRect();"bottom"===this.options.tooltip_position?p.right>q.left?(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top="",this.tooltip_max.style.bottom="22px"):(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top=this.tooltip_min.style.top,this.tooltip_max.style.bottom=""):p.right>q.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}},_createHighlightRange:function(a,b){return this._isHighlightRange(a,b)?a>b?{start:b,size:a-b}:{start:a,size:b-a}:null},_isHighlightRange:function(a,b){return a>=0&&100>=a&&b>=0&&100>=b?!0:!1},_resize:function(a){this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this._layout()},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this._state.enabled)return!1;this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this._state.percentage[0]-b),d=Math.abs(this._state.percentage[1]-b);this._state.dragged=d>c?0:1,this._adjustPercentageForRangeSliders(b)}else this._state.dragged=0;this._state.percentage[this._state.dragged]=b,this._layout(),this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this._setDataVal(e),this.setValue(e,!1,!0),a.returnValue=!1,this.options.focus&&this._triggerFocusOnHandle(this._state.dragged),!0},_touchstart:function(a){if(void 0===a.changedTouches)return void this._mousedown(a);var b=a.changedTouches[0];this.touchX=b.pageX,this.touchY=b.pageY},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this._state.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="vertical"===this.options.orientation&&!this.options.reversed,e="horizontal"===this.options.orientation&&this.options.reversed;(d||e)&&(c=-c)}var f=this._state.value[a]+c*this.options.step,g=f/this.options.max*100;if(this._state.keyCtrl=a,this.options.range){this._adjustPercentageForRangeSliders(g);var h=this._state.keyCtrl?this._state.value[0]:f,i=this._state.keyCtrl?f:this._state.value[1];f=[h,i]}return this._trigger("slideStart",f),this._setDataVal(f),this.setValue(f,!0,!0),this._setDataVal(f),this._trigger("slideStop",f),this._layout(),this._pauseEvent(b),delete this._state.keyCtrl,!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this._state.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b,this._layout();var c=this._calculateValue(!0);return this.setValue(c,!0,!0),!1},_touchmove:function(a){if(void 0!==a.changedTouches){var b=a.changedTouches[0],c=b.pageX-this.touchX,d=b.pageY-this.touchY;this._state.inDrag||("vertical"===this.options.orientation&&5>=c&&c>=-5&&(d>=15||-15>=d)?this._mousedown(a):5>=d&&d>=-5&&(c>=15||-15>=c)&&this._mousedown(a))}},_adjustPercentageForRangeSliders:function(a){if(this.options.range){var b=this._getNumDigitsAfterDecimalPlace(a);b=b?b-1:0;var c=this._applyToFixedAndParseFloat(a,b);0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1],b)c?(this._state.percentage[1]=this._state.percentage[0],this._state.dragged=0):0===this._state.keyCtrl&&this._state.value[1]/this.options.max*100a&&(this._state.percentage[1]=this._state.percentage[0],this._state.keyCtrl=0,this.handle1.focus())}},_mouseup:function(){if(!this._state.enabled)return!1;this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!1,this._state.over===!1&&this._hideTooltip();var a=this._calculateValue(!0);return this._layout(),this._setDataVal(a),this._trigger("slideStop",a),!1},_calculateValue:function(a){var b;if(this.options.range?(b=[this.options.min,this.options.max],0!==this._state.percentage[0]&&(b[0]=this._toValue(this._state.percentage[0]),b[0]=this._applyPrecision(b[0])),100!==this._state.percentage[1]&&(b[1]=this._toValue(this._state.percentage[1]),b[1]=this._applyPrecision(b[1]))):(b=this._toValue(this._state.percentage[0]),b=parseFloat(b),b=this._applyPrecision(b)),a){for(var c=[b,1/0],d=0;dh;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function e(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}this._state={value:null,enabled:null,offset:null,size:null,percentage:null,inDrag:!1,over:!1,tickIndex:null},this.ticksCallbackMap={},this.handleCallbackMap={},"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var e=Object.keys(this.defaultOptions),f=c.hasOwnProperty("min"),g=c.hasOwnProperty("max"),i=0;i0,this.ticksAreValid||(this.options.lock_to_ticks=!1),"auto"===this.options.rtl){var l=window.getComputedStyle(this.element);null!=l?this.options.rtl="rtl"===l.direction:this.options.rtl="rtl"===this.element.style.direction}"vertical"!==this.options.orientation||"top"!==this.options.tooltip_position&&"bottom"!==this.options.tooltip_position?"horizontal"!==this.options.orientation||"left"!==this.options.tooltip_position&&"right"!==this.options.tooltip_position||(this.options.tooltip_position="top"):this.options.rtl?this.options.tooltip_position="left":this.options.tooltip_position="right";var m,n,o,p,q,r=this.element.style.width,s=!1,t=this.element.parentNode;if(this.sliderElem)s=!0;else{this.sliderElem=document.createElement("div"),this.sliderElem.className="slider";var u=document.createElement("div");u.className="slider-track",n=document.createElement("div"),n.className="slider-track-low",m=document.createElement("div"),m.className="slider-selection",o=document.createElement("div"),o.className="slider-track-high",p=document.createElement("div"),p.className="slider-handle min-slider-handle",p.setAttribute("role","slider"),p.setAttribute("aria-valuemin",this.options.min),p.setAttribute("aria-valuemax",this.options.max),q=document.createElement("div"),q.className="slider-handle max-slider-handle",q.setAttribute("role","slider"),q.setAttribute("aria-valuemin",this.options.min),q.setAttribute("aria-valuemax",this.options.max),u.appendChild(n),u.appendChild(m),u.appendChild(o),this.rangeHighlightElements=[];var v=this.options.rangeHighlights;if(Array.isArray(v)&&v.length>0)for(var w=0;w0){for(this.ticksContainer=document.createElement("div"),this.ticksContainer.className="slider-tick-container",i=0;i0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",i=0;i0&&(g||(this.options.max=Math.max.apply(Math,this.options.ticks)),f||(this.options.min=Math.min.apply(Math,this.options.ticks))),Array.isArray(this.options.value)?(this.options.range=!0,this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value,this.options.max]:this._state.value=this.options.value,this.trackLow=n||this.trackLow,this.trackSelection=m||this.trackSelection,this.trackHigh=o||this.trackHigh,"none"===this.options.selection?(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")):("after"===this.options.selection||"before"===this.options.selection)&&(this._removeClass(this.trackLow,"hide"),this._removeClass(this.trackSelection,"hide"),this._removeClass(this.trackHigh,"hide")),this.handle1=p||this.handle1,this.handle2=q||this.handle2,s===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),i=0;ib.max?b.max:a},toValue:function(a){var b=a/100*(this.options.max-this.options.min),c=!0;if(this.options.ticks_positions.length>0){for(var d,e,f,g=0,i=1;i0){for(var b,c,d,e=0,f=0;f0?this.options.ticks[f-1]:0,d=f>0?this.options.ticks_positions[f-1]:0,c=this.options.ticks[f],e=this.options.ticks_positions[f];break}if(f>0){var g=(a-b)/(c-b);return d+g*(e-d)}}return 100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=1-this.options.min,c=Math.log(this.options.min+b),d=Math.log(this.options.max+b),e=Math.exp(c+(d-c)*a/100)-b;return Math.round(e)===d?d:(e=this.options.min+Math.round((e-this.options.min)/this.options.step)*this.options.step,h.linear.getValue(e,this.options))},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=1-this.options.min,c=Math.log(this.options.max+b),d=Math.log(this.options.min+b),e=Math.log(a+b);return 100*(e-d)/(c-d)}}};d=function(a,b){return e.call(this,a,b),this},d.prototype={_init:function(){},constructor:d,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,lock_to_ticks:!1,handle:"round",reversed:!1,rtl:"auto",enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_positions:[],ticks_labels:[],ticks_snap_bounds:0,ticks_tooltip:!1,scale:"linear",focus:!1,tooltip_position:null,labelledby:null,rangeHighlights:[]},getElement:function(){return this.sliderElem},getValue:function(){return this.options.range?this._state.value:this._state.value[0]},setValue:function(a,b,c){a||(a=0);var d=this.getValue();this._state.value=this._validateInputValue(a);var e=this._applyPrecision.bind(this);this.options.range?(this._state.value[0]=e(this._state.value[0]),this._state.value[1]=e(this._state.value[1]),this.ticksAreValid&&this.options.lock_to_ticks&&(this._state.value[0]=this.options.ticks[this._getClosestTickIndex(this._state.value[0])],this._state.value[1]=this.options.ticks[this._getClosestTickIndex(this._state.value[1])]),this._state.value[0]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[0])),this._state.value[1]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[1]))):(this._state.value=e(this._state.value),this.ticksAreValid&&this.options.lock_to_ticks&&(this._state.value=this.options.ticks[this._getClosestTickIndex(this._state.value)]),this._state.value=[Math.max(this.options.min,Math.min(this.options.max,this._state.value))],this._addClass(this.handle2,"hide"),"after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min),this._setTickIndex(),this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]),this._toPercentage(this._state.value[1]),100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0,0,100],this._layout();var f=this.options.range?this._state.value:this._state.value[0];this._setDataVal(f),b===!0&&this._trigger("slide",f);var g=!1;return g=Array.isArray(f)?d[0]!==f[0]||d[1]!==f[1]:d!==f,g&&c===!0&&this._trigger("change",{oldValue:d,newValue:f}),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),f===b&&this.$element.removeData(f),this.$element.removeData(c))},disable:function(){return this._state.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this._state.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this._state.enabled?this.disable():this.enable(),this},isEnabled:function(){return this._state.enabled},on:function(a,b){return this._bindNonQueryEventHandler(a,b),this},off:function(b,c){a?(this.$element.off(b,c),this.$sliderElem.off(b,c)):this._unbindNonQueryEventHandler(b,c)},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(d){var g=this.getValue();return this._removeSliderEventHandlers(),e.call(this,this.element,this.options),d&&d.useCurrentValue===!0&&this.setValue(g),a&&(f===b?(a.data(this.element,b,this),a.data(this.element,c,this)):a.data(this.element,c,this)),this},relayout:function(){return this._resize(),this},_removeTooltipListener:function(a,b){this.handle1.removeEventListener(a,b,!1),this.handle2.removeEventListener(a,b,!1)},_removeSliderEventHandlers:function(){if(this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.options.ticks_tooltip){for(var a=this.ticksContainer.getElementsByClassName("slider-tick"),b=0;b0&&a.options.ticks_positions[c]||a._toPercentage(a.options.ticks[c])):f=a._toPercentage(e),d.value[0]=e,d.percentage[0]=f,a._setToolTipOnMouseOver(d),a._showTooltip()};return b.addEventListener("mouseenter",d,!1),d},addMouseLeave:function(a,b){var c=function(){a._hideTooltip()};return b.addEventListener("mouseleave",c,!1),c}}},_layout:function(){var a,b;if(a=this.options.reversed?[100-this._state.percentage[0],this.options.range?100-this._state.percentage[1]:this._state.percentage[1]]:[this._state.percentage[0],this._state.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle1.setAttribute("aria-valuenow",this._state.value[0]),b=this.options.formatter(this._state.value[0]),isNaN(b)?this.handle1.setAttribute("aria-valuetext",b):this.handle1.removeAttribute("aria-valuetext"),this.handle2.style[this.stylePos]=a[1]+"%",this.handle2.setAttribute("aria-valuenow",this._state.value[1]),b=this.options.formatter(this._state.value[1]),isNaN(b)?this.handle2.setAttribute("aria-valuetext",b):this.handle2.removeAttribute("aria-valuetext"),this.rangeHighlightElements.length>0&&Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var c=0;c0){var h,i="vertical"===this.options.orientation?"height":"width";h="vertical"===this.options.orientation?"marginTop":this.options.rtl?"marginRight":"marginLeft";var j=this._state.size/(this.options.ticks.length-1);if(this.tickLabelContainer){var k=0;if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[h]=-j/2+"px"),k=this.tickLabelContainer.offsetHeight;else for(l=0;lk&&(k=this.tickLabelContainer.childNodes[l].offsetHeight);"horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=k+"px")}for(var l=0;l=a[0]&&m<=a[1]&&this._addClass(this.ticks[l],"in-selection"):"after"===this.options.selection&&m>=a[0]?this._addClass(this.ticks[l],"in-selection"):"before"===this.options.selection&&m<=a[0]&&this._addClass(this.ticks[l],"in-selection"),this.tickLabels[l]&&(this.tickLabels[l].style[i]=j+"px","vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[l]?(this.tickLabels[l].style.position="absolute",this.tickLabels[l].style[this.stylePos]=m+"%",this.tickLabels[l].style[h]=-j/2+"px"):"vertical"===this.options.orientation&&(this.options.rtl?this.tickLabels[l].style.marginRight=this.sliderElem.offsetWidth+"px":this.tickLabels[l].style.marginLeft=this.sliderElem.offsetWidth+"px",this.tickLabelContainer.style[h]=this.sliderElem.offsetWidth/2*-1+"px"),this._removeClass(this.tickLabels[l],"label-in-selection label-is-selection"),this.options.range?m>=a[0]&&m<=a[1]&&(this._addClass(this.tickLabels[l],"label-in-selection"),(m===a[0]||a[1])&&this._addClass(this.tickLabels[l],"label-is-selection")):("after"===this.options.selection&&m>=a[0]?this._addClass(this.tickLabels[l],"label-in-selection"):"before"===this.options.selection&&m<=a[0]&&this._addClass(this.tickLabels[l],"label-in-selection"),m===a[0]&&this._addClass(this.tickLabels[l],"label-is-selection")))}}var n;if(this.options.range){n=this.options.formatter(this._state.value),this._setText(this.tooltipInner,n),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%";var o=this.options.formatter(this._state.value[0]);this._setText(this.tooltipInner_min,o);var p=this.options.formatter(this._state.value[1]);this._setText(this.tooltipInner_max,p),this.tooltip_min.style[this.stylePos]=a[0]+"%",this.tooltip_max.style[this.stylePos]=a[1]+"%"}else n=this.options.formatter(this._state.value[0]),this._setText(this.tooltipInner,n),this.tooltip.style[this.stylePos]=a[0]+"%";if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{"right"===this.stylePos?this.trackLow.style.right="0":this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%","right"===this.stylePos?this.trackSelection.style.right=Math.min(a[0],a[1])+"%":this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%","right"===this.stylePos?this.trackHigh.style.left="0":this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var q=this.tooltip_min.getBoundingClientRect(),r=this.tooltip_max.getBoundingClientRect();"bottom"===this.options.tooltip_position?q.right>r.left?(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top="",this.tooltip_max.style.bottom="22px"):(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top=this.tooltip_min.style.top,this.tooltip_max.style.bottom=""):q.right>r.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}},_createHighlightRange:function(a,b){return this._isHighlightRange(a,b)?a>b?{start:b,size:a-b}:{start:a,size:b-a}:null},_isHighlightRange:function(a,b){return a>=0&&100>=a&&b>=0&&100>=b?!0:!1},_resize:function(a){this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this._layout()},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this._state.enabled)return!1;a.preventDefault&&a.preventDefault(),this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this._state.percentage[0]-b),d=Math.abs(this._state.percentage[1]-b);this._state.dragged=d>c?0:1,this._adjustPercentageForRangeSliders(b)}else this._state.dragged=0;this._state.percentage[this._state.dragged]=b,this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this.setValue(e,!1,!0),a.returnValue=!1,this.options.focus&&this._triggerFocusOnHandle(this._state.dragged),!0},_touchstart:function(a){this._mousedown(a)},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this._state.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="horizontal"===this.options.orientation,e="vertical"===this.options.orientation,f=this.options.rtl,g=this.options.reversed;d?f?g||(c=-c):g&&(c=-c):e&&(g||(c=-c))}var h;if(this.ticksAreValid&&this.options.lock_to_ticks){var i=void 0;i=this.options.ticks.indexOf(this._state.value[a]),-1===i&&(i=0,window.console.warn("(lock_to_ticks) _keydown: index should not be -1")),i+=c,i=Math.max(0,Math.min(this.options.ticks.length-1,i)),h=this.options.ticks[i]}else h=this._state.value[a]+c*this.options.step;var j=this._toPercentage(h);if(this._state.keyCtrl=a,this.options.range){this._adjustPercentageForRangeSliders(j);var k=this._state.keyCtrl?this._state.value[0]:h,l=this._state.keyCtrl?h:this._state.value[1];h=[Math.max(this.options.min,Math.min(this.options.max,k)),Math.max(this.options.min,Math.min(this.options.max,l))]}else h=Math.max(this.options.min,Math.min(this.options.max,h));return this._trigger("slideStart",h),this.setValue(h,!0,!0),this._trigger("slideStop",h),this._pauseEvent(b),delete this._state.keyCtrl,!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this._state.enabled)return!1; +var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b;var c=this._calculateValue(!0);return this.setValue(c,!0,!0),!1},_touchmove:function(a){void 0!==a.changedTouches&&a.preventDefault&&a.preventDefault()},_adjustPercentageForRangeSliders:function(a){if(this.options.range){var b=this._getNumDigitsAfterDecimalPlace(a);b=b?b-1:0;var c=this._applyToFixedAndParseFloat(a,b);0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1],b)c?(this._state.percentage[1]=this._state.percentage[0],this._state.dragged=0):0===this._state.keyCtrl&&this._toPercentage(this._state.value[1])a&&(this._state.percentage[1]=this._state.percentage[0],this._state.keyCtrl=0,this.handle1.focus())}},_mouseup:function(a){if(!this._state.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b,this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!1,this._state.over===!1&&this._hideTooltip();var c=this._calculateValue(!0);return this.setValue(c,!1,!0),this._trigger("slideStop",c),this._state.dragged=null,!1},_setValues:function(a,b){var c=0===a?0:100;this._state.percentage[a]!==c&&(b.data[a]=this._toValue(this._state.percentage[a]),b.data[a]=this._applyPrecision(b.data[a]))},_calculateValue:function(a){var b={};return this.options.range?(b.data=[this.options.min,this.options.max],this._setValues(0,b),this._setValues(1,b),a&&(b.data[0]=this._snapToClosestTick(b.data[0]),b.data[1]=this._snapToClosestTick(b.data[1]))):(b.data=this._toValue(this._state.percentage[0]),b.data=parseFloat(b.data),b.data=this._applyPrecision(b.data),a&&(b.data=this._snapToClosestTick(b.data))),b.data},_snapToClosestTick:function(a){for(var b=[a,1/0],c=0;ce&&(b=e,c=d)}return c},_setTickIndex:function(){this.ticksAreValid&&(this._state.tickIndex=[this.options.ticks.indexOf(this._state.value[0]),this.options.ticks.indexOf(this._state.value[1])])}},a&&a.fn&&(a.fn.slider?(windowIsDefined&&window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSlider namespace instead."),f=c):(a.bridget(b,d),f=b),a.bridget(c,d),a(function(){a("input[data-provide=slider]")[f]()}))}(a),d}); \ No newline at end of file diff --git a/data/web/js/bootstrap-select.min.js b/data/web/js/build/004-bootstrap-select.min.js similarity index 99% rename from data/web/js/bootstrap-select.min.js rename to data/web/js/build/004-bootstrap-select.min.js index 9e20a22e..14572226 100644 --- a/data/web/js/bootstrap-select.min.js +++ b/data/web/js/build/004-bootstrap-select.min.js @@ -5,4 +5,4 @@ * Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE) */ !function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b?b.replace(this.re,this.ch):""}),b}function c(b){var c=arguments,d=b;[].shift.apply(c);var e,f=this.each(function(){var b=a(this);if(b.is("select")){var f=b.data("selectpicker"),g="object"==typeof d&&d;if(f){if(g)for(var h in g)g.hasOwnProperty(h)&&(f.options[h]=g[h])}else{var i=a.extend({},k.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),g);i.template=a.extend({},k.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,g.template),b.data("selectpicker",f=new k(this,i))}"string"==typeof d&&(e=f[d]instanceof Function?f[d].apply(f,c):f.options[d])}});return"undefined"!=typeof e?e:f}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(a){}return c}(),c="".indexOf,d=function(b){if(null==this)throw new TypeError;var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw new TypeError;var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return!(g+j>e)&&c.call(d,f,i)!=-1};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(a){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j":">",'"':""","'":"'","`":"`"},g={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},h=function(a){var b=function(b){return a[b]},c="(?:"+Object.keys(a).join("|")+")",d=RegExp(c),e=RegExp(c,"g");return function(a){return a=null==a?"":""+a,d.test(a)?a.replace(e,b):a}},i=h(f),j=h(g),k=function(b,c){d.useDefault||(a.valHooks.select.set=d._set,d.useDefault=!0),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title"));var e=this.options.windowPadding;"number"==typeof e&&(this.options.windowPadding=[e,e,e,e]),this.val=k.prototype.val,this.render=k.prototype.render,this.refresh=k.prototype.refresh,this.setStyle=k.prototype.setStyle,this.selectAll=k.prototype.selectAll,this.deselectAll=k.prototype.deselectAll,this.destroy=k.prototype.destroy,this.remove=k.prototype.remove,this.show=k.prototype.show,this.hide=k.prototype.hide,this.init()};k.VERSION="1.12.2",k.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",showTick:!1,template:{caret:''},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1,windowPadding:0},k.prototype={constructor:k,init:function(){var b=this,c=this.$element.attr("id");this.$element.addClass("bs-select-hidden"),this.liObj={},this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createView(),this.$element.after(this.$newElement).appendTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(".dropdown-menu"),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element.removeClass("bs-select-hidden"),this.options.dropdownAlignRight===!0&&this.$menu.addClass("dropdown-menu-right"),"undefined"!=typeof c&&(this.$button.attr("data-id",c),a('label[for="'+c+'"]').click(function(a){a.preventDefault(),b.$button.focus()})),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.setStyle(),this.setWidth(),this.options.container&&this.selectPosition(),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(a){b.$menuInner.attr("aria-expanded",!1),b.$element.trigger("hide.bs.select",a)},"hidden.bs.dropdown":function(a){b.$element.trigger("hidden.bs.select",a)},"show.bs.dropdown":function(a){b.$menuInner.attr("aria-expanded",!0),b.$element.trigger("show.bs.select",a)},"shown.bs.dropdown":function(a){b.$element.trigger("shown.bs.select",a)}}),b.$element[0].hasAttribute("required")&&this.$element.on("invalid",function(){b.$button.addClass("bs-invalid").focus(),b.$element.on({"focus.bs.select":function(){b.$button.focus(),b.$element.off("focus.bs.select")},"shown.bs.select":function(){b.$element.val(b.$element.val()).off("shown.bs.select")},"rendered.bs.select":function(){this.validity.valid&&b.$button.removeClass("bs-invalid"),b.$element.off("rendered.bs.select")}})}),setTimeout(function(){b.$element.trigger("loaded.bs.select")})},createDropdown:function(){var b=this.multiple||this.options.showTick?" show-tick":"",c=this.$element.parent().hasClass("input-group")?" input-group-btn":"",d=this.autofocus?" autofocus":"",e=this.options.header?'
    '+this.options.header+"
    ":"",f=this.options.liveSearch?'':"",g=this.multiple&&this.options.actionsBox?'
    ":"",h=this.multiple&&this.options.doneButton?'
    ":"",j='
    ";return a(j)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul")[0].innerHTML=b,a},reloadLi:function(){var a=this.createLi();this.$menuInner[0].innerHTML=a},createLi:function(){var c=this,d=[],e=0,f=document.createElement("option"),g=-1,h=function(a,b,c,d){return""+a+""},j=function(d,e,f,g){return''+d+''};if(this.options.title&&!this.multiple&&(g--,!this.$element.find(".bs-title-option").length)){var k=this.$element[0];f.className="bs-title-option",f.innerHTML=this.options.title,f.value="",k.insertBefore(f,k.firstChild);var l=a(k.options[k.selectedIndex]);void 0===l.attr("selected")&&void 0===this.$element.data("selected")&&(f.selected=!0)}return this.$element.find("option").each(function(b){var f=a(this);if(g++,!f.hasClass("bs-title-option")){var k=this.className||"",l=this.style.cssText,m=f.data("content")?f.data("content"):f.html(),n=f.data("tokens")?f.data("tokens"):null,o="undefined"!=typeof f.data("subtext")?''+f.data("subtext")+"":"",p="undefined"!=typeof f.data("icon")?' ':"",q=f.parent(),r="OPTGROUP"===q[0].tagName,s=r&&q[0].disabled,t=this.disabled||s;if(""!==p&&t&&(p=""+p+""),c.options.hideDisabled&&(t&&!r||s))return void g--;if(f.data("content")||(m=p+''+m+o+""),r&&f.data("divider")!==!0){if(c.options.hideDisabled&&t){if(void 0===q.data("allOptionsDisabled")){var u=q.children();q.data("allOptionsDisabled",u.filter(":disabled").length===u.length)}if(q.data("allOptionsDisabled"))return void g--}var v=" "+q[0].className||"";if(0===f.index()){e+=1;var w=q[0].label,x="undefined"!=typeof q.data("subtext")?''+q.data("subtext")+"":"",y=q.data("icon")?' ':"";w=y+''+i(w)+x+"",0!==b&&d.length>0&&(g++,d.push(h("",null,"divider",e+"div"))),g++,d.push(h(w,null,"dropdown-header"+v,e))}if(c.options.hideDisabled&&t)return void g--;d.push(h(j(m,"opt "+k+v,l,n),b,"",e))}else if(f.data("divider")===!0)d.push(h("",b,"divider"));else if(f.data("hidden")===!0)d.push(h(j(m,k,l,n),b,"hidden is-hidden"));else{var z=this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName;if(!z&&c.options.hideDisabled)for(var A=a(this).prevAll(),B=0;B ':"";return b=d.options.showSubtext&&c.data("subtext")&&!d.multiple?' '+c.data("subtext")+"":"","undefined"!=typeof c.attr("title")?c.attr("title"):c.data("content")&&d.options.showContent?c.data("content").toString():e+c.html()+b}}).toArray(),f=this.multiple?e.join(this.options.multipleSeparator):e[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var g=this.options.selectedTextFormat.split(">");if(g.length>1&&e.length>g[1]||1==g.length&&e.length>=2){c=this.options.hideDisabled?", [disabled]":"";var h=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+c).length,i="function"==typeof this.options.countSelectedText?this.options.countSelectedText(e.length,h):this.options.countSelectedText;f=i.replace("{0}",e.length.toString()).replace("{1}",h.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(f=this.options.title),f||(f="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",j(a.trim(f.replace(/<[^>]*>?/g,"")))),this.$button.children(".filter-option").html(f),this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||this.options.size!==!1&&!this.sizeInfo){var c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("ul"),f=document.createElement("li"),g=document.createElement("li"),h=document.createElement("a"),i=document.createElement("span"),j=this.options.header&&this.$menu.find(".popover-title").length>0?this.$menu.find(".popover-title")[0].cloneNode(!0):null,k=this.options.liveSearch?document.createElement("div"):null,l=this.options.actionsBox&&this.multiple&&this.$menu.find(".bs-actionsbox").length>0?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,m=this.options.doneButton&&this.multiple&&this.$menu.find(".bs-donebutton").length>0?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(i.className="text",c.className=this.$menu[0].parentNode.className+" open",d.className="dropdown-menu open",e.className="dropdown-menu inner",f.className="divider",i.appendChild(document.createTextNode("Inner text")),h.appendChild(i),g.appendChild(h),e.appendChild(g),e.appendChild(f),j&&d.appendChild(j),k){var n=document.createElement("input");k.className="bs-searchbox",n.className="form-control",k.appendChild(n),d.appendChild(k)}l&&d.appendChild(l),d.appendChild(e),m&&d.appendChild(m),c.appendChild(d),document.body.appendChild(c);var o=h.offsetHeight,p=j?j.offsetHeight:0,q=k?k.offsetHeight:0,r=l?l.offsetHeight:0,s=m?m.offsetHeight:0,t=a(f).outerHeight(!0),u="function"==typeof getComputedStyle&&getComputedStyle(d),v=u?null:a(d),w={vert:parseInt(u?u.paddingTop:v.css("paddingTop"))+parseInt(u?u.paddingBottom:v.css("paddingBottom"))+parseInt(u?u.borderTopWidth:v.css("borderTopWidth"))+parseInt(u?u.borderBottomWidth:v.css("borderBottomWidth")),horiz:parseInt(u?u.paddingLeft:v.css("paddingLeft"))+parseInt(u?u.paddingRight:v.css("paddingRight"))+parseInt(u?u.borderLeftWidth:v.css("borderLeftWidth"))+parseInt(u?u.borderRightWidth:v.css("borderRightWidth"))},x={vert:w.vert+parseInt(u?u.marginTop:v.css("marginTop"))+parseInt(u?u.marginBottom:v.css("marginBottom"))+2,horiz:w.horiz+parseInt(u?u.marginLeft:v.css("marginLeft"))+parseInt(u?u.marginRight:v.css("marginRight"))+2};document.body.removeChild(c),this.sizeInfo={liHeight:o,headerHeight:p,searchHeight:q,actionsHeight:r,doneButtonHeight:s,dividerHeight:t,menuPadding:w,menuExtras:x}}},setSize:function(){if(this.findLis(),this.liHeight(),this.options.header&&this.$menu.css("padding-top",0),this.options.size!==!1){var b,c,d,e,f,g,h,i,j=this,k=this.$menu,l=this.$menuInner,m=a(window),n=this.$newElement[0].offsetHeight,o=this.$newElement[0].offsetWidth,p=this.sizeInfo.liHeight,q=this.sizeInfo.headerHeight,r=this.sizeInfo.searchHeight,s=this.sizeInfo.actionsHeight,t=this.sizeInfo.doneButtonHeight,u=this.sizeInfo.dividerHeight,v=this.sizeInfo.menuPadding,w=this.sizeInfo.menuExtras,x=this.options.hideDisabled?".disabled":"",y=function(){var b,c=j.$newElement.offset(),d=a(j.options.container);j.options.container&&!d.is("body")?(b=d.offset(),b.top+=parseInt(d.css("borderTopWidth")),b.left+=parseInt(d.css("borderLeftWidth"))):b={top:0,left:0};var e=j.options.windowPadding;f=c.top-b.top-m.scrollTop(),g=m.height()-f-n-b.top-e[2],h=c.left-b.left-m.scrollLeft(),i=m.width()-h-o-b.left-e[1],f-=e[0],h-=e[3]};if(y(),"auto"===this.options.size){var z=function(){var m,n=function(b,c){return function(d){return c?d.classList?d.classList.contains(b):a(d).hasClass(b):!(d.classList?d.classList.contains(b):a(d).hasClass(b))}},u=j.$menuInner[0].getElementsByTagName("li"),x=Array.prototype.filter?Array.prototype.filter.call(u,n("hidden",!1)):j.$lis.not(".hidden"),z=Array.prototype.filter?Array.prototype.filter.call(x,n("dropdown-header",!0)):x.filter(".dropdown-header");y(),b=g-w.vert,c=i-w.horiz,j.options.container?(k.data("height")||k.data("height",k.height()),d=k.data("height"),k.data("width")||k.data("width",k.width()),e=k.data("width")):(d=k.height(),e=k.width()),j.options.dropupAuto&&j.$newElement.toggleClass("dropup",f>g&&b-w.verti&&c-w.horiz3?3*p+w.vert-2:0,k.css({"max-height":b+"px",overflow:"hidden","min-height":m+q+r+s+t+"px"}),l.css({"max-height":b-q-r-s-t-v.vert+"px","overflow-y":"auto","min-height":Math.max(m-v.vert,0)+"px"})};z(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",z),m.off("resize.getSize scroll.getSize").on("resize.getSize scroll.getSize",z)}else if(this.options.size&&"auto"!=this.options.size&&this.$lis.not(x).length>this.options.size){var A=this.$lis.not(".divider").not(x).children().slice(0,this.options.size).last().parent().index(),B=this.$lis.slice(0,A+1).filter(".divider").length;b=p*this.options.size+B*u+v.vert,j.options.container?(k.data("height")||k.data("height",k.height()),d=k.data("height")):d=k.height(),j.options.dropupAuto&&this.$newElement.toggleClass("dropup",f>g&&b-w.vert');var b,c,d,e=this,f=a(this.options.container),g=function(a){e.$bsContainer.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),f.is("body")?c={top:0,left:0}:(c=f.offset(),c.top+=parseInt(f.css("borderTopWidth"))-f.scrollTop(),c.left+=parseInt(f.css("borderLeftWidth"))-f.scrollLeft()),d=a.hasClass("dropup")?0:a[0].offsetHeight,e.$bsContainer.css({top:b.top-c.top+d,left:b.left-c.left,width:a[0].offsetWidth})};this.$button.on("click",function(){var b=a(this);e.isDisabled()||(g(e.$newElement),e.$bsContainer.appendTo(e.options.container).toggleClass("open",!b.hasClass("open")).append(e.$menu))}),a(window).on("resize scroll",function(){g(e.$newElement)}),this.$element.on("hide.bs.select",function(){e.$menu.data("height",e.$menu.height()),e.$bsContainer.detach()})},setSelected:function(a,b,c){c||(this.togglePlaceholder(),c=this.findLis().eq(this.liObj[a])),c.toggleClass("selected",b).find("a").attr("aria-selected",b)},setDisabled:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),b?c.addClass("disabled").children("a").attr("href","#").attr("tabindex",-1).attr("aria-disabled",!0):c.removeClass("disabled").children("a").removeAttr("href").attr("tabindex",0).attr("aria-disabled",!1)},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){var a=this;this.isDisabled()?(this.$newElement.addClass("disabled"),this.$button.addClass("disabled").attr("tabindex",-1).attr("aria-disabled",!0)):(this.$button.hasClass("disabled")&&(this.$newElement.removeClass("disabled"),this.$button.removeClass("disabled").attr("aria-disabled",!1)),this.$button.attr("tabindex")!=-1||this.$element.data("tabindex")||this.$button.removeAttr("tabindex")),this.$button.click(function(){return!a.isDisabled()})},togglePlaceholder:function(){var a=this.$element.val();this.$button.toggleClass("bs-placeholder",null===a||""===a||a.constructor===Array&&0===a.length)},tabIndex:function(){this.$element.data("tabindex")!==this.$element.attr("tabindex")&&this.$element.attr("tabindex")!==-98&&"-98"!==this.$element.attr("tabindex")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex"))),this.$element.attr("tabindex",-98)},clickListener:function(){var b=this,c=a(document);c.data("spaceSelect",!1),this.$button.on("keyup",function(a){/(32)/.test(a.keyCode.toString(10))&&c.data("spaceSelect")&&(a.preventDefault(),c.data("spaceSelect",!1))}),this.$button.on("click",function(){b.setSize()}),this.$element.on("shown.bs.select",function(){if(b.options.liveSearch||b.multiple){if(!b.multiple){var a=b.liObj[b.$element[0].selectedIndex];if("number"!=typeof a||b.options.size===!1)return;var c=b.$lis.eq(a)[0].offsetTop-b.$menuInner[0].offsetTop;c=c-b.$menuInner[0].offsetHeight/2+b.sizeInfo.liHeight/2,b.$menuInner[0].scrollTop=c}}else b.$menuInner.find(".selected a").focus()}),this.$menuInner.on("click","li a",function(c){var d=a(this),f=d.parent().data("originalIndex"),g=b.$element.val(),h=b.$element.prop("selectedIndex"),i=!0;if(b.multiple&&1!==b.options.maxOptions&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var j=b.$element.find("option"),k=j.eq(f),l=k.prop("selected"),m=k.parent("optgroup"),n=b.options.maxOptions,o=m.data("maxOptions")||!1;if(b.multiple){if(k.prop("selected",!l),b.setSelected(f,!l),d.blur(),n!==!1||o!==!1){var p=n');t[2]&&(u=u.replace("{var}",t[2][n>1?0:1]),v=v.replace("{var}",t[2][o>1?0:1])),k.prop("selected",!1),b.$menu.append(w),n&&p&&(w.append(a("
    "+u+"
    ")),i=!1,b.$element.trigger("maxReached.bs.select")),o&&q&&(w.append(a("
    "+v+"
    ")),i=!1,b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(f,!1)},10),w.delay(750).fadeOut(300,function(){a(this).remove()})}}}else j.prop("selected",!1),k.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected").find("a").attr("aria-selected",!1),b.setSelected(f,!0);!b.multiple||b.multiple&&1===b.options.maxOptions?b.$button.focus():b.options.liveSearch&&b.$searchbox.focus(),i&&(g!=b.$element.val()&&b.multiple||h!=b.$element.prop("selectedIndex")&&!b.multiple)&&(e=[f,k.prop("selected"),l],b.$element.triggerNative("change"))}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menuInner.on("click",".divider, .dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll()}),this.$element.change(function(){b.render(!1),b.$element.trigger("changed.bs.select",e),e=null})},liveSearchListener:function(){var c=this,d=a('
  • ');this.$button.on("click.dropdown.data-api",function(){c.$menuInner.find(".active").removeClass("active"),c.$searchbox.val()&&(c.$searchbox.val(""),c.$lis.not(".is-hidden").removeClass("hidden"),d.parent().length&&d.remove()),c.multiple||c.$menuInner.find(".selected").addClass("active"),setTimeout(function(){c.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){if(c.$lis.not(".is-hidden").removeClass("hidden"),c.$lis.filter(".active").removeClass("active"),d.remove(),c.$searchbox.val()){var e,f=c.$lis.not(".is-hidden, .divider, .dropdown-header");if(e=c.options.liveSearchNormalize?f.find("a").not(":a"+c._searchStyle()+'("'+b(c.$searchbox.val())+'")'):f.find("a").not(":"+c._searchStyle()+'("'+c.$searchbox.val()+'")'),e.length===f.length)d.html(c.options.noneResultsText.replace("{0}",'"'+i(c.$searchbox.val())+'"')),c.$menuInner.append(d),c.$lis.addClass("hidden");else{e.parent().addClass("hidden");var g,h=c.$lis.not(".hidden");h.each(function(b){var c=a(this);c.hasClass("divider")?void 0===g?c.addClass("hidden"):(g&&g.addClass("hidden"),g=c):c.hasClass("dropdown-header")&&h.eq(b+1).data("optgroup")!==c.data("optgroup")?c.addClass("hidden"):g=null}),g&&g.addClass("hidden"),f.not(".hidden").first().addClass("active")}}})},_searchStyle:function(){var a={begins:"ibegins",startsWith:"ibegins"};return a[this.options.liveSearchStyle]||"icontains"},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},changeAll:function(b){if(this.multiple){"undefined"==typeof b&&(b=!0),this.findLis();var c=this.$element.find("option"),d=this.$lis.not(".divider, .dropdown-header, .disabled, .hidden"),e=d.length,f=[];if(b){if(d.filter(".selected").length===d.length)return}else if(0===d.filter(".selected").length)return;d.toggleClass("selected",b);for(var g=0;g=48&&c.keyCode<=57||c.keyCode>=96&&c.keyCode<=105||c.keyCode>=65&&c.keyCode<=90))return o.options.container?o.$button.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),void o.$searchbox.focus();if(o.options.liveSearch&&(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(c.preventDefault(),c.stopPropagation(),o.$menuInner.click(),o.$button.focus()),d=a('[role="listbox"] li'+p,n),m.val()||/(38|40)/.test(c.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$menuInner.find("li"),d=o.options.liveSearchNormalize?d.filter(":a"+o._searchStyle()+"("+b(q[c.keyCode])+")"):d.filter(":"+o._searchStyle()+"("+q[c.keyCode]+")"))),d.length){if(/(38|40)/.test(c.keyCode.toString(10)))e=d.index(d.find("a").filter(":focus").parent()),g=d.filter(p).first().index(),h=d.filter(p).last().index(),f=d.eq(e).nextAll(p).eq(0).index(),i=d.eq(e).prevAll(p).eq(0).index(),j=d.eq(f).prevAll(p).eq(0).index(),o.options.liveSearch&&(d.each(function(b){a(this).hasClass("disabled")||a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.first().data("index"),h=d.last().data("index"),f=d.eq(e).nextAll().eq(0).data("index"),i=d.eq(e).prevAll().eq(0).data("index"),j=d.eq(f).prevAll().eq(0).data("index")),k=m.data("prevIndex"),38==c.keyCode?(o.options.liveSearch&&e--,e!=j&&e>i&&(e=i),eh&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(c.preventDefault(),m.hasClass("dropdown-toggle")||(d.removeClass("active").eq(e).addClass("active").children("a").focus(),m.focus())):d.eq(e).children("a").focus();else if(!m.is("input")){var r,s,t=[];d.each(function(){a(this).hasClass("disabled")||a.trim(a(this).children("a").text().toLowerCase()).substring(0,1)==q[c.keyCode]&&t.push(a(this).index())}),r=a(document).data("keycount"),r++,a(document).data("keycount",r),s=a.trim(a(":focus").text().toLowerCase()).substring(0,1),s!=q[c.keyCode]?(r=1,a(document).data("keycount",r)):r>=t.length&&(a(document).data("keycount",0),r>t.length&&(r=1)),d.eq(t[r-1]).children("a").focus()}if((/(13|32)/.test(c.keyCode.toString(10))||/(^9$)/.test(c.keyCode.toString(10))&&o.options.selectOnTab)&&l){if(/(32)/.test(c.keyCode.toString(10))||c.preventDefault(),o.options.liveSearch)/(32)/.test(c.keyCode.toString(10))||(o.$menuInner.find(".active a").click(), -m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var l=a.fn.selectpicker;a.fn.selectpicker=c,a.fn.selectpicker.Constructor=k,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=l,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',k.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);c.call(b,b.data())})})}(a)}); +m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var l=a.fn.selectpicker;a.fn.selectpicker=c,a.fn.selectpicker.Constructor=k,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=l,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',k.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);c.call(b,b.data())})})}(a)}); \ No newline at end of file diff --git a/data/web/js/bootstrap-filestyle.min.js b/data/web/js/build/005-bootstrap-filestyle.min.js similarity index 100% rename from data/web/js/bootstrap-filestyle.min.js rename to data/web/js/build/005-bootstrap-filestyle.min.js diff --git a/data/web/js/notifications.min.js b/data/web/js/build/006-notifications.min.js similarity index 100% rename from data/web/js/notifications.min.js rename to data/web/js/build/006-notifications.min.js diff --git a/data/web/js/formcache.min.js b/data/web/js/build/007-formcache.min.js similarity index 100% rename from data/web/js/formcache.min.js rename to data/web/js/build/007-formcache.min.js diff --git a/data/web/js/google.charts.loader.js b/data/web/js/build/008-google.charts.loader.js similarity index 100% rename from data/web/js/google.charts.loader.js rename to data/web/js/build/008-google.charts.loader.js diff --git a/data/web/js/numberedtextarea.min.js b/data/web/js/build/009-numberedtextarea.min.js similarity index 100% rename from data/web/js/numberedtextarea.min.js rename to data/web/js/build/009-numberedtextarea.min.js diff --git a/data/web/js/build/010-sha1.min.js b/data/web/js/build/010-sha1.min.js new file mode 100644 index 00000000..1abe5880 --- /dev/null +++ b/data/web/js/build/010-sha1.min.js @@ -0,0 +1 @@ +!function(r){var o=function(r,o){return r<>>32-o},e=function(r){var o,e="";for(o=7;o>=0;o--)e+=(r>>>4*o&15).toString(16);return e};jQuery.extend({sha1:function(r){var a,t,n,h,C,c,f,d,u,i=new Array(80),A=1732584193,g=4023233417,s=2562383102,S=271733878,m=3285377520,p=(r=function(r){r=r.replace(/\x0d\x0a/g,"\n");for(var o="",e=0;e127&&a<2048?(o+=String.fromCharCode(a>>6|192),o+=String.fromCharCode(63&a|128)):(o+=String.fromCharCode(a>>12|224),o+=String.fromCharCode(a>>6&63|128),o+=String.fromCharCode(63&a|128))}return o}(r)).length,l=new Array;for(t=0;t>>29),l.push(p<<3&4294967295),a=0;a' + loading_text + ''); + parent_btn_grp.replaceWith(' + + +

    +
    +
    +
    +
    +
    + + + + +
    +
    + + @@ -304,17 +341,25 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/mailbox.php'; - - add('/web/js/site/mailbox.js'); require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; -} else { +} +else { header('Location: /'); exit(); } diff --git a/data/web/mobileconfig.php b/data/web/mobileconfig.php index 98691c55..ade4f606 100644 --- a/data/web/mobileconfig.php +++ b/data/web/mobileconfig.php @@ -12,158 +12,163 @@ if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'use error_reporting(0); header('Content-Type: application/x-apple-aspen-config'); -header('Content-Disposition: attachment; filename="Mailcow.mobileconfig"'); +header('Content-Disposition: attachment; filename="'.$UI_TEXTS['main_name'].'.mobileconfig"'); $email = $_SESSION['mailcow_cc_username']; $domain = explode('@', $_SESSION['mailcow_cc_username'])[1]; -$identifier = implode('.', array_reverse(explode('.', $domain))) . '.iphoneprofile.mailcow'; +$identifier = implode('.', array_reverse(preg_split( '/(@|\.)/', $email))) . '.appleprofile.'.preg_replace('/[^a-zA-Z0-9]+/', '', $UI_TEXTS['main_name']); try { $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username"); $stmt->execute(array(':username' => $email)); $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); + $displayname = empty($MailboxData['name']) ? $email : $MailboxData['name']; } catch(PDOException $e) { - die("Failed to determine name from SQL"); -} -if (!empty($MailboxData['name'])) { - $displayname = $MailboxData['name']; -} -else { $displayname = $email; } +if (isset($_GET['only_email'])) { + $onlyEmailAccount = true; + $description = 'IMAP'; +} else { + $onlyEmailAccount = false; + $description = 'IMAP, CalDAV, CardDAV'; +} + echo '' . "\n"; ?> - - PayloadContent - - - CalDAVAccountDescription - - CalDAVHostName - - CalDAVPort - - CalDAVPrincipalURL - /SOGo/dav/ - CalDAVUseSSL - - CalDAVUsername - - PayloadDescription - Configures CalDAV account. - PayloadDisplayName - CalDAV () - PayloadIdentifier - .CalDAV - PayloadOrganization - - PayloadType - com.apple.caldav.account - PayloadUUID - FC898573-EBA8-48AF-93BD-BFA0C9778FA7 - PayloadVersion - 1 - - - EmailAccountDescription - - EmailAccountType - EmailTypeIMAP - EmailAccountName - - EmailAddress - - IncomingMailServerAuthentication - EmailAuthPassword - IncomingMailServerHostName - - IncomingMailServerPortNumber - - IncomingMailServerUseSSL - - IncomingMailServerUsername - - OutgoingMailServerAuthentication - EmailAuthPassword - OutgoingMailServerHostName - - OutgoingMailServerPortNumber - - OutgoingMailServerUseSSL - - OutgoingMailServerUsername - - OutgoingPasswordSameAsIncomingPassword - - PayloadDescription - Configures email account. - PayloadDisplayName - IMAP Account () - PayloadIdentifier - .email - PayloadOrganization - - PayloadType - com.apple.mail.managed - PayloadUUID - 00294FBB-1016-413E-87B9-652D856D6875 - PayloadVersion - 1 - PreventAppSheet - - PreventMove - - SMIMEEnabled - - - - CardDAVAccountDescription - - CardDAVHostName - - CardDAVPort - - CardDAVPrincipalURL - /SOGo/dav/ - CardDAVUseSSL - - CardDAVUsername - - PayloadDescription - Configures CardDAV accounts - PayloadDisplayName - CardDAV () - PayloadIdentifier - .carddav - PayloadOrganization - - PayloadType - com.apple.carddav.account - PayloadUUID - 0797EF2B-B1F1-4BC7-ABCD-4580862252B4 - PayloadVersion - 1 - - - PayloadDescription - IMAP, CalDAV, CardDAV - PayloadDisplayName - Mailcow - PayloadIdentifier - - PayloadOrganization - - PayloadRemovalDisallowed - - PayloadType - Configuration - PayloadUUID - 5EE248C5-ACCB-42D8-9199-8F8ED08D5624 - PayloadVersion - 1 - + + PayloadContent + + + EmailAccountDescription + + EmailAccountType + EmailTypeIMAP + EmailAccountName + + EmailAddress + + IncomingMailServerAuthentication + EmailAuthPassword + IncomingMailServerHostName + + IncomingMailServerPortNumber + + IncomingMailServerUseSSL + + IncomingMailServerUsername + + OutgoingMailServerAuthentication + EmailAuthPassword + OutgoingMailServerHostName + + OutgoingMailServerPortNumber + + OutgoingMailServerUseSSL + + OutgoingMailServerUsername + + OutgoingPasswordSameAsIncomingPassword + + PayloadDescription + Configures email account. + PayloadDisplayName + IMAP Account () + PayloadIdentifier + .email + PayloadOrganization + + PayloadType + com.apple.mail.managed + PayloadUUID + + PayloadVersion + 1 + PreventAppSheet + + PreventMove + + SMIMEEnabled + + + + + CalDAVAccountDescription + + CalDAVHostName + + CalDAVPort + + CalDAVPrincipalURL + /SOGo/dav/ + CalDAVUseSSL + + CalDAVUsername + + PayloadDescription + Configures CalDAV account. + PayloadDisplayName + CalDAV () + PayloadIdentifier + .CalDAV + PayloadOrganization + + PayloadType + com.apple.caldav.account + PayloadUUID + + PayloadVersion + 1 + + + CardDAVAccountDescription + + CardDAVHostName + + CardDAVPort + + CardDAVPrincipalURL + /SOGo/dav/ + CardDAVUseSSL + + CardDAVUsername + + PayloadDescription + Configures CardDAV accounts + PayloadDisplayName + CardDAV () + PayloadIdentifier + .carddav + PayloadOrganization + + PayloadType + com.apple.carddav.account + PayloadUUID + + PayloadVersion + 1 + + + + PayloadDescription + + PayloadDisplayName + + PayloadIdentifier + + PayloadOrganization + + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + + PayloadVersion + 1 + diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php index 7e8656e5..2303519e 100644 --- a/data/web/modals/admin.php +++ b/data/web/modals/admin.php @@ -17,13 +17,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - +
    - +
    @@ -35,7 +35,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - +
    @@ -60,14 +60,14 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - + a-z A-Z - _ .
    - ".htmlspecialchars($domain).""; @@ -79,13 +79,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - +
    - +
    @@ -97,7 +97,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - +
    @@ -105,35 +105,82 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
    - -
    +
    -

    -
    -
    -
    -
    -
    - -
    - -

    []

    -

    []

    -

    - - () - -

    -
    -
    + +
    -
    -
    -
    -

    []

    -
    -
    -
    - -
    -
    : -

    -
    -
    -

    -
    -
    -
    -
    : -

    -
    -
    -

    -
    -
    -
    -
    -
    :
    -
    -

    -
    -
    -
    -
    :
    -
    -

    -
    -
    -
    -
    :
    -
    -

    -
    -
    -
    -
    -
    :
    -
    -
    -
    - % + +
    + +
    +
    +
    +
    +
    +
    + +
    + +

    []

    +

    []

    +

    []

    +

    + + () + +

    +
    +
    +
    + +
    +
    : +

    +
    +
    + $direct_alias_meta) { + (!empty($direct_alias_meta['public_comment'])) ? + printf('%s — %s
    ', $direct_alias, $direct_alias_meta['public_comment']) : + printf('%s
    ', $direct_alias); + } + } + ?> +
    +
    +
    +
    : +

    +
    +
    + $shared_alias_meta) { + (!empty($shared_alias_meta['public_comment'])) ? + printf('%s — %s
    ', $shared_alias, $shared_alias_meta['public_comment']) : + + printf('%s
    ', $shared_alias); + } + } + ?> +
    +
    +
    +
    +
    :
    +
    +

    +
    +
    +
    +
    :
    +
    +

    +
    +
    +
    +
    :
    +
    +

    +
    +
    +
    +
    +
    :
    +
    +
    +
    + % +
    +
    +

    /

    +
    +
    +
    + +
    +
    :
    +
    +
    + + + +
    +

    +

    +
    +
    + +
    +
    :
    +
    +
    + + +
    +

    +
    +
    + +
    +
    :
    +
    +
    + + + + +
    +

    +
    +
    +
    +
    +
    :
    +
    + +

    +
    +
    +
    +
    :
    +
    + +

    +
    -

    / ,

    - '; - // Show tagging options - if ($_SESSION['acl']['delimiter_action'] == 1): - $get_tagging_options = mailbox('get', 'delimiter_action', $username); - ?> -
    -
    :
    -
    -
    - - - - - - -
    -

    -

    -
    -
    - -
    -
    :
    -
    -
    - - - - - -
    -

    -
    -
    - -
    -
    :
    -
    - -

    -
    -
    - -
    -
    - - - -
    - -
    -
    +
    @@ -273,35 +321,33 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
    -
    -
    +
    -
    @@ -309,7 +355,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
    -
  • -

    5:15

    -
    -
    +
    + + +
    -

    @@ -354,26 +400,21 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
    - +
    -
    +
    - +
    -
    - +
    + - +
    -

    @@ -381,28 +422,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
    - +
    -
    +
    - +
    -
    - - - +
    + - +
    - +
    @@ -411,33 +446,27 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
    -
    -
    +
    -
    - +
    - - add('/web/js/site/user.js'); +require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; } else { header('Location: /'); diff --git a/docker-compose.yml b/docker-compose.yml index 871961a8..cbef6a40 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '2.1' services: unbound-mailcow: - image: mailcow/unbound:1.1 + image: mailcow/unbound:1.6 build: ./data/Dockerfiles/unbound command: /usr/sbin/unbound environment: @@ -10,6 +10,7 @@ services: volumes: - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro restart: always + tty: true networks: mailcow-network: ipv4_address: ${IPV4_NETWORK:-172.22.1}.254 @@ -20,6 +21,7 @@ services: image: mariadb:10.2 volumes: - mysql-vol-1:/var/lib/mysql/ + - mysql-socket-vol-1:/var/run/mysqld/ - ./data/conf/mysql/:/etc/mysql/conf.d/:ro environment: - TZ=${TZ} @@ -38,7 +40,7 @@ services: - mysql redis-mailcow: - image: redis:4-alpine + image: redis:5-alpine volumes: - redis-vol-1:/data/ restart: always @@ -53,16 +55,14 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.13 + image: mailcow/clamd:1.22 build: ./data/Dockerfiles/clamd restart: always - tty: true environment: - TZ=${TZ} - SKIP_CLAMD=${SKIP_CLAMD:-n} volumes: - ./data/conf/clamav/:/etc/clamav/ - - ./data/conf/clamav/whitelist.ign2:/var/lib/clamav/whitelist.ign2 dns: - ${IPV4_NETWORK:-172.22.1}.254 networks: @@ -71,7 +71,7 @@ services: - clamd rspamd-mailcow: - image: mailcow/rspamd:1.24 + image: mailcow/rspamd:1.38 build: ./data/Dockerfiles/rspamd stop_grace_period: 30s depends_on: @@ -79,11 +79,10 @@ services: environment: - TZ=${TZ} volumes: - - ./data/conf/rspamd/custom/:/etc/rspamd/custom:ro - - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:rw - - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:ro + - ./data/conf/rspamd/custom/:/etc/rspamd/custom + - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d + - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro - - rspamd-sock:/rspamd-sock - rspamd-vol-1:/var/lib/rspamd restart: always dns: @@ -95,7 +94,7 @@ services: - rspamd php-fpm-mailcow: - image: mailcow/phpfpm:1.18 + image: mailcow/phpfpm:1.36 build: ./data/Dockerfiles/phpfpm command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: @@ -103,12 +102,16 @@ services: volumes: - ./data/web:/web:rw - ./data/conf/rspamd/dynmaps:/dynmaps:ro - - rspamd-sock:/rspamd-sock + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ + - ./data/conf/sogo/:/etc/sogo/ - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + - ./data/conf/phpfpm/sogo-sso/:/etc/sogo-sso/ - ./data/conf/phpfpm/php-fpm.d/pools.conf:/usr/local/etc/php-fpm.d/z-pools.conf - ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini - ./data/conf/phpfpm/php-conf.d/upload.ini:/usr/local/etc/php/conf.d/upload.ini - ./data/conf/phpfpm/php-conf.d/other.ini:/usr/local/etc/php/conf.d/zzz-other.ini + - ./data/assets/templates:/tpls environment: - LOG_LINES=${LOG_LINES:-9999} - TZ=${TZ} @@ -127,6 +130,8 @@ services: - API_KEY=${API_KEY:-invalid} - API_ALLOW_FROM=${API_ALLOW_FROM:-invalid} - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized} + - SKIP_SOLR=${SKIP_SOLR:-y} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} restart: always dns: - ${IPV4_NETWORK:-172.22.1}.254 @@ -136,7 +141,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.34 + image: mailcow/sogo:1.54 build: ./data/Dockerfiles/sogo environment: - DBNAME=${DBNAME} @@ -145,8 +150,15 @@ services: - TZ=${TZ} - LOG_LINES=${LOG_LINES:-9999} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - ACL_ANYONE=${ACL_ANYONE:-disallow} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} volumes: - ./data/conf/sogo/:/etc/sogo/ + - ./data/web/inc/init_db.inc.php:/init_db.inc.php + - ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js + - mysql-socket-vol-1:/var/run/mysqld/ + - sogo-web-vol-1:/sogo_web restart: always dns: - ${IPV4_NETWORK:-172.22.1}.254 @@ -157,7 +169,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.33 + image: mailcow/dovecot:1.67 build: ./data/Dockerfiles/dovecot cap_add: - NET_BIND_SERVICE @@ -165,15 +177,26 @@ services: - ./data/conf/dovecot:/usr/local/etc/dovecot - ./data/assets/ssl:/etc/ssl/mail/:ro - ./data/conf/sogo/:/etc/sogo/ + - ./data/conf/phpfpm/sogo-sso/:/etc/phpfpm/ - vmail-vol-1:/var/vmail + - vmail-attachments-vol-1:/var/attachments - crypt-vol-1:/mail_crypt/ - - rspamd-sock:/rspamd-sock + - ./data/conf/rspamd/custom/:/etc/rspamd/custom + - ./data/assets/templates:/templates + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ environment: - LOG_LINES=${LOG_LINES:-9999} - DBNAME=${DBNAME} - DBUSER=${DBUSER} - DBPASS=${DBPASS} - TZ=${TZ} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440} + - ACL_ANYONE=${ACL_ANYONE:-disallow} + - SKIP_SOLR=${SKIP_SOLR:-y} + - MAILDIR_SUB=${MAILDIR_SUB:-} ports: - "${DOVEADM_PORT:-127.0.0.1:19991}:12345" - "${IMAP_PORT:-143}:143" @@ -182,6 +205,7 @@ services: - "${POPS_PORT:-995}:995" - "${SIEVE_PORT:-4190}:4190" restart: always + tty: true ulimits: nproc: 65535 nofile: @@ -192,18 +216,20 @@ services: hostname: ${MAILCOW_HOSTNAME} networks: mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.250 aliases: - dovecot postfix-mailcow: - image: mailcow/postfix:1.21 + image: mailcow/postfix:1.31 build: ./data/Dockerfiles/postfix volumes: - ./data/conf/postfix:/opt/postfix/conf - ./data/assets/ssl:/etc/ssl/mail/:ro - postfix-vol-1:/var/spool/postfix - crypt-vol-1:/var/lib/zeyple - - rspamd-sock:/rspamd-sock + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ environment: - LOG_LINES=${LOG_LINES:-9999} - TZ=${TZ} @@ -246,6 +272,7 @@ services: envsubst < /etc/nginx/conf.d/templates/server_name.template > /etc/nginx/conf.d/server_name.active && envsubst < /etc/nginx/conf.d/templates/sogo.template > /etc/nginx/conf.d/sogo.active && envsubst < /etc/nginx/conf.d/templates/sogo_eas.template > /etc/nginx/conf.d/sogo_eas.active && + . /etc/nginx/conf.d/templates/sogo.auth_request.template.sh > /etc/nginx/conf.d/sogo_proxy_auth.active && nginx -qt && until ping phpfpm -c1 > /dev/null; do sleep 1; done && until ping sogo -c1 > /dev/null; do sleep 1; done && @@ -258,12 +285,14 @@ services: - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - TZ=${TZ} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} volumes: - ./data/web:/web:ro - ./data/conf/rspamd/dynmaps:/dynmaps:ro - ./data/assets/ssl/:/etc/ssl/mail/:ro - ./data/conf/nginx/:/etc/nginx/conf.d/:rw - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/ ports: - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" @@ -278,8 +307,7 @@ services: acme-mailcow: depends_on: - nginx-mailcow - - mysql-mailcow - image: mailcow/acme:1.37 + image: mailcow/acme:1.51 build: ./data/Dockerfiles/acme dns: - ${IPV4_NETWORK:-172.22.1}.254 @@ -292,11 +320,14 @@ services: - DBPASS=${DBPASS} - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n} - SKIP_IP_CHECK=${SKIP_IP_CHECK:-n} + - SKIP_HTTP_VERIFICATION=${SKIP_HTTP_VERIFICATION:-n} + - LE_STAGING=${LE_STAGING:-n} - TZ=${TZ} volumes: - ./data/web/.well-known/acme-challenge:/var/www/acme:rw - ./data/assets/ssl:/var/lib/acme/:rw - ./data/assets/ssl-example:/var/lib/ssl-example/:ro + - mysql-socket-vol-1:/var/run/mysqld/ restart: always networks: mailcow-network: @@ -304,7 +335,7 @@ services: - acme netfilter-mailcow: - image: mailcow/netfilter:1.19 + image: mailcow/netfilter:1.23 build: ./data/Dockerfiles/netfilter stop_grace_period: 30s depends_on: @@ -328,13 +359,14 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.19 + image: mailcow/watchdog:1.40 # Debug #command: /watchdog.sh build: ./data/Dockerfiles/watchdog oom_kill_disable: true volumes: - - rspamd-sock:/rspamd-sock + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ restart: always environment: - LOG_LINES=${LOG_LINES:-9999} @@ -346,6 +378,11 @@ services: - WATCHDOG_NOTIFY_EMAIL=${WATCHDOG_NOTIFY_EMAIL} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - IP_BY_DOCKER_API=${IP_BY_DOCKER_API:-0} + - CHECK_UNBOUND=${CHECK_UNBOUND:-1} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n} + - HTTPS_PORT=${HTTPS_PORT:-443} dns: - ${IPV4_NETWORK:-172.22.1}.254 networks: @@ -354,11 +391,12 @@ services: - watchdog dockerapi-mailcow: - image: mailcow/dockerapi:1.13 + image: mailcow/dockerapi:1.26 restart: always build: ./data/Dockerfiles/dockerapi oom_kill_disable: true environment: + - DBROOT=${DBROOT} - TZ=${TZ} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro @@ -368,7 +406,41 @@ services: aliases: - dockerapi - ipv6nat: + solr-mailcow: + image: mailcow/solr:1.5 + build: ./data/Dockerfiles/solr + restart: always + volumes: + - solr-vol-1:/opt/solr/server/solr/dovecot-fts/data + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - TZ=${TZ} + - SOLR_HEAP=${SOLR_HEAP:-1024} + - SKIP_SOLR=${SKIP_SOLR:-y} + networks: + mailcow-network: + aliases: + - solr + + ipv6nat-mailcow: + depends_on: + - unbound-mailcow + - mysql-mailcow + - redis-mailcow + - clamd-mailcow + - rspamd-mailcow + - php-fpm-mailcow + - sogo-mailcow + - dovecot-mailcow + - postfix-mailcow + - memcached-mailcow + - nginx-mailcow + - acme-mailcow + - netfilter-mailcow + - watchdog-mailcow + - dockerapi-mailcow + - solr-mailcow image: robbertkl/ipv6nat restart: always privileged: true @@ -380,6 +452,8 @@ services: networks: mailcow-network: driver: bridge + driver_opts: + com.docker.network.bridge.name: br-mailcow enable_ipv6: true ipam: driver: default @@ -388,10 +462,15 @@ networks: - subnet: ${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} volumes: + # Storage for email files vmail-vol-1: + # Storage for attachments (deduplicated) + vmail-attachments-vol-1: mysql-vol-1: + mysql-socket-vol-1: redis-vol-1: rspamd-vol-1: + solr-vol-1: postfix-vol-1: crypt-vol-1: - rspamd-sock: + sogo-web-vol-1: diff --git a/generate_config.sh b/generate_config.sh index 7e4ae01c..d241a9ab 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -o pipefail @@ -16,6 +16,7 @@ if [ -f mailcow.conf ]; then case $response in [yY][eE][sS]|[yY]) mv mailcow.conf mailcow.conf_backup + chmod 600 mailcow.conf_backup ;; *) exit 1 @@ -48,6 +49,44 @@ while [ -z "${MAILCOW_TZ}" ]; do fi done +MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo) + +if [ ${MEM_TOTAL} -le "2621440" ]; then + echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations." + echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf." + read -r -p "Do you want to disable ClamAV now? [Y/n] " response + case $response in + [nN][oO]|[nN]) + SKIP_CLAMD=n + ;; + *) + SKIP_CLAMD=y + ;; + esac +else + SKIP_CLAMD=n +fi + +if [ ${MEM_TOTAL} -le "2097152" ]; then + echo "Disabling Solr on low-memory system." + SKIP_SOLR=y +elif [ ${MEM_TOTAL} -le "3670016" ]; then + echo "Installed memory is <= 3.5 GiB. It is recommended to disable Solr to prevent out-of-memory situations." + echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set in mailcow.conf according to your expected load." + echo "Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf but will refuse to start with less than 2 GB total memory." + read -r -p "Do you want to disable Solr now? [Y/n] " response + case $response in + [nN][oO]|[nN]) + SKIP_SOLR=n + ;; + *) + SKIP_SOLR=y + ;; + esac +else + SKIP_SOLR=n +fi + [ ! -f ./data/conf/rspamd/override.d/worker-controller-password.inc ] && echo '# Placeholder' > ./data/conf/rspamd/override.d/worker-controller-password.inc cat << EOF > mailcow.conf @@ -57,15 +96,18 @@ cat << EOF > mailcow.conf # example.org is _not_ a valid hostname, use a fqdn here. # Default admin user is "admin" # Default password is "moohoo" + MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} # ------------------------------ # SQL database configuration # ------------------------------ + DBNAME=mailcow DBUSER=mailcow # Please use long, random alphanumeric strings (A-Za-z0-9) + DBPASS=$(LC_ALL=C /backup/backup_mysql.gz" @@ -128,6 +138,14 @@ function restore() { debian:stretch-slim /bin/tar -Pxvzf /backup/backup_redis.tar.gz docker start $(docker ps -aqf name=redis-mailcow) ;; + crypt) + docker stop $(docker ps -qf name=dovecot-mailcow) + docker run -it --rm \ + -v ${RESTORE_LOCATION}:/backup \ + -v $(docker volume ls -qf name=${CMPS_PRJ}_crypt-vol-1):/crypt \ + debian:stretch-slim /bin/tar -Pxvzf /backup/backup_crypt.tar.gz + docker start $(docker ps -aqf name=dovecot-mailcow) + ;; rspamd) docker stop $(docker ps -qf name=rspamd-mailcow) docker run -it --rm \ @@ -189,7 +207,7 @@ elif [[ ${1} == "restore" ]]; then echo declare -A FILE_SELECTION RESTORE_POINT="${FOLDER_SELECTION[${input_sel}]}" - if [[ -z $(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 -type f -regex ".*\(redis\|rspamd\|mysql\|vmail\|postfix\).*") ]]; then + if [[ -z $(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 -type f -regex ".*\(redis\|rspamd\|mysql\|crypt\|vmail\|postfix\).*") ]]; then echo "No datasets found" exit 1 fi @@ -198,6 +216,10 @@ elif [[ ${1} == "restore" ]]; then echo "[ ${i} ] - Mail directory (/var/vmail)" FILE_SELECTION[${i}]="vmail" ((i++)) + elif [[ ${file} =~ crypt ]]; then + echo "[ ${i} ] - Crypt data" + FILE_SELECTION[${i}]="crypt" + ((i++)) elif [[ ${file} =~ redis ]]; then echo "[ ${i} ] - Redis DB" FILE_SELECTION[${i}]="redis" diff --git a/helper-scripts/ext_sql_sock.docker-compose.override.yml b/helper-scripts/ext_sql_sock.docker-compose.override.yml new file mode 100644 index 00000000..1f052f08 --- /dev/null +++ b/helper-scripts/ext_sql_sock.docker-compose.override.yml @@ -0,0 +1,31 @@ +version: '2.1' +services: + + php-fpm-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + sogo-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + dovecot-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + postfix-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + acme-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + watchdog-mailcow: + volumes: + - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock + + mysql-mailcow: + image: alpine:3.8 + command: /bin/true + restart: "no" diff --git a/helper-scripts/mailcow-reset-admin.sh b/helper-scripts/mailcow-reset-admin.sh index c0c979b5..74179798 100755 --- a/helper-scripts/mailcow-reset-admin.sh +++ b/helper-scripts/mailcow-reset-admin.sh @@ -19,10 +19,9 @@ read -r -p "Are you sure you want to reset the mailcow administrator account? [y response=${response,,} # tolower if [[ "$response" =~ ^(yes|y)$ ]]; then echo -e "\nWorking, please wait..." - docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin;" - docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "INSERT INTO admin (username, password, superadmin, created, modified, active) VALUES ('admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, NOW(), NOW(), 1);" - docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';" - docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "INSERT INTO domain_admins (username, domain, created, active) VALUES ('admin', 'ALL', NOW(), 1);" + docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';" + docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';" + docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "INSERT INTO admin (username, password, superadmin, active) VALUES ('admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, 1);" docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM tfa WHERE username='admin';" echo " Reset credentials: diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 3922f499..3ad9c9b4 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -29,94 +29,131 @@ cd ${SCRIPT_DIR}/../ source mailcow.conf if [[ ${NC_PURGE} == "y" ]]; then + read -r -p "Are you sure you want to purge Nextcloud? [y/N] " response + response=${response,,} + if [[ ! "$response" =~ ^(yes|y)$ ]]; then + echo "OK, aborting." + exit 1 + fi - docker exec -it $(docker ps -f name=mysql-mailcow -q) mysql -uroot -p${DBROOT} -e \ - "$(docker exec -it $(docker ps -f name=mysql-mailcow -q) mysql -uroot -p${DBROOT} -e "SELECT GROUP_CONCAT('DROP TABLE ', TABLE_SCHEMA, '.', TABLE_NAME SEPARATOR ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'nc_%' AND TABLE_SCHEMA = '${DBNAME}';" -BN)" - docker exec -it $(docker ps -f name=redis-mailcow -q) /bin/sh -c 'redis-cli KEYS "*nextcloud*" | xargs redis-cli DEL' - if [ -d ./data/web/nextcloud/config ]; then - mv ./data/web/nextcloud/config/ ./data/conf/nextcloud-config-folder-$(date +%s).bak - fi - [[ -d ./data/web/nextcloud ]] && rm -rf ./data/web/nextcloud + docker exec -it $(docker ps -f name=mysql-mailcow -q) mysql -uroot -p${DBROOT} -e \ + "$(docker exec -it $(docker ps -f name=mysql-mailcow -q) mysql -uroot -p${DBROOT} -e "SELECT IFNULL(GROUP_CONCAT('DROP TABLE ', TABLE_SCHEMA, '.', TABLE_NAME SEPARATOR ';'),'SELECT NULL;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'nc_%' AND TABLE_SCHEMA = '${DBNAME}';" -BN)" + docker exec -it $(docker ps -f name=redis-mailcow -q) /bin/sh -c ' cat < /dev/null 2>&1 ; then + read -p "Cannot ping subdomain, continue anyway? [y|N] " NC_CONT_FAIL + [[ ! ${NC_CONT_FAIL,,} =~ ^(yes|y)$ ]] && { echo "Ok, exiting..."; exit 1; } + fi + fi + ADMIN_NC_PASS=$( /dev/null 2>&1 ; then - read -p "Cannot ping subdomain, continue anyway? [y|N] " NC_CONT_FAIL - [[ ! ${NC_CONT_FAIL,,} =~ ^(yes|y)$ ]] && { echo "Ok, exiting..."; exit 1; } - fi - fi + curl -L# -o nextcloud.tar.bz2 "https://download.nextcloud.com/server/releases/latest-15.tar.bz2" || { echo "Failed to download Nextcloud archive."; exit 1; } \ + && tar -xjf nextcloud.tar.bz2 -C ./data/web/ \ + && rm nextcloud.tar.bz2 \ + && mkdir -p ./data/web/nextcloud/data \ + && chmod +x ./data/web/nextcloud/occ - ADMIN_NC_PASS=$(> mailcow.conf - echo "# mailcow-network will still be created as IPv6 enabled, all containers will be created" >> mailcow.conf - echo "# without IPv6 support." >> mailcow.conf - echo "# Use 1 for disabled, 0 for enabled" >> mailcow.conf - echo "SYSCTL_IPV6_DISABLED=0" >> mailcow.conf - fi elif [[ ${option} == "COMPOSE_PROJECT_NAME" ]]; then if ! grep -q ${option} mailcow.conf; then echo "Adding new option \"${option}\" to mailcow.conf" @@ -200,6 +213,46 @@ for option in ${CONFIG_ARRAY[@]}; do echo '# Use this IPv6 for outgoing connections (SNAT)' >> mailcow.conf echo "#SNAT6_TO_SOURCE=" >> mailcow.conf fi + elif [[ ${option} == "MAILDIR_GC_TIME" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Garbage collector cleanup' >> mailcow.conf + echo '# Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring' >> mailcow.conf + echo '# How long should objects remain in the garbage until they are being deleted? (value in minutes)' >> mailcow.conf + echo '# Check interval is hourly' >> mailcow.conf + echo 'MAILDIR_GC_TIME=1440' >> mailcow.conf + fi + elif [[ ${option} == "ACL_ANYONE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Set this to "allow" to enable the anyone pseudo user. Disabled by default.' >> mailcow.conf + echo '# When enabled, ACL can be created, that apply to "All authenticated users"' >> mailcow.conf + echo '# This should probably only be activated on mail hosts, that are used exclusivly by one organisation.' >> mailcow.conf + echo '# Otherwise a user might share data with too many other users.' >> mailcow.conf + echo 'ACL_ANYONE=disallow' >> mailcow.conf + fi + elif [[ ${option} == "SOLR_HEAP" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Solr heap size, there is no recommendation, please see Solr docs.' >> mailcow.conf + echo '# Solr is a prone to run OOM on large systems and should be monitored. Unmonitored Solr setups are not recommended.' >> mailcow.conf + echo '# Solr will refuse to start with total system memory below or equal to 2 GB.' >> mailcow.conf + echo "SOLR_HEAP=1024" >> mailcow.conf + fi + elif [[ ${option} == "SKIP_SOLR" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Solr is disabled by default after upgrading from non-Solr to Solr-enabled mailcows.' >> mailcow.conf + echo '# Disable Solr or if you do not want to store a readable index of your mails in solr-vol-1.' >> mailcow.conf + echo "SKIP_SOLR=y" >> mailcow.conf + fi + elif [[ ${option} == "MAILDIR_SUB" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# MAILDIR_SUB defines a path in a users virtual home to keep the maildir in. Leave empty for updated setups.' >> mailcow.conf + echo "#MAILDIR_SUB=Maildir" >> mailcow.conf + echo "MAILDIR_SUB=" >> mailcow.conf + fi elif ! grep -q ${option} mailcow.conf; then echo "Adding new option \"${option}\" to mailcow.conf" echo "${option}=n" >> mailcow.conf @@ -207,7 +260,7 @@ for option in ${CONFIG_ARRAY[@]}; do done echo -en "Checking internet connection... " -curl -o /dev/null google.com -sm3 +curl -o /dev/null 1.1.1.1 -sm3 if [[ $? != 0 ]]; then echo -e "\e[31mfailed\e[0m" exit 1 @@ -246,6 +299,8 @@ docker-compose down # Silently fixing remote url from andryyy to mailcow git remote set-url origin https://github.com/mailcow/mailcow-dockerized echo -e "\e[32mCommitting current status...\e[0m" +[[ -z "$(git config user.name)" ]] && git config user.name moo +[[ -z "$(git config user.email)" ]] && git config user.email moo@cow.moo git update-index --assume-unchanged data/conf/rspamd/override.d/worker-controller-password.inc git add -u git commit -am "Before update on ${DATE}" > /dev/null @@ -273,7 +328,6 @@ elif [[ ${MERGE_RETURN} != 0 ]]; then exit 1 fi - echo -e "\e[32mFetching new docker-compose version...\e[0m" sleep 2 if [[ ! -z $(which pip) && $(pip list --local | grep -c docker-compose) == 1 ]]; then @@ -315,9 +369,8 @@ if grep -q 'SYSCTL_IPV6_DISABLED=1' mailcow.conf; then read -p "Press any key to continue..." < /dev/tty fi -echo -e "Fixing project name... " +# Checking for old project name bug sed -i 's#COMPOSEPROJECT_NAME#COMPOSE_PROJECT_NAME#g' mailcow.conf -sed -i '/COMPOSE_PROJECT_NAME=/s/-//g' mailcow.conf echo -e "Fixing PHP-FPM worker ports for Nginx sites..." sed -i 's#phpfpm:9000#phpfpm:9002#g' data/conf/nginx/*.conf @@ -325,15 +378,23 @@ if ls data/conf/nginx/*.custom 1> /dev/null 2>&1; then sed -i 's#phpfpm:9000#phpfpm:9002#g' data/conf/nginx/*.custom fi -if [[ -f "data/web/nextcloud/occ" ]]; then -echo "Setting Nextcloud Redis timeout to 0.0..." -docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ config:system:set redis timeout --value=0.0 --type=integer" +# Fix Rspamd maps +if [ -f data/conf/rspamd/custom/global_from_blacklist.map ]; then + mv data/conf/rspamd/custom/global_from_blacklist.map data/conf/rspamd/custom/global_smtp_from_blacklist.map +fi +if [ -f data/conf/rspamd/custom/global_from_whitelist.map ]; then + mv data/conf/rspamd/custom/global_from_whitelist.map data/conf/rspamd/custom/global_smtp_from_whitelist.map fi echo -e "\e[32mStarting mailcow...\e[0m" sleep 2 docker-compose up -d --remove-orphans +if [[ -f "data/web/nextcloud/occ" ]]; then + echo "Setting Nextcloud Redis timeout to 0.0..." + docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ config:system:set redis timeout --value=0.0 --type=integer" +fi + echo -e "\e[32mCollecting garbage...\e[0m" docker_garbage