├── scrapy ├── wooyun │ ├── wooyun │ │ ├── __init__.py │ │ ├── spiders │ │ │ ├── __init__.py │ │ │ └── WooyunSpider.py │ │ ├── items.py │ │ ├── pipelines.py │ │ └── settings.py │ └── scrapy.cfg └── wooyun_drops │ ├── wooyun_drops │ ├── __init__.py │ ├── spiders │ │ ├── __init__.py │ │ └── WooyunSpider.py │ ├── items.py │ ├── settings.py │ └── pipelines.py │ └── scrapy.cfg ├── index.png ├── search.png ├── .gitignore ├── flask ├── static │ ├── bugs │ │ ├── bootstrap │ │ │ ├── fonts │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── js │ │ │ │ ├── npm.js │ │ │ │ └── bootstrap.min.js │ │ │ └── css │ │ │ │ ├── bootstrap-theme.min.css │ │ │ │ └── bootstrap-theme.css │ │ ├── js │ │ │ └── jquery.twbsPagination.js │ │ └── css │ │ │ └── style.css │ └── drops │ │ └── js │ │ └── bootstrap.min.js ├── templates │ ├── search_drops.html │ ├── search_bugs.html │ ├── index.html │ └── base.html └── app.py ├── update.sh ├── install.md ├── tornado ├── templates │ ├── search_drops.html │ ├── search_bugs.html │ ├── index.html │ └── base.html └── app.py ├── README.md └── elasticsearch_install.md /scrapy/wooyun/wooyun/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scrapy/wooyun_drops/wooyun_drops/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/index.png -------------------------------------------------------------------------------- /search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/search.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | flask/static/drops/运维安全-2547.html 3 | 4 | *.html 5 | 6 | *.jpg 7 | 8 | *.pyc 9 | -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0oVicero0/wooyun_public/master/flask/static/bugs/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /scrapy/wooyun/wooyun/spiders/__init__.py: -------------------------------------------------------------------------------- 1 | # This package will contain the spiders of your Scrapy project 2 | # 3 | # Please refer to the documentation for information on how to create and manage 4 | # your spiders. 5 | -------------------------------------------------------------------------------- /scrapy/wooyun_drops/wooyun_drops/spiders/__init__.py: -------------------------------------------------------------------------------- 1 | # This package will contain the spiders of your Scrapy project 2 | # 3 | # Please refer to the documentation for information on how to create and manage 4 | # your spiders. 5 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mongod --config /usr/local/etc/mongod.conf & 4 | 5 | cd scrapy/wooyun 6 | scrapy crawl wooyun -a page_max=100 7 | 8 | cd ../wooyun_drops 9 | scrapy crawl wooyun -a page_max=10 10 | 11 | cd ../../flask 12 | ./app.py 13 | -------------------------------------------------------------------------------- /scrapy/wooyun/scrapy.cfg: -------------------------------------------------------------------------------- 1 | # Automatically created by: scrapy startproject 2 | # 3 | # For more information about the [deploy] section see: 4 | # https://scrapyd.readthedocs.org/en/latest/deploy.html 5 | 6 | [settings] 7 | default = wooyun.settings 8 | 9 | [deploy] 10 | #url = http://localhost:6800/ 11 | project = wooyun 12 | -------------------------------------------------------------------------------- /scrapy/wooyun_drops/scrapy.cfg: -------------------------------------------------------------------------------- 1 | # Automatically created by: scrapy startproject 2 | # 3 | # For more information about the [deploy] section see: 4 | # https://scrapyd.readthedocs.org/en/latest/deploy.html 5 | 6 | [settings] 7 | default = wooyun_drops.settings 8 | 9 | [deploy] 10 | #url = http://localhost:6800/ 11 | project = wooyun_drops 12 | -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /scrapy/wooyun_drops/wooyun_drops/items.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your scraped items 4 | # 5 | # See documentation in: 6 | # http://doc.scrapy.org/en/latest/topics/items.html 7 | 8 | import scrapy 9 | 10 | 11 | class WooyunItem(scrapy.Item): 12 | # define the fields for your item here like: 13 | # name = scrapy.Field() 14 | title = scrapy.Field() 15 | author = scrapy.Field() 16 | datetime = scrapy.Field() 17 | category = scrapy.Field() 18 | url = scrapy.Field() 19 | html = scrapy.Field() 20 | 21 | image_urls = scrapy.Field() 22 | images = scrapy.Field() 23 | 24 | -------------------------------------------------------------------------------- /scrapy/wooyun/wooyun/items.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your scraped items 4 | # 5 | # See documentation in: 6 | # http://doc.scrapy.org/en/latest/topics/items.html 7 | 8 | import scrapy 9 | 10 | 11 | class WooyunItem(scrapy.Item): 12 | # define the fields for your item here like: 13 | # name = scrapy.Field() 14 | datetime = scrapy.Field() 15 | datetime_open = scrapy.Field() 16 | title = scrapy.Field() 17 | wooyun_id = scrapy.Field() 18 | author = scrapy.Field() 19 | bug_type = scrapy.Field() 20 | html = scrapy.Field() 21 | # 22 | image_urls = scrapy.Field() 23 | images = scrapy.Field() 24 | -------------------------------------------------------------------------------- /install.md: -------------------------------------------------------------------------------- 1 | wooyun_public在Ubuntu下的安装 2 | ============================= 3 | 4 | 以下为在ubuntu14.04和16.04的安装过程,需要安装的依赖组件: 5 | 6 | + python 2.7和pip 7 | + mongodb 8 | + scrapy 9 | + flask 或 tornado 10 | + pymongo 11 | 12 | 步骤 13 | -------- 14 | 1、安装python、pip、mongodb 15 | 16 | ```bash 17 | sudo apt-get install python python-pip mongodb 18 | ``` 19 | 2、安装scrapy 20 | 21 | ```bash 22 | 安装scrapy如果报错,则先apt-get安装下述依赖包,然后安装pip安装lxml后即可正常安装scrapy 23 | sudo apt-get install libxml2-dev libxslt1-dev python-dev zlib1g-dev libevent-dev python-openssl 24 | 25 | sudo pip install lxml 26 | sudo pip install scrapy 27 | ``` 28 | 3、安装pymongo和flask(或tornado) 29 | 30 | ```bash 31 | sudo pip install flask pymongo 32 | (sudo pip install tornado) 33 | ``` 34 | 4、从github下载源码 35 | 36 | ```bash 37 | git clone https://github.com/hanc00l/wooyun_public 38 | ``` 39 | 40 | 41 | -------------------------------------------------------------------------------- /tornado/templates/search_drops.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |
7 |

关键字【{{keywords}}】的搜索结果共{{page_info['total_rows']}}记录

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for row in page_info['rows'] %} 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | {% end %} 25 |
发表时间标题文章类型作者
{{row['datetime']}} 19 | {{row['title']}}{{row['category']}}{{row['author']}}
26 | 27 | 28 |
    29 | 43 |
    44 |
    45 |
    46 |
    47 | {% end %} -------------------------------------------------------------------------------- /flask/templates/search_drops.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
    4 |
    5 |
    6 |
    7 |

    关键字【{{keywords}}】的搜索结果共{{page_info['total_rows']}}记录

    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for row in page_info['rows'] %} 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | {% endfor %} 25 |
    发表时间标题文章类型作者
    {{row['datetime']}} 19 | {{row['title']}}{{row['category']}}{{row['author']}}
    26 | 27 | 28 |
      29 | 43 |
      44 |
      45 |
      46 |
      47 | {% endblock %} -------------------------------------------------------------------------------- /tornado/templates/search_bugs.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
      4 |
      5 |
      6 |
      7 |

      关键字【{{keywords}}】的搜索结果共{{page_info['total_rows']}}记录

      8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for row in page_info['rows'] %} 16 | 17 | 18 | 20 | 21 | 22 | 23 | {% end %} 24 |
      提交时间标题漏洞类型提交者
      {{row['datetime']}} 19 | {{row['title']}}{{row['bug_type']}}{{row['author']}}
      25 | 26 | 27 |
        28 | 42 |
        43 |
        44 |
        45 |
        46 | {% end %} -------------------------------------------------------------------------------- /flask/templates/search_bugs.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
        4 |
        5 |
        6 |
        7 |

        关键字【{{keywords}}】的搜索结果共{{page_info['total_rows']}}记录

        8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% for row in page_info['rows'] %} 16 | 17 | 18 | 20 | 21 | 22 | 23 | {% endfor %} 24 |
        提交时间标题漏洞类型提交者
        {{row['datetime']}} 19 | {{row['title']}}{{row['bug_type']}}{{row['author']}}
        25 | 26 | 27 |
          28 | 42 |
          43 |
          44 |
          45 |
          46 | {% endblock %} -------------------------------------------------------------------------------- /tornado/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 |
          5 |
          6 |
          7 |

          乌云公开漏洞、知识库搜索  漏洞/文章数:{{total_count_bugs}}/{{total_count_drops}}

          8 |
          9 |
          10 | 11 | 12 | 13 | 14 |
          15 |
          16 |
          17 |
          18 |
          19 | 22 |
          23 |
          24 | 28 |
          29 |
          30 |
          31 |
          32 | 35 |
          36 |
          37 |
          38 |
          39 |
          40 |
          41 |
          42 | 43 |
          44 |
          45 | 46 | {% end %} 47 | -------------------------------------------------------------------------------- /flask/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 |
          5 |
          6 |
          7 |

          乌云公开漏洞、知识库搜索  漏洞/文章数:{{total_count_bugs}}/{{total_count_drops}}

          8 |
          9 |
          10 | 11 | 12 | 13 | 14 |
          15 |
          16 |
          17 |
          18 |
          19 | 22 |
          23 |
          24 | 28 |
          29 |
          30 |
          31 |
          32 | 35 |
          36 |
          37 |
          38 |
          39 |
          40 |
          41 |
          42 | 43 |
          44 |
          45 | 46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /tornado/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{title}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 35 | 36 |
          37 | {% block content %}{% end %} 38 | 39 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /flask/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{title}} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 35 | 36 |
          37 | {% block content %}{% endblock %} 38 | 39 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wooyun_public 2 | **乌云公开漏洞、知识库爬虫和搜索** 3 | 4 | **crawl and search for wooyun.org public bug(vulnerability) and drops** 5 | 6 | ![index](index.png) 7 | ![search](search.png) 8 | 9 | 1.依赖组件 10 | -------- 11 | + python 2.7和pip 12 | + mongodb 13 | + scrapy 14 | + flask 或者 tornado 15 | + pymongo 16 | + Elasticserch (搜索引擎,可选) 17 | 18 | [在ubuntu下的安装过程(点我)](install.md) 19 | 20 | 21 | 2.爬虫 22 | -------- 23 | 24 | + 乌云公开漏洞和知识库的爬虫分别位于目录scrapy/wooyun和scrapy/wooyun_drops 25 | 26 | + 运行scrapy crawl wooyun -a page_max=1 -a local_store=false -a update=false,有三个参数用于控制爬取: 27 | 28 | -a page_max: 控制爬取的页数,默认为1,如果值为0,表示所有页面 29 | -a local_store: 控制是否将每个漏洞离线存放到本地,默认为false 30 | -a update:控制是否重复爬取,默认为false 31 | 32 | + 第一次爬取全部内容时,用scrapy crawl wooyun -a page_max=0 -a update=true 33 | 34 | + 平时只爬取最近的更新时,用scrapy crawl wooyun -a page_max=1,可以根据自己的爬取频率和网站更新情况调整page_max的值 35 | 36 | + 全部公开漏洞的列表和每个漏洞的文本内容存在mongodb中,大概约2G内容;如果整站爬全部文本和图片作为离线查询,大概需要10G空间、2小时(10M电信带宽);爬取全部知识库,总共约500M空间。(截止2015年10月) 37 | 38 | 3.搜索 39 | -------- 40 | + 漏洞搜索使用了Flask作为web server,bootstrap作为前端(8.12增加tornador web server,可配合nginx反向代理,支持高并发的应用) 41 | 42 | + 启动web server :在flask目录下运行./app.py,默认端口是5000 43 | 44 | + #### 启动Elassticsearch(如果已配置了Elasticsearch):在elasticsearch-2.3.4/bin目录下运行./elasticsearch -d (-d表示以后台方式运行) 45 | 46 | + 搜索:在浏览器通过http://localhost:5000进行搜索漏洞,多个关键字可以用空格分开。 47 | 48 | + 默认使用mongodb的数据库搜索,在进行全文搜索时比较慢,推荐安装使用Elasicsearch搜索引擎。[安装和配置Elasicsearch的方法(点我)](elasticsearch_install.md) 49 | 50 | 4.为mongodb数据库创建索引 51 | -------- 52 | ```bash 53 | mongo 54 | use wooyun 55 | db.wooyun_list.ensureIndex({"datetime":1}) 56 | db.wooyun_drops.ensureIndex({"datetime":1}) 57 | ``` 58 | 59 | 5.虚拟机 60 | ------ 61 | 62 | + 虚拟机1:在2016年6月底爬的wooyun全部漏洞库和知识库内容,集成了Elasticsearch搜索,总共35G(压缩后约14G),网盘地址为: [http://pan.baidu.com/s/1kVtY2rX](http://pan.baidu.com/s/1kVtY2rX) ,提取密码:5ik7(8.5更新) 63 | 64 | 使用方法: 65 | 66 | 1、压缩包解压后是一个vmware虚拟机的镜像,可以由vmware直接打开运行; 67 | 2、由于在制作压缩包时虚拟机为“挂起”状态,当前虚拟机的IP地址可能和宿主机的IP地址段不一致,请将虚拟机重启后重新获取IP地址,虚拟机用户密码为hancool/qwe123; 68 | 3、进入wooyun_public目录,先用git更新一下到最新的代码git pull(如果提示merge冲突,先进行git reset --hard origin/master后再git pull); 69 | 4、在elasticsearch-2.3.4/bin目录下运行./elasticsearch -d (-d表示以后台方式运行) 70 | 5、进入wooyun_public/flask目录,运行./app.py; 71 | 6、打开浏览器,输入http://ip:5000,ip为虚拟机的网卡地址(使用ifconfig eth0查看) 72 | 73 | 74 | + 虚拟机2:已打包了一个安装了所有组件和elasticsearch搜索的虚拟机,不包含具体内容,压缩后约2.3G(由于wooyun还处于升级关闭期间,无法进行内容的爬取),网盘地址:[http://pan.baidu.com/s/1nvrS3zj](http://pan.baidu.com/s/1nvrS3zj),提取密码:2290 (8.5更新) 75 | 76 | 使用方法: 77 | 78 | 1、压缩包解压后是一个vmware虚拟机的镜像,可以由vmware直接打开运行; 79 | 2、由于在制作压缩包时虚拟机为“挂起”状态,当前虚拟机的IP地址可能和宿主机的IP地址段不一致,请将虚拟机重启后重新获取IP地址,虚拟机用户密码为hancool/qwe123; 80 | 3、在elasticsearch-2.3.4/bin目录下运行./elasticsearch -d (-d表示以后台方式运行) 81 | 4、运行mongo-connect,用于将mongodb的数据实时同步到elasticsearch:sudo mongo-connector -m localhost:27017 -t localhost:9200 -d elastic2_doc_manager & 82 | 5、进入wooyun_public目录,先用git更新一下到最新的代码git pull(如果提示merge冲突,先进行git reset --hard origin/master后再git pull); 83 | 6、分别进入wooyun_public目录下的wooyun和wooyun_drops,运行爬虫爬取数据(爬取全部数据并且本地离线缓存):scrapy crawl wooyun -a page_max=0 -a local_store=true -a update=true 84 | 7、进入wooyun_publich目录下的flask,运行./app.py,启动web服务 85 | 8、打开浏览器,输入http://ip:5000,ip为虚拟机的网卡地址(使用ifconfig eth0查看) 86 | 87 | 88 | 6.其它 89 | -------- 90 | 91 | + 本程序只用于技术研究和个人使用,程序组件均为开源程序,漏洞和知识库来源于乌云公开漏洞,版权归wooyun.org。 92 | 93 | + 期待雨过天晴、重开wooyun! 94 | 95 | + hancool@163.com 96 | 97 | -------------------------------------------------------------------------------- /scrapy/wooyun_drops/wooyun_drops/spiders/WooyunSpider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import datetime 3 | from urllib import unquote 4 | import pymongo 5 | import scrapy 6 | from wooyun_drops.items import WooyunItem 7 | from scrapy.conf import settings 8 | 9 | 10 | class WooyunSpider(scrapy.Spider): 11 | name = "wooyun" 12 | allowed_domains = ["wooyun.org"] 13 | start_urls = [ 14 | 'http://drops.wooyun.org/' 15 | ] 16 | 17 | def __init__(self,page_max=settings['PAGE_MAX_DEFAULT'],local_store=settings['LOCAL_STORE_DEFAULT'],\ 18 | update=settings['UPDATE_DEFAULT'],*args, **kwargs): 19 | self.page_max = int(page_max) 20 | self.local_store = 'true' == local_store.lower() 21 | self.update = 'true' == update.lower() 22 | 23 | self.connection_string = "mongodb://%s:%d" % (settings['MONGODB_SERVER'],settings['MONGODB_PORT']) 24 | self.client = pymongo.MongoClient(self.connection_string) 25 | self.db = self.client[settings['MONGODB_DB']] 26 | self.collection = self.db[settings['MONGODB_COLLECTION']] 27 | 28 | def closed(self,reason): 29 | self.client.close() 30 | 31 | def parse(self, response): 32 | # 第 1 页,共 80 页 33 | total_pages = response.xpath("//div[@class='wp-pagenavi']/span[@class = 'pages']/text()").re(u"共 (\d+) 页")[0] 34 | if self.page_max == 0: 35 | end_page = int(total_pages) 36 | else: 37 | end_page = self.page_max 38 | 39 | for page in range(1,end_page + 1): 40 | page_url = "http://drops.wooyun.org/page/%d"%page 41 | yield scrapy.Request(page_url, self.parse_post_urls) 42 | 43 | def parse_post_urls(self, response): 44 | post_urls = response.xpath("//div[@class = 'post']/h2[@class = 'entry-title']/a/@href").extract() 45 | for url in post_urls: 46 | url = response.urljoin(url) 47 | if self.update or not self.__search_mongodb(url): 48 | yield scrapy.Request(url, self.parse_detail) 49 | 50 | def parse_detail(self,response): 51 | item = WooyunItem() 52 | item['url'] = unquote(response.url) 53 | item['category'] = unquote(response.url).split('//')[1].split('/')[1] 54 | item['title'] = response.xpath("//title/text()").extract()[0].split(u"|")[0].strip() 55 | item['author'] = response.xpath("//div[@class = 'entry-meta']/a/@href").extract()[0].split("/")[2] 56 | dt = response.xpath("//div[@class = 'entry-meta']/time/text()").extract()[0].split(' ')[0].split('/') 57 | dt_time = response.xpath("//div[@class = 'entry-meta']/time/text()").extract()[0].split(' ')[1].split(':') 58 | item['datetime'] = datetime(int(dt[0]),int(dt[1]),int(dt[2]),int(dt_time[0]),int(dt_time[1])) 59 | item['image_urls'] = [] 60 | if self.local_store: 61 | image_urls = response.xpath("//p/img/@src").extract() 62 | #skip the https image download 63 | #skip www.quip.com,can'n be downloaded 64 | for u in image_urls: 65 | if 'https://' not in u and 'www.quip.com' not in u: 66 | item['image_urls'].append(u) 67 | 68 | item['html'] = response.body.decode('utf-8','ignore') 69 | 70 | return item 71 | 72 | def __search_mongodb(self,url): 73 | # 74 | wooyun_drops_exsist = True if self.collection.find({'url':url}).count()>0 else False 75 | # 76 | return wooyun_drops_exsist 77 | -------------------------------------------------------------------------------- /scrapy/wooyun/wooyun/pipelines.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import logging 3 | import re 4 | from datetime import datetime 5 | import copy 6 | import codecs 7 | import pymongo 8 | from scrapy.conf import settings 9 | from scrapy.exceptions import DropItem 10 | 11 | # Define your item pipelines here 12 | # 13 | # Don't forget to add your pipeline to the ITEM_PIPELINES setting 14 | # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html 15 | 16 | class MongoDBPipeline(object): 17 | def __init__(self): 18 | self.connection_string = "mongodb://%s:%d" % (settings['MONGODB_SERVER'],settings['MONGODB_PORT']) 19 | 20 | def open_spider(self, spider): 21 | self.client = pymongo.MongoClient(self.connection_string) 22 | self.db = self.client[settings['MONGODB_DB']] 23 | self.collection = self.db[settings['MONGODB_COLLECTION']] 24 | self.log = logging.getLogger(spider.name) 25 | 26 | def close_spider(self, spider): 27 | self.client.close() 28 | 29 | def process_item(self, item, spider): 30 | # 31 | post_data = copy.deepcopy(item) 32 | post_data.pop('image_urls') 33 | post_data.pop('images') 34 | # 35 | wooyun_id_exsist = True if self.collection.find({'wooyun_id':item['wooyun_id']}).count()>0 else False 36 | if wooyun_id_exsist == False: 37 | self.collection.insert_one(dict(post_data)) 38 | self.log.debug('wooyun_id:%s added to mongdb!'%item['wooyun_id'],) 39 | else: 40 | if spider.update: 41 | self.collection.update_one({'wooyun_id':item['wooyun_id']},{'$set':dict(post_data)}) 42 | self.log.debug('wooyun_id:%s exist,update!' %item['wooyun_id']) 43 | else: 44 | self.log.debug('wooyun_id:%s exist,not update!' %item['wooyun_id']) 45 | 46 | return item 47 | 48 | class WooyunSaveToLocalPipeline(object): 49 | def process_item(self,item,spider): 50 | # 51 | if spider.local_store == False: 52 | return item 53 | # 54 | if item['wooyun_id'] == None or item['wooyun_id'] =='': 55 | self.log.debug('There is none wooyun_id,this item do not be saved!') 56 | return item 57 | # 58 | post_data = copy.deepcopy(item) 59 | if self.__process_html(post_data) == False: 60 | return item 61 | # 62 | path_name = settings['LOCAL_STORE'] + item['wooyun_id'] + '.html' 63 | #save file as utf-8 format 64 | with codecs.open(path_name,mode='w',encoding='utf-8',errors='ignore') as f: 65 | f.write(post_data['html']) 66 | 67 | return item 68 | 69 | def __process_html(self,item): 70 | if item['html'] == None or item['html'] == '': 71 | self.log.debug('the wooyunid:%s html body is empty!'%item['wooyun_id']) 72 | return False 73 | #deal the img 74 | for img in item['images']: 75 | #处理部份图片存放于http://www.wooyun.org时,使用/upload/..形式的路径 76 | if img['url'].startswith('http://www.wooyun.org'): 77 | img['url'] = img['url'].replace('http://www.wooyun.org','') 78 | item['html'] = re.sub('0 else False 38 | if not wooyun_drops_exsist : 39 | self.collection.insert_one(dict(post_data)) 40 | self.log.debug('wooyun_drop url:%s added to mongdb!'%item['url'],) 41 | else: 42 | if spider.update: 43 | self.collection.update_one({'url':item['url']},{'$set':dict(post_data)}) 44 | self.log.debug('wooyun_drop url:%s exist,update!' %item['url']) 45 | else: 46 | self.log.debug('wooyun_drop url:%s exist,not update!' %item['url']) 47 | 48 | return item 49 | 50 | def __map_category(self,category_name): 51 | category_map={'papers':u'漏洞分析','tips':u'技术分享','tools':u'工具收集','news':u'业界资讯',\ 52 | 'web':u'web安全','pentesting':u'渗透案例','mobile':u'移动安全','wireless':u'无线安全',\ 53 | 'database':u'数据库安全','binary':u'二进制安全'} 54 | if category_name in category_map: 55 | return category_map[category_name] 56 | 57 | return category_name 58 | 59 | class WooyunSaveToLocalPipeline(object): 60 | def process_item(self,item,spider): 61 | # 62 | if not spider.local_store: 63 | return item 64 | # 65 | if item['url'] == None or item['url'] =='': 66 | self.log.debug('There is none wooyun_drop url,this item do not be saved!') 67 | return item 68 | # 69 | post_data = copy.deepcopy(item) 70 | if not self.__process_html(post_data): 71 | return item 72 | # 73 | path_name = settings['LOCAL_STORE'] + self.__process_local_filename(item['url']) 74 | #save file as utf-8 format 75 | with codecs.open(path_name,mode='w',encoding='utf-8',errors='ignore') as f: 76 | f.write(post_data['html']) 77 | 78 | return item 79 | 80 | def __process_local_filename(self,url): 81 | urlsep = url.split('//')[1].split('/') 82 | return '%s-%s.html'%(urlsep[1],urlsep[2]) 83 | 84 | def __process_html(self,item): 85 | if item['html'] == None or item['html'] == '': 86 | self.log.debug('the wooyunid:%s html body is empty!'%item['wooyun_id']) 87 | return False 88 | jquery_js = "http://wooyun.b0.upaiyun.com/static/js/jquery.min.js" 89 | bootstrap_js = "http://wooyun.b0.upaiyun.com/static/js/bootstrap.min.js" 90 | main_css = "http://wooyun.b0.upaiyun.com/static/css/95e46879.main.css" 91 | bootstrap_css = "http://wooyun.b0.upaiyun.com/static/css/bootstrap.min.css" 92 | 93 | wooyun_jquery_js = "static/drops/js/jquery.js" 94 | wooyun_bootstrap_js = "static/dropsjs/bootstrap.min.js" 95 | wooyun_main_css = "static/drops/css/95e46879.main.css" 96 | wooyun_bootstrap_css = "static/drops/css/bootstrap.min.css" 97 | 98 | item['html'] = item['html'].replace(jquery_js, wooyun_jquery_js).replace(bootstrap_js, wooyun_bootstrap_js) 99 | item['html'] = item['html'].replace(main_css, wooyun_main_css).replace(bootstrap_css, wooyun_bootstrap_css) 100 | 101 | for it in item['images']: 102 | item['html'] = item['html'].replace(it['url'], 'static/drops/%s'%it['path']) 103 | 104 | return True 105 | 106 | 107 | -------------------------------------------------------------------------------- /scrapy/wooyun/wooyun/spiders/WooyunSpider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from datetime import datetime 3 | import pymongo 4 | import scrapy 5 | from wooyun.items import WooyunItem 6 | from scrapy.conf import settings 7 | 8 | 9 | class WooyunSpider(scrapy.Spider): 10 | name = "wooyun" 11 | allowed_domains = ["wooyun.org"] 12 | start_urls = [ 13 | 'http://wooyun.org/bugs/new_public/' 14 | ] 15 | 16 | def __init__(self,page_max=settings['PAGE_MAX_DEFAULT'],local_store=settings['LOCAL_STORE_DEFAULT'],\ 17 | update=settings['UPDATE_DEFAULT'],*args, **kwargs): 18 | self.page_max = int(page_max) 19 | self.local_store = 'true' == local_store.lower() 20 | self.update = 'true' == update.lower() 21 | 22 | self.connection_string = "mongodb://%s:%d" % (settings['MONGODB_SERVER'],settings['MONGODB_PORT']) 23 | self.client = pymongo.MongoClient(self.connection_string) 24 | self.db = self.client[settings['MONGODB_DB']] 25 | self.collection = self.db[settings['MONGODB_COLLECTION']] 26 | 27 | def closed(self,reason): 28 | self.client.close() 29 | 30 | def parse(self, response): 31 | total_pages = response.xpath("//p[@class='page']/text()").re('\d+')[1] 32 | if self.page_max == 0: 33 | end_page = int(total_pages) 34 | else: 35 | end_page = self.page_max 36 | for n in range(1,end_page + 1): 37 | page = "/bugs/new_public/page/%d" %n 38 | url = response.urljoin(page) 39 | yield scrapy.Request(url, self.parse_list) 40 | 41 | def parse_list(self,response): 42 | links = response.xpath('//tbody/tr/td/a/@href').extract() 43 | for url in links: 44 | wooyun_id = url.split('/')[2] 45 | if self.update == True or self.__search_mongodb(wooyun_id) == False: 46 | url = response.urljoin(url) 47 | yield scrapy.Request(url, self.parse_detail) 48 | 49 | def parse_detail(self,response): 50 | item = WooyunItem() 51 | item['wooyun_id'] = response.xpath('//*[@id="bugDetail"]/div[5]/h3[1]/a/@href').extract()[0].split('/')[2] 52 | item['title'] = response.xpath('//title/text()').extract()[0].split("|")[0] 53 | item['bug_type'] = response.xpath("//h3[@class='wybug_type']/text()").extract()[0].split(u':')[1].strip() 54 | #item['bug_type'] = response.xpath('//*[@id="bugDetail"]/div[5]/h3[7]/text()').extract()[0].split(u':')[1].strip() 55 | #some author not text,for examp: 56 | #http://wooyun.org/bugs/wooyun-2010-01010 57 | #there will be error while parse author,so do this 58 | try: 59 | #item['author'] = response.xpath("//h3[@class='wybug_author']/a/text()").extract()[0] 60 | item['author'] = response.xpath('//*[@id="bugDetail"]/div[5]/h3[4]/a/text()').extract()[0] 61 | except: 62 | item['author'] ='' 63 | #the response.body type is str,so we need to convert to utf-8 64 | #if not utf-8,saving to mongodb may have some troubles 65 | item['html'] = response.body.decode('utf-8','ignore') 66 | #dt = response.xpath("//h3[@class='wybug_date']/text()").re("[\d+]{4}-[\d+]{2}-[\d+]{2}")[0].split('-') 67 | dt = response.xpath('//*[@id="bugDetail"]/div[5]/h3[5]/text()').re("[\d+]{4}-[\d+]{2}-[\d+]{2}")[0].split('-') 68 | item['datetime'] = datetime(int(dt[0]),int(dt[1]),int(dt[2])) 69 | #dt = response.xpath("//h3[@class='wybug_open_date']/text()").re("[\d+]{4}-[\d+]{2}-[\d+]{2}")[0].split('-') 70 | dt = response.xpath('//*[@id="bugDetail"]/div[5]/h3[6]/text()').re("[\d+]{4}-[\d+]{2}-[\d+]{2}")[0].split('-') 71 | item['datetime_open'] = datetime(int(dt[0]),int(dt[1]),int(dt[2])) 72 | #images url for download 73 | item['image_urls']=[] 74 | if self.local_store: 75 | #乌云图片目前发两种格式,一种是http://static.wooyun.org/wooyun/upload/,另一格式是/upload/... 76 | #因此,对后一种在爬取时,增加http://www.wooyun.org,以形成完整的url地址 77 | #同时,在piplines.py存放时,作相应的反向处理 78 | image_urls = response.xpath("//img[contains(@src, '/upload/')]/@src").extract() 79 | for u in image_urls: 80 | if self.__check_ingnored_image(u): 81 | continue 82 | if u.startswith('/'): 83 | u = 'http://www.wooyun.org' + u 84 | item['image_urls'].append(u) 85 | return item 86 | 87 | def __check_ingnored_image(self,image_url): 88 | for ignored_url in settings['IMAGE_DOWLOAD_IGNORED']: 89 | if ignored_url in image_url: 90 | return True 91 | 92 | return False 93 | 94 | def __search_mongodb(self,wooyun_id): 95 | # 96 | wooyun_id_exsist = True if self.collection.find({'wooyun_id':wooyun_id}).count()>0 else False 97 | # 98 | return wooyun_id_exsist 99 | -------------------------------------------------------------------------------- /elasticsearch_install.md: -------------------------------------------------------------------------------- 1 | Elasticsearch Install 2 | ============================= 3 | 4 | 当进行全文搜索时,使用mongodb效率很低,且比较耗内存;解决办法是使用elasticsearch引擎,通过mongo-connector将数据同步到elasticsearch后进行快速搜索。 5 | 6 | 安装elasticsearch 7 | -------- 8 | 9 | 1、安装JDK(或者JRE) 10 | 11 | ```bash 12 | sudo apt-get install openjdk-7-jdk 13 | ``` 14 | 2、下载elasticseach 15 | 16 | ```bash 17 | wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.4/elasticsearch-2.3.4.tar.gz 18 | tar xvf elasticsearch-2.3.4.tar.gz 19 | ``` 20 | 21 | 3、运行elasticsearch 22 | 23 | ```bash 24 | cd elasticsearch-2.3.4/bin 25 | ./elasticsearch 26 | ``` 27 | 28 | 4、测试一下,安装完成运行后elasticsearch会在9200端口上进行监听 29 | 30 | ```bash 31 | curl -X GET http://localhost:9200 32 | { 33 | "name" : "Sebastian Shaw", 34 | "cluster_name" : "elasticsearch", 35 | "version" : { 36 | "number" : "2.3.4", 37 | "build_hash" : "e455fd0c13dceca8dbbdbb1665d068ae55dabe3f", 38 | "build_timestamp" : "2016-06-30T11:24:31Z", 39 | "build_snapshot" : false, 40 | "lucene_version" : "5.5.0" 41 | }, 42 | "tagline" : "You Know, for Search" 43 | } 44 | ``` 45 | 46 | 47 | 配置mongodb 48 | ------- 49 | 50 | 1、编辑/etc/mongodb.conf,增加: 51 | 52 | replSet=rs0 #这里是指定replSet的名字 53 | oplogSize=100 #这里是指定oplog表数据大小(太大了不支持) 54 | 55 | 重启动mongodb 56 | 57 | ```bash 58 | sudo service mongodb restart 59 | ``` 60 | 2,进入mongodb shell,初始化replicSet 61 | 62 | ```bash 63 | mongo 64 | rs.initiate( {"_id" : "rs0", "version" : 1, "members" : [ { "_id" : 0, "host" : "127.0.0.1:27017" } ]}) 65 | ``` 66 | 3,搭建好replicSet之后,退出mongo shell重新登录,提示符会变成:rs0:PRIMARY>,就可以退出Mongodb 67 | 68 | 69 | 安装中文分词插件elasticsearch-analysis-ik 70 | ------- 71 | 72 | 1、从github下载编译好好的插件 73 | 74 | ```bash 75 | cd ~ 76 | sudo apt-get install unzip 77 | wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v1.9.4/elasticsearch-analysis-ik-1.9.4.zip 78 | unzip elasticsearch-analysis-ik-1.9.4.zip -d elasticsearch-analysis-ik 79 | ``` 80 | 81 | 2、将插件复制到elasticsearch的plugins目录 82 | 83 | ```bash 84 | cp -r elasticsearch-analysis-ik elasticsearch-2.3.4/plugins 85 | ``` 86 | 87 | 3、修改elasticsearch.yml配置,定义插件配置 88 | 89 | ```bash 90 | vi elasticsearch-2.3.4/config/elasticsearch.yml 91 | ``` 92 | 在最后增加: 93 | 94 | index.analysis.analyzer.ik.type : 'ik' 95 | index.analysis.analyzer.default.type : 'ik' 96 | 97 | 4、退出并重启elasticsearch 98 | 99 | ```bash 100 | elasticsearch-2.3.4/bin/elasticsearch -d 101 | (-d表示以后台方式运行) 102 | ``` 103 | 104 | 安装mongo-connector,将数据同步到elasticsearch 105 | ------- 106 | 107 | ```bash 108 | sudo pip install mongo-connector elastic2_doc_manager 109 | sudo mongo-connector -m localhost:27017 -t localhost:9200 -d elastic2_doc_manager 110 | ``` 111 | 显示Logging to mongo-connector.log.后将会把mongodb数据库的信息同步到elasticsearch中,完全同步完成估计需要30分钟左右,同步期间不能中断,否则可能导致elasticsearch与mongodb数据不一致。 112 | 113 | 在同步过程中,可能会报错: 114 | 115 | ```bash 116 | OperationFailed: ConnectionTimeout caused by - ReadTimeoutError(HTTPConnectionPool(host=u'localhost', port=9200): Read timed out. (read timeout=10)) 117 | 2016-08-04 17:24:53,372 [ERROR] mongo_connector.oplog_manager:633 - OplogThread: Failed during dump collection cannot recover! Collection(Database(MongoClient(u'127.0.0.1', 27017), u'local'), u'oplog.rs') 118 | 2016-08-04 17:24:54,371 [ERROR] mongo_connector.connector:304 - MongoConnector: OplogThread unexpectedly stopped! Shutting down 119 | ``` 120 | 121 | ####解决办法: 122 | 123 | 修改timeout值,从默认的10改为200 124 | 125 | ```bash 126 | sudo vi /usr/local/lib/python2.7/dist-packages/mongo_connector/doc_managers/elastic2_doc_manager.py 127 | ``` 128 | 将: 129 | self.elastic = Elasticsearch(hosts=[url],**kwargs.get('clientOptions', {})) 130 | 131 | 修改为: 132 | self.elastic = Elasticsearch(hosts=[url],timeout=200, **kwargs.get('clientOptions', {})) 133 | 134 | 135 | 启用全文搜索 136 | ------- 137 | 1、安装elasticsearch-py 138 | 139 | ```bash 140 | pip install elasticsearch 141 | ``` 142 | 2、更新app.py 143 | 144 | ```bash 145 | cd ~/wooyun_public 146 | git pull 147 | ``` 148 | 149 | 3、修改app.py 150 | 151 | ```bash 152 | vi ~/wooyun_public/flask/app.py 153 | 修改: 154 | SEARCH_BY_ES = 'auto' 155 | ``` 156 | 参考链接 157 | ------- 158 | 1、[https://imququ.com/post/elasticsearch.html](https://imququ.com/post/elasticsearch.html) 159 | 160 | 2、[https://github.com/medcl/elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik) 161 | 162 | 3、[http://es.xiaoleilu.com](http://es.xiaoleilu.com) 163 | 164 | 4、[http://www.cnblogs.com/ciaos/p/3601209.html](http://www.cnblogs.com/ciaos/p/3601209.html) 165 | 166 | 5、[https://segmentfault.com/a/1190000002470467](https://segmentfault.com/a/1190000002470467) 167 | 168 | 6、[https://github.com/medcl/elasticsearch-analysis-ik/issues/207](https://github.com/medcl/elasticsearch-analysis-ik/issues/207) 169 | 170 | 7、[https://github.com/mongodb-labs/mongo-connector/wiki/Usage%20with%20ElasticSearch](https://github.com/mongodb-labs/mongo-connector/wiki/Usage%20with%20ElasticSearch) -------------------------------------------------------------------------------- /flask/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | import math 4 | import re 5 | import time 6 | import urllib2 7 | import pymongo 8 | from flask import Flask, request, render_template 9 | # setting: 10 | MONGODB_SERVER = 'localhost' 11 | MONGODB_PORT = 27017 12 | MONGODB_DB = 'wooyun' 13 | MONGODB_COLLECTION_BUGS = 'wooyun_list' 14 | MONGODB_COLLECTION_DROPS = 'wooyun_drops' 15 | ROWS_PER_PAGE = 20 16 | ELASTICSEARCH_HOST = 'localhost:9200' 17 | #ELASTICSEARCH CHOOSE 18 | # auto: auto detect elasticsearch ,if opened then use elasticsearch,else use mongodb 19 | # yes: always use elasticsearch 20 | # no: not use elasticsearch 21 | SEARCH_BY_ES = 'auto' 22 | # flask app: 23 | app = Flask(__name__) 24 | # monogodb connection string 25 | connection_string = "mongodb://%s:%d" % (MONGODB_SERVER, MONGODB_PORT) 26 | content = {'by_bugs': 27 | {'mongodb_collection': MONGODB_COLLECTION_BUGS, 'template_html': 'search_bugs.html'}, 28 | 'by_drops': 29 | {'mongodb_collection': MONGODB_COLLECTION_DROPS, 'template_html': 'search_drops.html'}, 30 | } 31 | 32 | 33 | def get_search_regex(keywords, search_by_html): 34 | keywords_regex = {} 35 | kws = [ks for ks in keywords.strip().split(' ') if ks != ''] 36 | field_name = 'html' if search_by_html else 'title' 37 | if len(kws) > 0: 38 | reg_pattern = re.compile('|'.join(kws), re.IGNORECASE) 39 | # keywords_regex[field_name]={'$regex':'|'.join(kws)} 40 | keywords_regex[field_name] = reg_pattern 41 | 42 | return keywords_regex 43 | 44 | 45 | def search_mongodb(keywords, page, content_search_by, search_by_html): 46 | client = pymongo.MongoClient(connection_string) 47 | db = client[MONGODB_DB] 48 | keywords_regex = get_search_regex(keywords, search_by_html) 49 | collection = db[content[content_search_by]['mongodb_collection']] 50 | # get the total count and page: 51 | total_rows = collection.find(keywords_regex).count() 52 | total_page = int( 53 | math.ceil(total_rows / (ROWS_PER_PAGE * 1.0))) 54 | page_info = {'current': page, 'total': total_page, 55 | 'total_rows': total_rows, 'rows': []} 56 | # get the page rows 57 | if total_page > 0 and page <= total_page: 58 | row_start = (page - 1) * ROWS_PER_PAGE 59 | cursors = collection.find(keywords_regex)\ 60 | .sort('datetime', pymongo.DESCENDING).skip(row_start).limit(ROWS_PER_PAGE) 61 | for c in cursors: 62 | c['datetime'] = c['datetime'].strftime('%Y-%m-%d') 63 | if 'url' in c: 64 | urlsep = c['url'].split('//')[1].split('/') 65 | c['url_local'] = '%s-%s.html' % (urlsep[1], urlsep[2]) 66 | page_info['rows'].append(c) 67 | client.close() 68 | # 69 | return page_info 70 | 71 | def search_mongodb_by_es(keywords, page, content_search_by, search_by_html): 72 | from elasticsearch import Elasticsearch 73 | 74 | field_name = 'html' if search_by_html else 'title' 75 | page_info = {'current': page, 'total': 0, 76 | 'total_rows': 0, 'rows': []} 77 | # get the page rows 78 | if page >= 1 : 79 | row_start = (page - 1) * ROWS_PER_PAGE 80 | es = Elasticsearch([ELASTICSEARCH_HOST]) 81 | if keywords.strip() == '': 82 | query_dsl = { 83 | "query": { 84 | "filtered": { 85 | "query": { 86 | "match_all":{ } 87 | } 88 | } 89 | }, 90 | "sort": {"datetime": { "order": "desc" }}, 91 | "from": row_start, 92 | "size": ROWS_PER_PAGE 93 | } 94 | else: 95 | query_dsl = { 96 | "query": { 97 | "filtered": { 98 | "query": { 99 | "match": { 100 | field_name : { 101 | 'query':keywords, 102 | 'operator':'and' 103 | } 104 | } 105 | } 106 | } 107 | }, 108 | "sort": {"datetime": { "order": "desc" }}, 109 | "from": row_start, 110 | "size": ROWS_PER_PAGE 111 | } 112 | res = es.search(body=query_dsl,index=MONGODB_DB,doc_type=content[content_search_by]['mongodb_collection']) 113 | #get total rows and pages 114 | page_info['total_rows'] = res['hits']['total'] 115 | page_info['total'] = int(math.ceil(page_info['total_rows'] / (ROWS_PER_PAGE * 1.0))) 116 | #get everyone row set 117 | for doc in res['hits']['hits']: 118 | c = doc['_source'] 119 | c['datetime'] = time.strftime('%Y-%m-%d',time.strptime(c['datetime'],'%Y-%m-%dT%H:%M:%S')) 120 | if 'url' in c: 121 | urlsep = c['url'].split('//')[1].split('/') 122 | c['url_local'] = '%s-%s.html' % (urlsep[1], urlsep[2]) 123 | page_info['rows'].append(c) 124 | 125 | return page_info 126 | 127 | def check_elastichsearch_open(): 128 | try: 129 | html = urllib2.urlopen('http://%s' %ELASTICSEARCH_HOST).read() 130 | if len(html) > 0: 131 | return True 132 | else: 133 | return False 134 | except: 135 | return False 136 | 137 | def get_wooyun_total_count(): 138 | client = pymongo.MongoClient(connection_string) 139 | db = client[MONGODB_DB] 140 | collection_bugs = db[MONGODB_COLLECTION_BUGS] 141 | total_count_bugs = collection_bugs.find().count() 142 | collection_drops = db[MONGODB_COLLECTION_DROPS] 143 | total_count_drops = collection_drops.find().count() 144 | client.close() 145 | 146 | return (total_count_bugs, total_count_drops) 147 | 148 | 149 | @app.route('/') 150 | def index(): 151 | total_count_bugs, total_count_drops = get_wooyun_total_count() 152 | return render_template('index.html', total_count_bugs=total_count_bugs, total_count_drops=total_count_drops, title=u'乌云公开漏洞、知识库搜索') 153 | 154 | 155 | @app.route('/search', methods=['get']) 156 | def search(): 157 | keywords = request.args.get('keywords') 158 | page = int(request.args.get('page', 1)) 159 | search_by_html = True if 'true' == request.args.get( 160 | 'search_by_html', 'false').lower() else False 161 | content_search_by = request.args.get('content_search_by', 'by_bugs') 162 | if page < 1: 163 | page = 1 164 | #search by elasticsearch or mongo 165 | if SEARCH_BY_ES == 'yes' or ( SEARCH_BY_ES == 'auto' and check_elastichsearch_open() is True ): 166 | page_info = search_mongodb_by_es(keywords, page, content_search_by, search_by_html) 167 | else: 168 | page_info = search_mongodb(keywords, page, content_search_by, search_by_html) 169 | # 170 | return render_template(content[content_search_by]['template_html'], keywords=keywords, page_info=page_info, search_by_html=search_by_html, title=u'搜索结果-乌云公开漏洞、知识库搜索') 171 | 172 | 173 | def main(): 174 | port = 5000 175 | app.run(host='0.0.0.0', port = port, debug=False, threaded=True) 176 | 177 | if __name__ == '__main__': 178 | main() 179 | -------------------------------------------------------------------------------- /tornado/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | import os 4 | import math 5 | import re 6 | import time 7 | import urllib2 8 | import pymongo 9 | import tornado.ioloop 10 | import tornado.web 11 | # setting: 12 | MONGODB_SERVER = 'localhost' 13 | MONGODB_PORT = 27017 14 | MONGODB_DB = 'wooyun' 15 | MONGODB_COLLECTION_BUGS = 'wooyun_list' 16 | MONGODB_COLLECTION_DROPS = 'wooyun_drops' 17 | ROWS_PER_PAGE = 20 18 | ELASTICSEARCH_HOST = 'localhost:9200' 19 | #ELASTICSEARCH CHOOSE 20 | # auto: auto detect elasticsearch ,if opened then use elasticsearch,else use mongodb 21 | # yes: always use elasticsearch 22 | # no: not use elasticsearch 23 | SEARCH_BY_ES = 'auto' 24 | # monogodb connection string 25 | connection_string = "mongodb://%s:%d" % (MONGODB_SERVER, MONGODB_PORT) 26 | content = {'by_bugs': 27 | {'mongodb_collection': MONGODB_COLLECTION_BUGS, 'template_html': 'search_bugs.html'}, 28 | 'by_drops': 29 | {'mongodb_collection': MONGODB_COLLECTION_DROPS, 'template_html': 'search_drops.html'}, 30 | } 31 | 32 | def get_wooyun_total_count(): 33 | client = pymongo.MongoClient(connection_string) 34 | db = client[MONGODB_DB] 35 | collection_bugs = db[MONGODB_COLLECTION_BUGS] 36 | total_count_bugs = collection_bugs.find().count() 37 | collection_drops = db[MONGODB_COLLECTION_DROPS] 38 | total_count_drops = collection_drops.find().count() 39 | client.close() 40 | 41 | return (total_count_bugs, total_count_drops) 42 | 43 | def get_search_regex(keywords, search_by_html): 44 | keywords_regex = {} 45 | kws = [ks for ks in keywords.strip().split(' ') if ks != ''] 46 | field_name = 'html' if search_by_html else 'title' 47 | if len(kws) > 0: 48 | reg_pattern = re.compile('|'.join(kws), re.IGNORECASE) 49 | # keywords_regex[field_name]={'$regex':'|'.join(kws)} 50 | keywords_regex[field_name] = reg_pattern 51 | 52 | return keywords_regex 53 | 54 | 55 | def search_mongodb(keywords, page, content_search_by, search_by_html): 56 | client = pymongo.MongoClient(connection_string) 57 | db = client[MONGODB_DB] 58 | keywords_regex = get_search_regex(keywords, search_by_html) 59 | collection = db[content[content_search_by]['mongodb_collection']] 60 | # get the total count and page: 61 | total_rows = collection.find(keywords_regex).count() 62 | total_page = int( 63 | math.ceil(total_rows / (ROWS_PER_PAGE * 1.0))) 64 | page_info = {'current': page, 'total': total_page, 65 | 'total_rows': total_rows, 'rows': []} 66 | # get the page rows 67 | if total_page > 0 and page <= total_page: 68 | row_start = (page - 1) * ROWS_PER_PAGE 69 | cursors = collection.find(keywords_regex)\ 70 | .sort('datetime', pymongo.DESCENDING).skip(row_start).limit(ROWS_PER_PAGE) 71 | for c in cursors: 72 | c['datetime'] = c['datetime'].strftime('%Y-%m-%d') 73 | if 'url' in c: 74 | urlsep = c['url'].split('//')[1].split('/') 75 | c['url_local'] = '%s-%s.html' % (urlsep[1], urlsep[2]) 76 | page_info['rows'].append(c) 77 | client.close() 78 | # 79 | return page_info 80 | 81 | def search_mongodb_by_es(keywords, page, content_search_by, search_by_html): 82 | from elasticsearch import Elasticsearch 83 | 84 | field_name = 'html' if search_by_html else 'title' 85 | page_info = {'current': page, 'total': 0, 86 | 'total_rows': 0, 'rows': []} 87 | # get the page rows 88 | if page >= 1 : 89 | row_start = (page - 1) * ROWS_PER_PAGE 90 | es = Elasticsearch([ELASTICSEARCH_HOST]) 91 | if keywords.strip() == '': 92 | query_dsl = { 93 | "query": { 94 | "filtered": { 95 | "query": { 96 | "match_all":{ } 97 | } 98 | } 99 | }, 100 | "sort": {"datetime": { "order": "desc" }}, 101 | "from": row_start, 102 | "size": ROWS_PER_PAGE 103 | } 104 | else: 105 | query_dsl = { 106 | "query": { 107 | "filtered": { 108 | "query": { 109 | "match": { 110 | field_name : { 111 | 'query':keywords, 112 | 'operator':'and' 113 | } 114 | } 115 | } 116 | } 117 | }, 118 | "sort": {"datetime": { "order": "desc" }}, 119 | "from": row_start, 120 | "size": ROWS_PER_PAGE 121 | } 122 | res = es.search(body=query_dsl,index=MONGODB_DB,doc_type=content[content_search_by]['mongodb_collection']) 123 | #get total rows and pages 124 | page_info['total_rows'] = res['hits']['total'] 125 | page_info['total'] = int(math.ceil(page_info['total_rows'] / (ROWS_PER_PAGE * 1.0))) 126 | #get everyone row set 127 | for doc in res['hits']['hits']: 128 | c = doc['_source'] 129 | c['datetime'] = time.strftime('%Y-%m-%d',time.strptime(c['datetime'],'%Y-%m-%dT%H:%M:%S')) 130 | if 'url' in c: 131 | urlsep = c['url'].split('//')[1].split('/') 132 | c['url_local'] = '%s-%s.html' % (urlsep[1], urlsep[2]) 133 | page_info['rows'].append(c) 134 | 135 | return page_info 136 | 137 | def check_elastichsearch_open(): 138 | try: 139 | html = urllib2.urlopen('http://%s' % ELASTICSEARCH_HOST).read() 140 | if len(html) > 0: 141 | return True 142 | else: 143 | return False 144 | except: 145 | return False 146 | 147 | 148 | class IndexHandler(tornado.web.RequestHandler): 149 | def get(self): 150 | total_count_bugs, total_count_drops = get_wooyun_total_count() 151 | # 152 | self.render('index.html', total_count_bugs=total_count_bugs, total_count_drops=total_count_drops, title=u'乌云公开漏洞、知识库搜索') 153 | 154 | 155 | class SearchHandler(tornado.web.RequestHandler): 156 | def get(self): 157 | keywords = self.get_argument('keywords') 158 | page = int(self.get_argument('page', 1)) 159 | search_by_html = True if 'true' == self.get_argument( 160 | 'search_by_html', 'false').lower() else False 161 | content_search_by = self.get_argument('content_search_by', 'by_bugs') 162 | if page < 1: 163 | page = 1 164 | #search by elasticsearch or mongo 165 | if SEARCH_BY_ES == 'yes' or ( SEARCH_BY_ES == 'auto' and check_elastichsearch_open() is True ): 166 | page_info = search_mongodb_by_es(keywords, page, content_search_by, search_by_html) 167 | else: 168 | page_info = search_mongodb(keywords, page, content_search_by, search_by_html) 169 | # 170 | self.render(content[content_search_by]['template_html'], keywords=keywords, page_info=page_info, search_by_html=search_by_html, title=u'搜索结果-乌云公开漏洞、知识库搜索') 171 | 172 | 173 | class Application(tornado.web.Application): 174 | def __init__(self): 175 | handlers = [ 176 | (r"/", IndexHandler), 177 | (r"/search", SearchHandler) 178 | ] 179 | settings = dict( 180 | static_path= os.path.join(os.path.dirname(__file__), "../flask/static"), 181 | template_path=os.path.join(os.path.dirname(__file__), "templates"), 182 | ) 183 | tornado.web.Application.__init__(self, handlers, **settings) 184 | 185 | def main(): 186 | port = 5000 187 | application = Application() 188 | application.listen(port) 189 | 190 | print('Listen on http://localhost:{0}'.format(port)) 191 | tornado.ioloop.IOLoop.instance().start() 192 | 193 | if __name__ == "__main__": 194 | main() 195 | -------------------------------------------------------------------------------- /flask/static/bugs/js/jquery.twbsPagination.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery pagination plugin v1.2.5 3 | * http://esimakin.github.io/twbs-pagination/ 4 | * 5 | * Copyright 2014, Eugene Simakin 6 | * Released under Apache 2.0 license 7 | * http://apache.org/licenses/LICENSE-2.0.html 8 | */ 9 | ; 10 | (function ($, window, document, undefined) { 11 | 12 | 'use strict'; 13 | 14 | var old = $.fn.twbsPagination; 15 | 16 | // PROTOTYPE AND CONSTRUCTOR 17 | 18 | var TwbsPagination = function (element, options) { 19 | this.$element = $(element); 20 | this.options = $.extend({}, $.fn.twbsPagination.defaults, options); 21 | 22 | if (this.options.startPage < 1 || this.options.startPage > this.options.totalPages) { 23 | throw new Error('Start page option is incorrect'); 24 | } 25 | 26 | this.options.totalPages = parseInt(this.options.totalPages); 27 | if (isNaN(this.options.totalPages)) { 28 | throw new Error('Total pages option is not correct!'); 29 | } 30 | 31 | this.options.visiblePages = parseInt(this.options.visiblePages); 32 | if (isNaN(this.options.visiblePages)) { 33 | throw new Error('Visible pages option is not correct!'); 34 | } 35 | 36 | if (this.options.totalPages < this.options.visiblePages) { 37 | this.options.visiblePages = this.options.totalPages; 38 | } 39 | 40 | if (this.options.onPageClick instanceof Function) { 41 | this.$element.first().bind('page', this.options.onPageClick); 42 | } 43 | 44 | if (this.options.href) { 45 | var m, regexp = this.options.href.replace(/[-\/\\^$*+?.|[\]]/g, '\\$&'); 46 | regexp = regexp.replace(this.options.hrefVariable, '(\\d+)'); 47 | if ((m = new RegExp(regexp, 'i').exec(window.location.href)) != null) { 48 | this.options.startPage = parseInt(m[1], 10); 49 | } 50 | } 51 | 52 | var tagName = (typeof this.$element.prop === 'function') ? 53 | this.$element.prop('tagName') : this.$element.attr('tagName'); 54 | 55 | if (tagName === 'UL') { 56 | this.$listContainer = this.$element; 57 | } else { 58 | this.$listContainer = $(''); 59 | } 60 | 61 | this.$listContainer.addClass(this.options.paginationClass); 62 | 63 | if (tagName !== 'UL') { 64 | this.$element.append(this.$listContainer); 65 | } 66 | 67 | this.render(this.getPages(this.options.startPage)); 68 | this.setupEvents(); 69 | 70 | return this; 71 | }; 72 | 73 | TwbsPagination.prototype = { 74 | 75 | constructor: TwbsPagination, 76 | 77 | destroy: function () { 78 | this.$element.empty(); 79 | this.$element.removeData('twbs-pagination'); 80 | this.$element.unbind('page'); 81 | return this; 82 | }, 83 | 84 | show: function (page) { 85 | if (page < 1 || page > this.options.totalPages) { 86 | throw new Error('Page is incorrect.'); 87 | } 88 | 89 | this.render(this.getPages(page)); 90 | this.setupEvents(); 91 | 92 | this.$element.trigger('page', page); 93 | return this; 94 | }, 95 | 96 | buildListItems: function (pages) { 97 | var $listItems = $(); 98 | 99 | if (this.options.first) { 100 | $listItems = $listItems.add(this.buildItem('first', 1)); 101 | } 102 | 103 | if (this.options.prev) { 104 | var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages : 1; 105 | $listItems = $listItems.add(this.buildItem('prev', prev)); 106 | } 107 | 108 | for (var i = 0; i < pages.numeric.length; i++) { 109 | $listItems = $listItems.add(this.buildItem('page', pages.numeric[i])); 110 | } 111 | 112 | if (this.options.next) { 113 | var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.loop ? 1 : this.options.totalPages; 114 | $listItems = $listItems.add(this.buildItem('next', next)); 115 | } 116 | 117 | if (this.options.last) { 118 | $listItems = $listItems.add(this.buildItem('last', this.options.totalPages)); 119 | } 120 | 121 | return $listItems; 122 | }, 123 | 124 | buildItem: function (type, page) { 125 | var itemContainer = $('
        • '), 126 | itemContent = $(''), 127 | itemText = null; 128 | 129 | switch (type) { 130 | case 'page': 131 | itemText = page; 132 | itemContainer.addClass(this.options.pageClass); 133 | break; 134 | case 'first': 135 | itemText = this.options.first; 136 | itemContainer.addClass(this.options.firstClass); 137 | break; 138 | case 'prev': 139 | itemText = this.options.prev; 140 | itemContainer.addClass(this.options.prevClass); 141 | break; 142 | case 'next': 143 | itemText = this.options.next; 144 | itemContainer.addClass(this.options.nextClass); 145 | break; 146 | case 'last': 147 | itemText = this.options.last; 148 | itemContainer.addClass(this.options.lastClass); 149 | break; 150 | default: 151 | break; 152 | } 153 | 154 | itemContainer.data('page', page); 155 | itemContainer.data('page-type', type); 156 | itemContainer.append(itemContent.attr('href', this.makeHref(page)).html(itemText)); 157 | return itemContainer; 158 | }, 159 | 160 | getPages: function (currentPage) { 161 | var pages = []; 162 | 163 | var half = Math.floor(this.options.visiblePages / 2); 164 | var start = currentPage - half + 1 - this.options.visiblePages % 2; 165 | var end = currentPage + half; 166 | 167 | // handle boundary case 168 | if (start <= 0) { 169 | start = 1; 170 | end = this.options.visiblePages; 171 | } 172 | if (end > this.options.totalPages) { 173 | start = this.options.totalPages - this.options.visiblePages + 1; 174 | end = this.options.totalPages; 175 | } 176 | 177 | var itPage = start; 178 | while (itPage <= end) { 179 | pages.push(itPage); 180 | itPage++; 181 | } 182 | 183 | return {"currentPage": currentPage, "numeric": pages}; 184 | }, 185 | 186 | render: function (pages) { 187 | this.$listContainer.children().remove(); 188 | this.$listContainer.append(this.buildListItems(pages)); 189 | 190 | var children = this.$listContainer.children(); 191 | children.filter(function () { 192 | return $(this).data('page') === pages.currentPage && $(this).data('page-type') === 'page'; 193 | }).addClass(this.options.activeClass); 194 | 195 | children.filter(function () { 196 | return $(this).data('page-type') === 'first'; 197 | }).toggleClass(this.options.disabledClass, pages.currentPage === 1); 198 | 199 | children.filter(function () { 200 | return $(this).data('page-type') === 'last'; 201 | }).toggleClass(this.options.disabledClass, pages.currentPage === this.options.totalPages); 202 | 203 | children.filter(function () { 204 | return $(this).data('page-type') === 'prev'; 205 | }).toggleClass(this.options.disabledClass, !this.options.loop && pages.currentPage === 1); 206 | 207 | children.filter(function () { 208 | return $(this).data('page-type') === 'next'; 209 | }).toggleClass(this.options.disabledClass, !this.options.loop && pages.currentPage === this.options.totalPages); 210 | }, 211 | 212 | setupEvents: function () { 213 | var base = this; 214 | this.$listContainer.find('li').each(function () { 215 | var $this = $(this); 216 | $this.off(); 217 | if ($this.hasClass(base.options.disabledClass) || $this.hasClass(base.options.activeClass)) { 218 | $this.click(function (evt) { 219 | evt.preventDefault(); 220 | }); 221 | return; 222 | } 223 | $this.click(function (evt) { 224 | // Prevent click event if href is not set. 225 | !base.options.href && evt.preventDefault(); 226 | base.show(parseInt($this.data('page'), 10)); 227 | }); 228 | }); 229 | }, 230 | 231 | makeHref: function (c) { 232 | return this.options.href ? this.options.href.replace(this.options.hrefVariable, c) : "#"; 233 | } 234 | 235 | }; 236 | 237 | // PLUGIN DEFINITION 238 | 239 | $.fn.twbsPagination = function (option) { 240 | var args = Array.prototype.slice.call(arguments, 1); 241 | var methodReturn; 242 | 243 | var $this = $(this); 244 | var data = $this.data('twbs-pagination'); 245 | var options = typeof option === 'object' && option; 246 | 247 | if (!data) $this.data('twbs-pagination', (data = new TwbsPagination(this, options) )); 248 | if (typeof option === 'string') methodReturn = data[ option ].apply(data, args); 249 | 250 | return ( methodReturn === undefined ) ? $this : methodReturn; 251 | }; 252 | 253 | $.fn.twbsPagination.defaults = { 254 | totalPages: 0, 255 | startPage: 1, 256 | visiblePages: 5, 257 | href: false, 258 | hrefVariable: '{{number}}', 259 | first: 'First', 260 | prev: 'Previous', 261 | next: 'Next', 262 | last: 'Last', 263 | loop: false, 264 | onPageClick: null, 265 | paginationClass: 'pagination', 266 | nextClass: 'next', 267 | prevClass: 'prev', 268 | lastClass: 'last', 269 | firstClass: 'first', 270 | pageClass: 'page', 271 | activeClass: 'active', 272 | disabledClass: 'disabled' 273 | }; 274 | 275 | $.fn.twbsPagination.Constructor = TwbsPagination; 276 | 277 | $.fn.twbsPagination.noConflict = function () { 278 | $.fn.twbsPagination = old; 279 | return this; 280 | }; 281 | 282 | })(jQuery, window, document); 283 | -------------------------------------------------------------------------------- /flask/static/bugs/css/style.css: -------------------------------------------------------------------------------- 1 | *{margin:0;padding:0;}li{list-style:none;}img{border:none;}a{color:#002E8C;text-decoration:none;}a:hover{color:#F60;text-decoration:underline;}a.btn{border:#999 1px solid;background:#DDD;padding:3px 5px}table{border-spacing:0;border-collapse:collapse;}textarea{font-size:13px;}.fred{color:red;}.fbold{font-weight:bold;}.clear{clear:both;height:0;overflow:hidden}html,body{font:12px Verdana,"Microsoft YaHei",Helvetica,Arial,Sans-Serif;width:100%;height:100%;text-align:center;background:#E0E4E7 url("../images/bg.png") repeat-x top;}.banner,.login,.nav,.bread,.content,.support,#footer{width:1000px;margin:0 auto;text-align:left;background:#FFF;}.banner{height:100px;background:url("../images/topBg.png") repeat-x;position:relative;overflow:normal;z-index:99;clear:both}.banner h1{font-size:40px;height:100px;line-height:100px;text-indent:24px;}.logo{float:left;width:450px}.logo h1{float:left}.logo .weibo{float:left;margin-top:45px;padding-left:9px;height:24px;width:110px;line-height:24px;}.login{width:550px;height:22px;line-height:22px;text-align:right;float:right;}.login a.reg{margin-right:12px;}.remind{width:150px;float:right;background:#f0f0f0;border:#999 1px solid;padding:1px 0;margin:15px 13px 0 0;text-align:center}.nav{color:#B6B6B6;height:40px;line-height:40px;*line-height:42px;background:url("../images/navBg.png") repeat-x;overflow:hidden;position:relative;}.nav ul li{float:left;}.nav ul li a{float:left;color:#B6B6B6;text-decoration:none;background:url("../images/liBg.gif") no-repeat right;padding:0 13px 0 12px;}.nav ul li a:hover{color:#FFF;}.nav p{float:right;height:24px;line-height:24px;text-align:right;padding:8px 12px;}.nav p input{float:right;height:22px;line-height:22px;border:1px solid #999;}.nav p a{float:right;display:block;width:29px;height:24px;margin-left:2px;}.bread{height:24px;line-height:24px;text-indent:12px;}.content{padding-top:10px;position:relative;z-index:2;}.content h3{font-size:14px;font-weight:normal;width:950px;text-indent:10px;margin:0 auto;padding-top:15px;word-break:break-all;word-wrap:break-word;}.content h3 a{font-weight:bold;}.content p.caption{width:936px;line-height:22px;text-indent:2em;border:1px solid #BBB;background:#D7D6DC;margin:10px auto 0;padding:6px;}.content p.corpCaption{display:none;}.content hr{color:#BBB;width:950px;height:0;border:none;border-top:1px solid #BBB;margin:10px auto 0;}.content h2{font-size:26px;width:950px;line-height:2em;margin:0 auto;}.content p.detail{font-size:13px;width:870px;line-height:25px;margin:0 auto;padding:5px 12px;word-break:break-all;word-wrap:break-word;}.content h5{font-size:14px;text-align:center;margin:10px auto 0;}.content h5 a{display:inline-block;height:32px;line-height:32px;text-decoration:none;border:1px solid #999;background:#DDD;padding:0 6px;margin:0 6px;}.corp{display:none;}.success{width:636px;height:122px;line-height:22px;text-align:center;border:1px solid #999;background:#DDD;margin:10px auto 0;padding:84px 6px 6px;}.classTable{width:950px;line-height:22px;border:none;margin:10px auto 0;}.classTable tbody tr th,.classTable tbody tr td{padding:0 6px;}.classTable tbody tr th{text-align:right;}.listTable{width:950px;line-height:22px;border:2px solid #FFF;margin:10px auto 0;}.listTable thead tr{background:#D7D6DC;}.listTable thead tr th{font-weight:normal;text-align:center;}.listTable tbody tr:hover{background-color:#ebebeb;}.listTable tr th,.listTable tr td{border:2px solid #FFF;padding:0 6px;white-space:nowrap;}.listTable tbody tr th{font-weight:normal;text-align:center;}.formTable{font-size:14px;width:950px;line-height:24px;border:none;margin:10px auto 0;}.formTable tbody tr th *,.formTable tbody tr td *{vertical-align:middle;}.formTable tbody tr th,.formTable tbody tr td{padding:3px 6px;white-space:nowrap;}.formTable tbody tr th{font-weight:normal;text-align:right;}.page{width:946px;text-align:right;margin:10px auto 0;padding:0 2px;}.page a{margin:0 5px;}.page a.current{font-weight:bold;text-decoration:underline;}.copyright{height:60px;line-height:60px;margin-left:30px;}.infoTab{width:750px;height:31px;border-bottom:1px solid #999;background:#DDD;margin:0 auto;position:relative;}.infoTab ul{width:726px;height:32px;padding:0 12px;position:absolute;bottom:-1px;right:0;}.infoTab ul li{float:right;height:24px;margin:7px 0 0 6px;padding:0 6px;}.infoTab ul li.current{border:1px solid #999;border-bottom:0;background:#FFF;}.infoTab ul li a{display:block;height:18px;line-height:18px;margin-top:3px;padding:0 6px 1px;*padding:1px 6px 0;*width:50px}.infoTab ul li a:hover{color:#FFF;text-decoration:none;background:#F60;}.infoTab ul li.current a:hover{color:#000;background:#FFF;cursor:default;}.infoContent{display:none;width:726px;margin:10px auto 0;padding:0 12px 10px;}.infoContent.block{display:block;}.infoContent .formTable{width:100%;}.infoContent .listTable{width:700px;}#list .listTable{margin-top:15px;}#userUpdate .content h2{width:750px;}#corpList .listTable{border:none;background:none;margin-top:15px;}#corpList .listTable tr th,#corpList .listTable tr td{border:none;padding:0 6px;white-space:nowrap;}#friends .classTable{width:900px;}#bugDetail .content h3{padding-top:5px;}#bugDetail .content h3.detailTitle{border-left:5px solid #999;margin-top:15px;}.remark{color:blue;display:none;font-size:12px;line-height:24px;}.error{color:red;font-size:12px;line-height:24px;margin-left:24px;}pre,code{font-family:Lucida Console,Courier New,Courier,mono,monospace;color:#333;background-color:#f8f8f8;}pre{border:1px #ccc solid;line-height:18px;overflow:auto;word-wrap:break-word;margin:0 auto;padding:4px 8px;width:852px;}.mainLeft{float:left;width:179px;border-right:1px dashed #333;padding:40px 10px 10px;}.mainLeft ul li{line-height:24px;list-style:square inside;}.mainRight{float:right;width:800px;}.infoLeftTab{width:947px;height:31px;border-bottom:1px solid #999;background:#DDD;margin:0 auto;margin-top:10px;position:relative;}.infoLeftTab ul{width:920px;height:32px;padding:0 12px;position:absolute;bottom:-1px;right:0;}.infoLeftTab ul li{float:left;height:24px;margin:7px 0 0 12px;padding:0 6px;}.infoLeftTab ul li.current{border:1px solid #999;border-bottom:0;background:#FFF;}.infoLeftTab ul li a{display:block;height:18px;line-height:18px;margin-top:3px;padding:0 6px 1px;*padding:1px 6px 0;*width:50px}.infoLeftTab ul li a:hover{color:#FFF;text-decoration:none;background:#F60;}.infoLeftTab ul li.current a:hover{color:#000;background:#FFF;cursor:default;}ul.corplist{margin:0;padding:0}ul.corplist li{float:left}ul.corplist li.current{border-bottom:#000 1px solid}span.small{margin-left:15px;font-size:12px;font-weight:normal}div.comment{margin:0 auto 15px auto;width:870px;text-align:left}dl.commentlist{width:650px}dl.commentlist dt{line-height:22px}dl.commentlist dt span.user{margin-left:15px}dl.commentlist dt span.user label{color:#555555;font-size:12px}dl.commentlist dd{line-height:25px;font-size:14px;padding:5px;word-wrap:break-word;border-bottom:1px dashed #ccc}.content .catrss{background:url("../images/catrss.png") no-repeat left;width:16px;height:11px;display:inline-block;margin-bottom:-1px;margin-left:5px;}.content .corprss{background:url("../images/corprss.png") no-repeat left;width:16px;height:16px;display:inline-block;margin-bottom:-4px;margin-left:5px;}.catrss:hover,.corprss:hover{text-decoration:none;}div.sms_content{width:600px;padding:10px 0 30px 0;word-wrap:break-word;word-break:break-all;table-layout:fixed;clear:both;white-space:-moz-pre-wrap;white-space:-hp-pre-wrap;white-space:-o-pre-wrap;white-space:-pre-wrap;white-space:pre;white-space:pre-wrap;white-space:pre-line}span.sms_time{font-size:12px;float:right;padding-right:20px}.fsize_13{font-size:13px}.csetip{margin:0 15px;font-size:14px}#searchbox{background:url("../images/search.png") no-repeat right;display:inline;float:right;height:24px;line-height:24px;padding:8px 0;margin:0 12px 0 0;}#search_input{height:22px;line-height:22px;width:151px;border:1px solid #999;}#search_button{background:none repeat scroll 0 0 transparent;border:medium none;cursor:pointer;width:29px;height:24px;text-indent:-1000px;}#share{height:24px;line-height:24px;font-size:14px;}.jobshare{margin:10px 0 0 65px;}.new{display:inline-block;background:url(../images/new.png) no-repeat 52px 3px;}.credit{height:16px;border:none;margin:0 0 -3px 5px;}.content .toctit{margin-bottom:5px;background:#eee;border-bottom:1px solid #999;padding:5px 0;margin-top:15px;}.content .toc{font-size:13px;line-height:25px;margin:0 auto;width:900px;margin-left:80px;}.content .toc li{list-style-type:decimal;}#help p,#about p,#lawer p{text-indent:2em;font-size:13px;line-height:25px;margin:0 auto;width:900px;word-wrap:break-word;}span.tag{text-align:center;margin-right:3px;padding:2px 5px;background:#E1E1E1}span.zonetag{font-size:12px;text-align:center;margin-right:4px;padding:3px 6px;background:#E1E1E1;border:#CCC 1px solid}.hot{width:932px;height:160px;border:1px solid #DDD;margin:0 auto;padding:0 8px 8px;overflow:hidden;position:relative;}.scrollContent{width:932px;position:absolute;top:0;left:8px;}.hotContent{width:932px;padding-bottom:8px;overflow:hidden;}.hot .listTable{float:left;width:522px;display:block;}.zoneIntro{float:right;width:376px;height:142px;line-height:1.5em;background:#EFEFEF;margin-top:6px;padding:6px 12px;}.zoneIntro h1{line-height:1.5em;font-size:18px;margin-bottom:5px;}.zoneIntro p{line-height:1.8em;text-indent:2em;}.zoneList{width:950px;height:22px;line-height:22px;margin:0 auto;padding-bottom:10px;}.zoneList li{float:left;display:block;margin-right:3px;}.zoneList li a{float:left;border:1px solid #DDD;background:#EEE;padding:0 6px;}.zoneList li a:hover{text-decoration:none;}.zoneList li.current a{color:#FFF;text-decoration:none;background:#F60;}.zoneList li.current a:hover{text-decoration:none;}.support{width:950px;border-top:1px solid #DDD;margin-top:12px;}.supportTable{border:none;margin-top:10px;}.supportTable tr th{font-size:15px;font-weight:bold;}.supportTable tr th,.supportTable tr td{padding:3px 6px;}.bugImg{min-width:200px;max-width:870px;width:auto;_width:600px;}.replys{margin:0 15px 15px 65px;}.replys .topic{width:100%;}.replylist .reply{border-bottom:1px solid #CCC;overflow:hidden;padding:15px 15px 0 15px;}.reply .description p{font-size:14px;margin-top:10px;}.replylist li{width:700px;}.fixed,.clear{clear:both;}.clearfix:after{content:".";display:block;clear:both;visibility:hidden;line-height:0;height:0;}.clearfix{display:inline-block;}.author-info .addtime,.replylist .addtime{font:12px Georgia,Verdana,Microsoft YaHei,Helvetica,Arial,Sans-Serif;color:#333;}.reply .reply-info{color:#999;}.reply .replylist-act{height:14px;float:right;padding-bottom:8px;}.reply .replylist-act .replyBtn{display:none;}.reply .replylist-act span.floor{display:block;float:right;margin-left:10px;color:#999}.paper-info h3{line-height:24px;padding:0;}.paper-toc{line-height:24px;margin-left:100px;}.paper-toc li{line-height:24px;}#paper{font-size:14px;}#paper .toc li{list-style:none;}#paper p{text-indent:2em;font-size:14px;line-height:25px;margin:0 auto;width:900px;word-wrap:break-word;}div.toc-sidebar{border:1px solid #ccc;background:none repeat scroll 0 0 #f8f8f8;float:right;position:fixed;top:4em;right:1em;z-index:1;border-radius:4px 4px 4px 4px;opacity:0.2;padding:3px;}div.toc-sidebar:hover{box-shadow:0 0 8px #666;opacity:1;}div.toc-sidebar ul{margin:0;padding:0 0 0 1em;}div.toc-sidebar>ul{padding:0;}div.toc-sidebar li{list-style-type:none;line-height:18px;overflow:hidden;margin:0;padding:0 0 0 18px;}.good_replys{background-color:#FFF;border:1px solid #999;width:730px;bottom:-100px;}.good_replys_title{font-size:20px;color:#FF6600;font-weight:bold;background:#EEEEEE;border-bottom:1px solid #999999;padding:5px 10px;}.good_replys_list{padding:0;}.good_replys_list .replylist{margin-bottom:-2px;}.content h5.rating{height:45px;margin:10px auto 0;width:320px;}.myrating{width:140px;}.myrating span{display:inline-block;width:21px;height:21px;background:url(/images/star-empty.png) center no-repeat;cursor:pointer}.myrating span.on{background:url(/images/star-new.png) center no-repeat}.myrating span.hover{background:url(/images/star-new-hover.png) center no-repeat}.ratingText,.myrating{float:left;}#ratingShow{width:350px;text-align:left;font-weight:normal;position:absolute;padding:0 0 0 18px}.ratingShow{text-align:left;font-weight:normal;position:absolute;padding:0 15px;background:#fff;text-indent:0}.likenums{margin-left:10px;color:red;}.likenum{position:relative;display:inline-block;top:0;height:14px;width:90px;vertical-align:-2px;_height:15px;}.likebox,.likepre,.likesuf{display:inline-block;height:16px;overflow-y:hidden;background:url(/images/likeicon.png);}.likebox{float:right;background-position:0 -19px;background-repeat:repeat-x;left:10px;}.likepre,.likesuf,.liketext{overflow:hidden;float:left;cursor:default;}.likepre{cursor:pointer;}.liketext{color:#2979A1;line-height:16px;font-size:11px;width:30px;text-align:center;}.liketext_min{width:35px;}.liketext_max{width:55px;}.likepre{width:20px;}.likesuf{width:3px;background-position:-32px 0;}#rating_wrap{font-size:10px;line-height:21px;height:110px;margin:3px auto 0;width:250px;}.starstop{float:left;background:url(/images/all_star.png);display:block;width:105px;height:21px;margin:0;}.stargray{float:left;background:url(/images/star_gray.png);display:block;width:105px;height:18px;margin:0;}.sub_ins .starstop{float:none;width:105px;display:inline;position:absolute;}.stars{display:inline-block;background:url(/images/all_star.png);width:105px;height:21px;margin:1px 0 0 7px;}.stars4{background-position:left 84px;}.stars3{background-position:left 63px;}.stars2{background-position:left 42px;}.stars1{background-position:left 21px;}.power{height:15px;float:left;background:#f5cbad;margin:3px 3px;}.itemcount{font-size:11px;}.btn-fav{border:1px solid #EDCEBA;border-radius:3px 3px 3px 3px;display:inline-block;height:19px;line-height:19px;margin-left:4px;overflow:hidden;padding:0 8px 0 20px;vertical-align:middle;}a.btn-fav:link,a.btn-fav:visited{background-color:#FFF6EE;border-color:#F2ECE7;color:#99776B;font-weight:normal}a.btn-fav:hover,a.btn-fav:active{background-color:#FFF0E2;border-color:#EDCEBA;color:#99776B;font-weight:normal}.fav-add,.fav-add:link,.fav-add:hover{background:url("../images/collect_like.png") no-repeat scroll 8px 3px transparent;}.fav-cancel,.fav-cancel:link,.fav-cancel:hover{background:url("../images/collect_like.png") no-repeat scroll 8px -17px transparent;}.fav-num{color:#666666;display:inline-block;}.fleft{float:left;}.fright{float:right;}#footer{height:60px;line-height:60px;padding-top:15px}.other{margin-right:30px;}.winlist{padding-left:15px}.winlist ul li{font-size:14px;line-height:25px}.winlist ul li span.date{margin-right:10px}.ewmthumb{position:relative;z-index:0;}.ewmthumb:hover{background-color:transparent;z-index:50;}.ewmthumb span{position:absolute;background-color:lightyellow;padding:1px;left:-1000px;border:0px dashed gray;visibility:hidden;color:black;text-decoration:none;}.ewmthumb span img{position:absolute;border-width:0;padding:2px;}.ewmthumb:hover span{visibility:visible;top:17px;left:-90px;}.wxewm{float:right;height:24px;line-height:24px;margin-top:45px;padding-left:1px;width:20px;}.go-to-wrapper{font-size:14px;width:1120px;height:98px;background:transparent;margin-left:-560px;position:fixed;left:50%;bottom:96px;z-index:1;}@media (max-width: 1119px) {.go-to-wrapper{width:auto;margin-left:0;padding-right:12px;left:auto;right:0;z-index:9999;}}@media (max-width: 767px) {.go-to-wrapper{display:none;}}.go-to{float:right;width:48px;}.go-to li{display:none;width:36px;height:36px;text-indent:-9999em;background:#a1acb5 url("../images/go-to.png") no-repeat;overflow:hidden;margin-top:2px;padding:6px;}.go-to li:hover{text-indent:0;background-image:none;}#go-to-comment{background-position:center top;margin-top:0;}#back-to-top{background-position:center -48px;}#bugDetail #go-to-comment{display:block;background-position:center top;}#go-to-feedback{display:block;background-position:center -96px;}.go-to li a{color:#fff;line-height:18px;}.go-to li a:hover{text-decoration:none;}.month-wrapper{width:948px;height:22px;overflow:hidden;margin:12px auto -22px;position:relative;z-index:1;}.month-list{width:9999999px;height:22px;line-height:22px;position:absolute;top:0;left:0;}.month-list li{color:#002E8C;float:left;width:118.5px;text-align:left;}.chart-list{width:926px;height:38px;background:url("../images/charts-bg.png") no-repeat 22px bottom;margin:0 auto;padding-left:22px;position:relative;z-index:2;}.chart-list li{float:left;width:121px;height:38px;margin-left:-2px;cursor:pointer;position:relative;}.chart-list li:first-child{margin-left:0;}.chart-list li.active{background:url("../images/month-bg.png") no-repeat left bottom;z-index:2;}.golden{color:#ff8400;font-weight:bold;text-shadow:0 0 3px rgba(241,184,0,1);}.fieldset{width:870px;border:1px solid #ccc;margin:0 auto;}.fieldset legend{font-weight:bold;padding:0 12px;margin-left:12px;}.fieldset pre{width:846px;border-width:0;overflow:hidden;padding:12px 12px;}.fieldset .fieldset{width:846px;}.fieldset .fieldset pre{width:822px;}.text-ellipsis{display:inline-block;width:678px;overflow:hidden;white-space:nowrap;-o-text-overflow:ellipsis;text-overflow:ellipsis;}.table-cell-sm{width:538px;}.table-cell-xs{width:413px;}div#__cz_push_c_object_box__,div#ooDiv,a[id^="__czUnion_a"]{display:none!important;z-index:-1!important;} -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.5 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /flask/static/bugs/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.5 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | .btn-default, 7 | .btn-primary, 8 | .btn-success, 9 | .btn-info, 10 | .btn-warning, 11 | .btn-danger { 12 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 13 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 14 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | } 16 | .btn-default:active, 17 | .btn-primary:active, 18 | .btn-success:active, 19 | .btn-info:active, 20 | .btn-warning:active, 21 | .btn-danger:active, 22 | .btn-default.active, 23 | .btn-primary.active, 24 | .btn-success.active, 25 | .btn-info.active, 26 | .btn-warning.active, 27 | .btn-danger.active { 28 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 29 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | } 31 | .btn-default.disabled, 32 | .btn-primary.disabled, 33 | .btn-success.disabled, 34 | .btn-info.disabled, 35 | .btn-warning.disabled, 36 | .btn-danger.disabled, 37 | .btn-default[disabled], 38 | .btn-primary[disabled], 39 | .btn-success[disabled], 40 | .btn-info[disabled], 41 | .btn-warning[disabled], 42 | .btn-danger[disabled], 43 | fieldset[disabled] .btn-default, 44 | fieldset[disabled] .btn-primary, 45 | fieldset[disabled] .btn-success, 46 | fieldset[disabled] .btn-info, 47 | fieldset[disabled] .btn-warning, 48 | fieldset[disabled] .btn-danger { 49 | -webkit-box-shadow: none; 50 | box-shadow: none; 51 | } 52 | .btn-default .badge, 53 | .btn-primary .badge, 54 | .btn-success .badge, 55 | .btn-info .badge, 56 | .btn-warning .badge, 57 | .btn-danger .badge { 58 | text-shadow: none; 59 | } 60 | .btn:active, 61 | .btn.active { 62 | background-image: none; 63 | } 64 | .btn-default { 65 | text-shadow: 0 1px 0 #fff; 66 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 67 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 68 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 69 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 70 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 71 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 72 | background-repeat: repeat-x; 73 | border-color: #dbdbdb; 74 | border-color: #ccc; 75 | } 76 | .btn-default:hover, 77 | .btn-default:focus { 78 | background-color: #e0e0e0; 79 | background-position: 0 -15px; 80 | } 81 | .btn-default:active, 82 | .btn-default.active { 83 | background-color: #e0e0e0; 84 | border-color: #dbdbdb; 85 | } 86 | .btn-default.disabled, 87 | .btn-default[disabled], 88 | fieldset[disabled] .btn-default, 89 | .btn-default.disabled:hover, 90 | .btn-default[disabled]:hover, 91 | fieldset[disabled] .btn-default:hover, 92 | .btn-default.disabled:focus, 93 | .btn-default[disabled]:focus, 94 | fieldset[disabled] .btn-default:focus, 95 | .btn-default.disabled.focus, 96 | .btn-default[disabled].focus, 97 | fieldset[disabled] .btn-default.focus, 98 | .btn-default.disabled:active, 99 | .btn-default[disabled]:active, 100 | fieldset[disabled] .btn-default:active, 101 | .btn-default.disabled.active, 102 | .btn-default[disabled].active, 103 | fieldset[disabled] .btn-default.active { 104 | background-color: #e0e0e0; 105 | background-image: none; 106 | } 107 | .btn-primary { 108 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); 109 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); 110 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); 111 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); 112 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); 113 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 114 | background-repeat: repeat-x; 115 | border-color: #245580; 116 | } 117 | .btn-primary:hover, 118 | .btn-primary:focus { 119 | background-color: #265a88; 120 | background-position: 0 -15px; 121 | } 122 | .btn-primary:active, 123 | .btn-primary.active { 124 | background-color: #265a88; 125 | border-color: #245580; 126 | } 127 | .btn-primary.disabled, 128 | .btn-primary[disabled], 129 | fieldset[disabled] .btn-primary, 130 | .btn-primary.disabled:hover, 131 | .btn-primary[disabled]:hover, 132 | fieldset[disabled] .btn-primary:hover, 133 | .btn-primary.disabled:focus, 134 | .btn-primary[disabled]:focus, 135 | fieldset[disabled] .btn-primary:focus, 136 | .btn-primary.disabled.focus, 137 | .btn-primary[disabled].focus, 138 | fieldset[disabled] .btn-primary.focus, 139 | .btn-primary.disabled:active, 140 | .btn-primary[disabled]:active, 141 | fieldset[disabled] .btn-primary:active, 142 | .btn-primary.disabled.active, 143 | .btn-primary[disabled].active, 144 | fieldset[disabled] .btn-primary.active { 145 | background-color: #265a88; 146 | background-image: none; 147 | } 148 | .btn-success { 149 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 150 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 151 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 152 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 153 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 154 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 155 | background-repeat: repeat-x; 156 | border-color: #3e8f3e; 157 | } 158 | .btn-success:hover, 159 | .btn-success:focus { 160 | background-color: #419641; 161 | background-position: 0 -15px; 162 | } 163 | .btn-success:active, 164 | .btn-success.active { 165 | background-color: #419641; 166 | border-color: #3e8f3e; 167 | } 168 | .btn-success.disabled, 169 | .btn-success[disabled], 170 | fieldset[disabled] .btn-success, 171 | .btn-success.disabled:hover, 172 | .btn-success[disabled]:hover, 173 | fieldset[disabled] .btn-success:hover, 174 | .btn-success.disabled:focus, 175 | .btn-success[disabled]:focus, 176 | fieldset[disabled] .btn-success:focus, 177 | .btn-success.disabled.focus, 178 | .btn-success[disabled].focus, 179 | fieldset[disabled] .btn-success.focus, 180 | .btn-success.disabled:active, 181 | .btn-success[disabled]:active, 182 | fieldset[disabled] .btn-success:active, 183 | .btn-success.disabled.active, 184 | .btn-success[disabled].active, 185 | fieldset[disabled] .btn-success.active { 186 | background-color: #419641; 187 | background-image: none; 188 | } 189 | .btn-info { 190 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 191 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 192 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 193 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 194 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 195 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 196 | background-repeat: repeat-x; 197 | border-color: #28a4c9; 198 | } 199 | .btn-info:hover, 200 | .btn-info:focus { 201 | background-color: #2aabd2; 202 | background-position: 0 -15px; 203 | } 204 | .btn-info:active, 205 | .btn-info.active { 206 | background-color: #2aabd2; 207 | border-color: #28a4c9; 208 | } 209 | .btn-info.disabled, 210 | .btn-info[disabled], 211 | fieldset[disabled] .btn-info, 212 | .btn-info.disabled:hover, 213 | .btn-info[disabled]:hover, 214 | fieldset[disabled] .btn-info:hover, 215 | .btn-info.disabled:focus, 216 | .btn-info[disabled]:focus, 217 | fieldset[disabled] .btn-info:focus, 218 | .btn-info.disabled.focus, 219 | .btn-info[disabled].focus, 220 | fieldset[disabled] .btn-info.focus, 221 | .btn-info.disabled:active, 222 | .btn-info[disabled]:active, 223 | fieldset[disabled] .btn-info:active, 224 | .btn-info.disabled.active, 225 | .btn-info[disabled].active, 226 | fieldset[disabled] .btn-info.active { 227 | background-color: #2aabd2; 228 | background-image: none; 229 | } 230 | .btn-warning { 231 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 232 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 233 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 234 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 235 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 236 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 237 | background-repeat: repeat-x; 238 | border-color: #e38d13; 239 | } 240 | .btn-warning:hover, 241 | .btn-warning:focus { 242 | background-color: #eb9316; 243 | background-position: 0 -15px; 244 | } 245 | .btn-warning:active, 246 | .btn-warning.active { 247 | background-color: #eb9316; 248 | border-color: #e38d13; 249 | } 250 | .btn-warning.disabled, 251 | .btn-warning[disabled], 252 | fieldset[disabled] .btn-warning, 253 | .btn-warning.disabled:hover, 254 | .btn-warning[disabled]:hover, 255 | fieldset[disabled] .btn-warning:hover, 256 | .btn-warning.disabled:focus, 257 | .btn-warning[disabled]:focus, 258 | fieldset[disabled] .btn-warning:focus, 259 | .btn-warning.disabled.focus, 260 | .btn-warning[disabled].focus, 261 | fieldset[disabled] .btn-warning.focus, 262 | .btn-warning.disabled:active, 263 | .btn-warning[disabled]:active, 264 | fieldset[disabled] .btn-warning:active, 265 | .btn-warning.disabled.active, 266 | .btn-warning[disabled].active, 267 | fieldset[disabled] .btn-warning.active { 268 | background-color: #eb9316; 269 | background-image: none; 270 | } 271 | .btn-danger { 272 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 273 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 274 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 275 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 276 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 277 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 278 | background-repeat: repeat-x; 279 | border-color: #b92c28; 280 | } 281 | .btn-danger:hover, 282 | .btn-danger:focus { 283 | background-color: #c12e2a; 284 | background-position: 0 -15px; 285 | } 286 | .btn-danger:active, 287 | .btn-danger.active { 288 | background-color: #c12e2a; 289 | border-color: #b92c28; 290 | } 291 | .btn-danger.disabled, 292 | .btn-danger[disabled], 293 | fieldset[disabled] .btn-danger, 294 | .btn-danger.disabled:hover, 295 | .btn-danger[disabled]:hover, 296 | fieldset[disabled] .btn-danger:hover, 297 | .btn-danger.disabled:focus, 298 | .btn-danger[disabled]:focus, 299 | fieldset[disabled] .btn-danger:focus, 300 | .btn-danger.disabled.focus, 301 | .btn-danger[disabled].focus, 302 | fieldset[disabled] .btn-danger.focus, 303 | .btn-danger.disabled:active, 304 | .btn-danger[disabled]:active, 305 | fieldset[disabled] .btn-danger:active, 306 | .btn-danger.disabled.active, 307 | .btn-danger[disabled].active, 308 | fieldset[disabled] .btn-danger.active { 309 | background-color: #c12e2a; 310 | background-image: none; 311 | } 312 | .thumbnail, 313 | .img-thumbnail { 314 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 315 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 316 | } 317 | .dropdown-menu > li > a:hover, 318 | .dropdown-menu > li > a:focus { 319 | background-color: #e8e8e8; 320 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 321 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 322 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 323 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 324 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 325 | background-repeat: repeat-x; 326 | } 327 | .dropdown-menu > .active > a, 328 | .dropdown-menu > .active > a:hover, 329 | .dropdown-menu > .active > a:focus { 330 | background-color: #2e6da4; 331 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 332 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 333 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 334 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 336 | background-repeat: repeat-x; 337 | } 338 | .navbar-default { 339 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 340 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 342 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 344 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 345 | background-repeat: repeat-x; 346 | border-radius: 4px; 347 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 348 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 349 | } 350 | .navbar-default .navbar-nav > .open > a, 351 | .navbar-default .navbar-nav > .active > a { 352 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 353 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 355 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 357 | background-repeat: repeat-x; 358 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 359 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 360 | } 361 | .navbar-brand, 362 | .navbar-nav > li > a { 363 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 364 | } 365 | .navbar-inverse { 366 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 367 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 368 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 369 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 370 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 371 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 372 | background-repeat: repeat-x; 373 | border-radius: 4px; 374 | } 375 | .navbar-inverse .navbar-nav > .open > a, 376 | .navbar-inverse .navbar-nav > .active > a { 377 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 378 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 379 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 380 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 382 | background-repeat: repeat-x; 383 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 384 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 385 | } 386 | .navbar-inverse .navbar-brand, 387 | .navbar-inverse .navbar-nav > li > a { 388 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 389 | } 390 | .navbar-static-top, 391 | .navbar-fixed-top, 392 | .navbar-fixed-bottom { 393 | border-radius: 0; 394 | } 395 | @media (max-width: 767px) { 396 | .navbar .navbar-nav .open .dropdown-menu > .active > a, 397 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, 398 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { 399 | color: #fff; 400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | } 408 | .alert { 409 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 410 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 411 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 412 | } 413 | .alert-success { 414 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 415 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 416 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 417 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 418 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 419 | background-repeat: repeat-x; 420 | border-color: #b2dba1; 421 | } 422 | .alert-info { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 428 | background-repeat: repeat-x; 429 | border-color: #9acfea; 430 | } 431 | .alert-warning { 432 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 433 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 435 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #f5e79e; 439 | } 440 | .alert-danger { 441 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 442 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 443 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 444 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 445 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 446 | background-repeat: repeat-x; 447 | border-color: #dca7a7; 448 | } 449 | .progress { 450 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 451 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 453 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 455 | background-repeat: repeat-x; 456 | } 457 | .progress-bar { 458 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); 459 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); 460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); 461 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); 462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); 463 | background-repeat: repeat-x; 464 | } 465 | .progress-bar-success { 466 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 467 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 469 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 471 | background-repeat: repeat-x; 472 | } 473 | .progress-bar-info { 474 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 475 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 476 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 477 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 478 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 479 | background-repeat: repeat-x; 480 | } 481 | .progress-bar-warning { 482 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 483 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 484 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 485 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 486 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 487 | background-repeat: repeat-x; 488 | } 489 | .progress-bar-danger { 490 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 491 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 492 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 493 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 494 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 495 | background-repeat: repeat-x; 496 | } 497 | .progress-bar-striped { 498 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 499 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 500 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 501 | } 502 | .list-group { 503 | border-radius: 4px; 504 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 505 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 506 | } 507 | .list-group-item.active, 508 | .list-group-item.active:hover, 509 | .list-group-item.active:focus { 510 | text-shadow: 0 -1px 0 #286090; 511 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); 512 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); 513 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); 514 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); 515 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); 516 | background-repeat: repeat-x; 517 | border-color: #2b669a; 518 | } 519 | .list-group-item.active .badge, 520 | .list-group-item.active:hover .badge, 521 | .list-group-item.active:focus .badge { 522 | text-shadow: none; 523 | } 524 | .panel { 525 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 526 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 527 | } 528 | .panel-default > .panel-heading { 529 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 530 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 531 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 532 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 533 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 534 | background-repeat: repeat-x; 535 | } 536 | .panel-primary > .panel-heading { 537 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 538 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 539 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 540 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 541 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 542 | background-repeat: repeat-x; 543 | } 544 | .panel-success > .panel-heading { 545 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 546 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 547 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 548 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 549 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 550 | background-repeat: repeat-x; 551 | } 552 | .panel-info > .panel-heading { 553 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 554 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 555 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 556 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 557 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 558 | background-repeat: repeat-x; 559 | } 560 | .panel-warning > .panel-heading { 561 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 562 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 563 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 564 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 565 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 566 | background-repeat: repeat-x; 567 | } 568 | .panel-danger > .panel-heading { 569 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 570 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 571 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 572 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 573 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 574 | background-repeat: repeat-x; 575 | } 576 | .well { 577 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 578 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 579 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 580 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 581 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 582 | background-repeat: repeat-x; 583 | border-color: #dcdcdc; 584 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 585 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 586 | } 587 | /*# sourceMappingURL=bootstrap-theme.css.map */ 588 | -------------------------------------------------------------------------------- /flask/static/drops/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.1",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.1",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c="prev"==a?-1:1,d=this.getItemIndex(b),e=(d+c)%this.$items.length;return this.$items.eq(e)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i="next"==b?"first":"last",j=this;if(!f.length){if(!this.options.wrap)return;f=this.$element.find(".item")[i]()}if(f.hasClass("active"))return this.sliding=!1;var k=f[0],l=a.Event("slide.bs.carousel",{relatedTarget:k,direction:h});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var m=a(this.$indicators.children()[this.getItemIndex(f)]);m&&m.addClass("active")}var n=a.Event("slid.bs.carousel",{relatedTarget:k,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),j.sliding=!1,setTimeout(function(){j.$element.trigger(n)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(n)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a(this.options.trigger).filter('[href="#'+b.id+'"], [data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.1",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.find("> .panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.1",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); --------------------------------------------------------------------------------