├── .gitignore ├── README.md ├── demo.py ├── index └── segments.gen ├── indexing.py ├── initial.py ├── sds.sql ├── serve.py ├── settings.py ├── static ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js ├── img │ ├── alipay.jpg │ └── donate.jpg ├── script │ ├── Chart.min.js │ ├── angular-sanitize.js │ ├── angular-sanitize.min.js │ ├── angular-sanitize.min.js.map │ ├── angular.min.js │ ├── angular.min.js.map │ ├── jquery.min.js │ ├── sanitize.js │ └── tools.js └── style │ └── dashboard.css ├── template ├── dashboard.html ├── donate.html ├── index.html └── testchinese.html ├── tools.py └── traffic.py /.gitignore: -------------------------------------------------------------------------------- 1 | index/* 2 | log/* 3 | *.swp 4 | *.pyc 5 | *.gen 6 | *.log 7 | *.csv 8 | *.log 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # skydrivesearcher 2 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | from IPython import embed 4 | 5 | embed() 6 | -------------------------------------------------------------------------------- /index/segments.gen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/index/segments.gen -------------------------------------------------------------------------------- /indexing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding:utf-8 3 | 4 | from __future__ import unicode_literals 5 | from lucene import * 6 | from settings import db, INDEX_DIR, ANALYZER 7 | from tools import gen_logger, pagination 8 | from time import time 9 | 10 | logger = gen_logger(__file__, 'w') 11 | 12 | def index(): 13 | ''' 14 | :desc:重构索引 15 | ''' 16 | logger.info('重构索引...') 17 | start_time = time() 18 | resource_count = db.get('select count(*) as count from resource')['count'] 19 | logger.info('收录数据 {} 条'.format(resource_count)) 20 | sql = 'select * from resource limit 10000 offset %s' 21 | counter = 0 22 | writer = IndexWriter(INDEX_DIR, ANALYZER, True, IndexWriter.MaxFieldLength.UNLIMITED) 23 | for offset in range(0, resource_count, 10000): 24 | items = db.query(sql, offset) 25 | for item in items: 26 | doc = Document() 27 | doc.add(Field('title', item['title'], Field.Store.YES, Field.Index.ANALYZED)) 28 | doc.add(Field('url', item['url'], Field.Store.YES, Field.Index.NOT_ANALYZED)) 29 | doc.add(Field('feed_time', str(item['feed_time']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 30 | doc.add(Field('feed_username', item['feed_username'], Field.Store.YES, Field.Index.NOT_ANALYZED)) 31 | doc.add(Field('feed_user_uk', str(item['feed_user_uk']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 32 | doc.add(Field('origin', item['origin'], Field.Store.YES, Field.Index.NOT_ANALYZED)) 33 | doc.add(Field('size', str(item['size']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 34 | doc.add(Field('v_cnt', str(item['v_cnt']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 35 | doc.add(Field('d_cnt', str(item['d_cnt']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 36 | doc.add(Field('t_cnt', str(item['t_cnt']), Field.Store.YES, Field.Index.NOT_ANALYZED)) 37 | writer.addDocument(doc) 38 | counter += 1 39 | if counter % 10000 == 0: 40 | logger.info('计数 {} / {}'.format(counter, resource_count)) 41 | 42 | writer.close() 43 | cost_time = int(time() - start_time) 44 | logger.info('重构索引完毕,耗时 {}'.format(cost_time,)) 45 | index_time = int(time()) 46 | db.insert('insert into index_log (index_time, count, cost_time) values (%s, %s, %s)', 47 | index_time, resource_count, cost_time) 48 | 49 | if __name__ == '__main__': 50 | index() 51 | -------------------------------------------------------------------------------- /initial.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | import os 4 | from pymongo import MongoClient 5 | from indexing import index 6 | from os.path import join, dirname, abspath 7 | from settings import LOG_DIR 8 | 9 | db = torndb.Connection('localhost:3306', 'sds', user='root', password='britten') 10 | 11 | # 清空日志 12 | for parent, dirnames, filenames in os.walk(LOG_DIR): 13 | for filename in filenames: 14 | filepath = join(parent, filename) 15 | os.remove(filepath) 16 | 17 | # 初始化索引 18 | index() 19 | -------------------------------------------------------------------------------- /sds.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.5.35, for debian-linux-gnu (x86_64) 2 | -- 3 | -- Host: localhost Database: sds 4 | -- ------------------------------------------------------ 5 | -- Server version 5.5.35-1ubuntu1 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `index_log` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `index_log`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `index_log` ( 26 | `id` int(11) NOT NULL AUTO_INCREMENT, 27 | `cost_time` bigint(20) NOT NULL, 28 | `count` bigint(20) NOT NULL, 29 | `index_time` bigint(20) NOT NULL, 30 | PRIMARY KEY (`id`) 31 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 32 | /*!40101 SET character_set_client = @saved_cs_client */; 33 | 34 | -- 35 | -- Table structure for table `resource` 36 | -- 37 | 38 | DROP TABLE IF EXISTS `resource`; 39 | /*!40101 SET @saved_cs_client = @@character_set_client */; 40 | /*!40101 SET character_set_client = utf8 */; 41 | CREATE TABLE `resource` ( 42 | `id` int(11) NOT NULL AUTO_INCREMENT, 43 | `origin` varchar(18) NOT NULL, 44 | `url` text NOT NULL, 45 | `title` text NOT NULL, 46 | `feed_time` int(11) NOT NULL, 47 | `feed_username` text NOT NULL, 48 | `feed_user_uk` varchar(18) NOT NULL, 49 | `size` bigint(20) NOT NULL, 50 | `v_cnt` int(11) NOT NULL, 51 | `d_cnt` int(11) NOT NULL, 52 | `t_cnt` int(11) NOT NULL, 53 | PRIMARY KEY (`id`) 54 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 55 | /*!40101 SET character_set_client = @saved_cs_client */; 56 | 57 | -- 58 | -- Table structure for table `user` 59 | -- 60 | 61 | DROP TABLE IF EXISTS `user`; 62 | /*!40101 SET @saved_cs_client = @@character_set_client */; 63 | /*!40101 SET character_set_client = utf8 */; 64 | CREATE TABLE `user` ( 65 | `id` int(11) NOT NULL AUTO_INCREMENT, 66 | `uk` varchar(18) NOT NULL, 67 | `origin` varchar(18) NOT NULL, 68 | PRIMARY KEY (`id`), 69 | UNIQUE KEY `uk` (`uk`) 70 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 71 | /*!40101 SET character_set_client = @saved_cs_client */; 72 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 73 | 74 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 75 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 76 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 77 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 78 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 79 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 80 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 81 | 82 | -- Dump completed on 2015-07-21 23:13:47 83 | -------------------------------------------------------------------------------- /serve.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | import tornado 4 | import tornado.web 5 | import tornado.ioloop 6 | import json 7 | import re 8 | from time import localtime, strftime, time 9 | from lucene import * 10 | from settings import * 11 | from tools import gen_logger, pagination 12 | from functools import wraps 13 | from IPython import embed 14 | 15 | logger = gen_logger(__file__, 'w') 16 | SEARCHER = IndexSearcher(INDEX_DIR) 17 | 18 | def traffic_counter(func): 19 | ''' 20 | :desc:流量统计 21 | ''' 22 | @wraps(func) 23 | def wrapper(*args, **kwargs): 24 | return func(*args, **kwargs) 25 | return wrapper 26 | 27 | class IndexHandler(tornado.web.RequestHandler): 28 | ''' 29 | :desc:首页 30 | ''' 31 | def get(self): 32 | self.render('index.html') 33 | 34 | class SearchHandler(tornado.web.RequestHandler): 35 | ''' 36 | :desc:搜索 37 | ''' 38 | @tornado.web.asynchronous 39 | def get(self): 40 | # 转义字符前加上\ 41 | def replace(matched): 42 | return '\{escape}'.format(escape=matched.group('escape')) 43 | query_string = self.get_argument('query_string', '').strip() 44 | page = int(self.get_argument('page', 1)) 45 | if query_string == '': 46 | self.send_error(400) 47 | else: 48 | # 转义特殊字符 49 | query_string = re.sub(r'(?P[-+!\\():^\]\[{}~*?])', replace, query_string) 50 | # 解析用户查询 51 | query = QueryParser(Version.LUCENE_30, 'title', ANALYZER).parse(query_string) 52 | scorer = QueryScorer(query, 'title') 53 | # 设置高亮器 54 | highlighter = Highlighter(FORMATTER, scorer) 55 | highlighter.setTextFragmenter(SimpleSpanFragmenter(scorer)) 56 | start_time = time() 57 | # 开始搜索 58 | total_hits = SEARCHER.search(query, RESULT_MAX_NUM) 59 | cost_time = '%.3f 秒' % ((time() - start_time),) 60 | # 符合条件的资源数量 61 | total_count = len(total_hits.scoreDocs) 62 | 63 | # 对搜索结果进行高亮和封装 64 | # 对搜索结果分页 65 | paging = pagination(total_hits.scoreDocs, page, RESULT_PAGE_SIZE) 66 | 67 | def unit(size): 68 | if size == 0: 69 | return '未知' 70 | elif size >= 1024 ** 3: 71 | return '%.1f G' % (size / 1024 ** 3,) 72 | elif size >= 1024 ** 2: 73 | return '%.1f M' % (size / 1024 ** 2,) 74 | else: 75 | return '%.1f K' % (size / 1024,) 76 | 77 | def wrap(hit): 78 | doc = SEARCHER.doc(hit.doc) 79 | title = doc.get('title') 80 | stream = TokenSources.getAnyTokenStream(SEARCHER.getIndexReader(), hit.doc, 'title', doc, ANALYZER) 81 | title = highlighter.getBestFragment(stream, title) 82 | feed_time = int(doc.get('feed_time')) 83 | item = dict( 84 | title=title, 85 | url=doc.get('url'), 86 | size=unit(float(doc.get('size'))), 87 | v_cnt=doc.get('v_cnt'), 88 | d_cnt=doc.get('d_cnt'), 89 | t_cnt=doc.get('t_cnt'), 90 | origin=doc.get('origin'), 91 | feed_time=strftime('%Y-%m-%d %H:%M:%S', localtime(feed_time)), 92 | ) 93 | return item 94 | 95 | paging['objects'] = map(wrap, paging['objects']) 96 | 97 | kwargs = dict( 98 | cost_time=cost_time, 99 | paging=paging, 100 | total_count=total_count, 101 | ) 102 | 103 | self.write(json.dumps(kwargs)) 104 | self.finish() 105 | 106 | # class OverlookHandler(tornado.web.RequestHandler): 107 | # def get(self): 108 | # self.render('dashboard.html') 109 | 110 | # class OverlookChartHandler(tornado.web.RequestHandler): 111 | # def get(self): 112 | # chartname = self.get_argument('chartname', None) 113 | # log = { 114 | # 'user': list(db.user_log.find()), 115 | # 'resource': list(db.resource_log.find()), 116 | # 'traffic': list(db.traffic_log.find()), 117 | # }.get(chartname, None) 118 | # if log is None: self.send_error(400) 119 | 120 | # def gen_time(ctime): 121 | # return strftime('%H:%M', localtime(ctime)) 122 | 123 | # if len(log) <= LOG_LIMIT: 124 | # ctime_list = [gen_time(x['ctime']) for x in log] 125 | # count_list = [x['count'] for x in log] 126 | # else: 127 | # log = log[len(log) - LOG_LIMIT:] 128 | # ctime_list = [gen_time(x['ctime']) for x in log] 129 | # count_list = [x['count'] for x in log] 130 | 131 | # data = dict( 132 | # ctime_list=ctime_list, 133 | # count_list=count_list, 134 | # ) 135 | 136 | # self.write(json.dumps(data)) 137 | 138 | # class OverlookCSVHandler(tornado.web.RequestHandler): 139 | # @tornado.web.asynchronous 140 | # def get(self): 141 | # csvname = self.get_argument('csvname', None) 142 | # csvinfo = { 143 | # 'user':[db.user_log, 'user.log.{}.csv'], 144 | # 'resource':[db.resource_log, 'resource.log.{}.csv'], 145 | # 'traffic':[db.traffic_log, 'traffic.log.{}.csv'], 146 | # }.get(csvname, None) 147 | # if csvinfo is None: self.send_error(400) 148 | 149 | # self.set_header('Content-Type', 'application/octet-stream') 150 | # self.set_header('Content-Disposition', 'attachment;filename=' + csvinfo[1].format(int(time()))) 151 | 152 | # def gen_line(item): 153 | # _ctime = strftime('%Y-%m-%d %H:%M', localtime(item['ctime'])) 154 | # count = item['count'] 155 | # return '{ctime},{count}\n'.format(ctime=_ctime, count=count) 156 | 157 | # def yield_line(collection): 158 | # for item in collection.find(): 159 | # yield gen_line(item) 160 | 161 | # self.write('ctime,count\n') 162 | # for line in yield_line(csvinfo[0]): 163 | # self.write(line) 164 | 165 | # self.finish() 166 | 167 | class IndexHandler(tornado.web.RequestHandler): 168 | def get(self): 169 | return self.render('index.html') 170 | 171 | class IndexInfoHandler(tornado.web.RequestHandler): 172 | @tornado.web.asynchronous 173 | def get(self): 174 | resource_count = db.get('select count from index_log order by id desc')['count'] 175 | data = dict( 176 | resource_count=resource_count, 177 | ) 178 | self.write(json.dumps(data)) 179 | self.finish() 180 | 181 | # class DonateHandler(tornado.web.RequestHandler): 182 | # def get(self): 183 | # self.render('donate.html') 184 | 185 | # class TestChineseHandler(tornado.web.RequestHandler): 186 | # def post(self): 187 | # query_string = self.get_argument('query_string') 188 | # query = QueryParser(Version.LUCENE_30, 'content', ANALYZER).parse(query_string) 189 | # scorer = QueryScorer(query, 'content') 190 | # highlighter = Highlighter(FORMATTER, scorer) 191 | # highlighter.setTextFragmenter(SimpleSpanFragmenter(scorer)) 192 | # start_time = time() 193 | # total_hits = TESTSEARCHER.search(query, RESULT_MAX_NUM) 194 | # items = [] 195 | 196 | # for hit in total_hits.scoreDocs: 197 | # doc = TESTSEARCHER.doc(hit.doc) 198 | # content = doc.get('content') 199 | # stream = TokenSources.getAnyTokenStream(TESTSEARCHER.getIndexReader(), hit.doc, 'content', doc, ANALYZER) 200 | # content = highlighter.getBestFragment(stream, content) 201 | # items.append(content) 202 | 203 | # self.render('testchinese.html', content=TEST_CHINESE_CONTENT, items=items) 204 | 205 | # def get(self): 206 | # self.render('testchinese.html', content=TEST_CHINESE_CONTENT, items=None) 207 | 208 | settings = dict( 209 | debug=True, 210 | template_path=TEMPLATE_PATH, 211 | static_path=STATIC_PATH, 212 | ) 213 | 214 | application = tornado.web.Application([ 215 | (r'/', IndexHandler), 216 | # (r'/testchinese', TestChineseHandler), 217 | (r'/info', IndexInfoHandler), 218 | # (r'/donate', DonateHandler), 219 | (r'/search', SearchHandler), 220 | # (r'/admin', OverlookHandler), 221 | # (r'/admin/overlook', OverlookHandler), 222 | # (r'/admin/overlook/chart', OverlookChartHandler), 223 | # (r'/admin/overlook/csv', OverlookCSVHandler), 224 | ], **settings) 225 | 226 | if __name__ == '__main__': 227 | application.listen(8888) 228 | tornado.ioloop.IOLoop.instance().start() 229 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | import lucene 4 | import torndb 5 | import MySQLdb 6 | from lucene import * 7 | from os.path import join, abspath, dirname 8 | 9 | initVM() 10 | 11 | db = torndb.Connection('localhost:3306', 'sds', user='root', password='britten') 12 | # db = MySQLdb.connect('localhost', 'root', 'britten', 'sds') 13 | 14 | RESULT_PAGE_SIZE = 20 15 | RESULT_MAX_NUM = 5000 16 | 17 | TEST_CHINESE_CONTENT = ''' 18 | 中华人民共和国 19 | ''' 20 | 21 | # ANALYZER = StandardAnalyzer(Version.LUCENE_30) 22 | # ANALYZER = ChineseAnalyzer(Version.LUCENE_30) 23 | # ANALYZER = CJKAnalyzer(Version.LUCENE_30) 24 | ANALYZER = SmartChineseAnalyzer(Version.LUCENE_30) 25 | 26 | # TESTINDEXPATH = join(dirname(abspath(__file__)), 'testindex') 27 | # TESTINDEXDIR = SimpleFSDirectory(File(TESTINDEXPATH)) 28 | # TESTSEARCHER = IndexSearcher(TESTINDEXDIR) 29 | 30 | STATIC_PATH = join(dirname(abspath(__file__)), 'static') 31 | TEMPLATE_PATH = join(dirname(abspath(__file__)), 'template') 32 | INDEX_PATH = join(dirname(abspath(__file__)), 'index') 33 | 34 | INDEX_DIR = SimpleFSDirectory(File(INDEX_PATH)) 35 | LOG_DIR = join(dirname(abspath(__file__)), 'log') 36 | 37 | FORMATTER = SimpleHTMLFormatter("", "") 38 | -------------------------------------------------------------------------------- /static/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.4 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn-default .badge, 33 | .btn-primary .badge, 34 | .btn-success .badge, 35 | .btn-info .badge, 36 | .btn-warning .badge, 37 | .btn-danger .badge { 38 | text-shadow: none; 39 | } 40 | .btn:active, 41 | .btn.active { 42 | background-image: none; 43 | } 44 | .btn-default { 45 | text-shadow: 0 1px 0 #fff; 46 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 47 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 48 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 49 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 50 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 51 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 52 | background-repeat: repeat-x; 53 | border-color: #dbdbdb; 54 | border-color: #ccc; 55 | } 56 | .btn-default:hover, 57 | .btn-default:focus { 58 | background-color: #e0e0e0; 59 | background-position: 0 -15px; 60 | } 61 | .btn-default:active, 62 | .btn-default.active { 63 | background-color: #e0e0e0; 64 | border-color: #dbdbdb; 65 | } 66 | .btn-default.disabled, 67 | .btn-default:disabled, 68 | .btn-default[disabled] { 69 | background-color: #e0e0e0; 70 | background-image: none; 71 | } 72 | .btn-primary { 73 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); 74 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); 75 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); 76 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); 77 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); 78 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 79 | background-repeat: repeat-x; 80 | border-color: #245580; 81 | } 82 | .btn-primary:hover, 83 | .btn-primary:focus { 84 | background-color: #265a88; 85 | background-position: 0 -15px; 86 | } 87 | .btn-primary:active, 88 | .btn-primary.active { 89 | background-color: #265a88; 90 | border-color: #245580; 91 | } 92 | .btn-primary.disabled, 93 | .btn-primary:disabled, 94 | .btn-primary[disabled] { 95 | background-color: #265a88; 96 | background-image: none; 97 | } 98 | .btn-success { 99 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 100 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 101 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 102 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 103 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 104 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 105 | background-repeat: repeat-x; 106 | border-color: #3e8f3e; 107 | } 108 | .btn-success:hover, 109 | .btn-success:focus { 110 | background-color: #419641; 111 | background-position: 0 -15px; 112 | } 113 | .btn-success:active, 114 | .btn-success.active { 115 | background-color: #419641; 116 | border-color: #3e8f3e; 117 | } 118 | .btn-success.disabled, 119 | .btn-success:disabled, 120 | .btn-success[disabled] { 121 | background-color: #419641; 122 | background-image: none; 123 | } 124 | .btn-info { 125 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 126 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 127 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 128 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 129 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 130 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 131 | background-repeat: repeat-x; 132 | border-color: #28a4c9; 133 | } 134 | .btn-info:hover, 135 | .btn-info:focus { 136 | background-color: #2aabd2; 137 | background-position: 0 -15px; 138 | } 139 | .btn-info:active, 140 | .btn-info.active { 141 | background-color: #2aabd2; 142 | border-color: #28a4c9; 143 | } 144 | .btn-info.disabled, 145 | .btn-info:disabled, 146 | .btn-info[disabled] { 147 | background-color: #2aabd2; 148 | background-image: none; 149 | } 150 | .btn-warning { 151 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 152 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 153 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 154 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 155 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 156 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 157 | background-repeat: repeat-x; 158 | border-color: #e38d13; 159 | } 160 | .btn-warning:hover, 161 | .btn-warning:focus { 162 | background-color: #eb9316; 163 | background-position: 0 -15px; 164 | } 165 | .btn-warning:active, 166 | .btn-warning.active { 167 | background-color: #eb9316; 168 | border-color: #e38d13; 169 | } 170 | .btn-warning.disabled, 171 | .btn-warning:disabled, 172 | .btn-warning[disabled] { 173 | background-color: #eb9316; 174 | background-image: none; 175 | } 176 | .btn-danger { 177 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 178 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 179 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 180 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 181 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 182 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 183 | background-repeat: repeat-x; 184 | border-color: #b92c28; 185 | } 186 | .btn-danger:hover, 187 | .btn-danger:focus { 188 | background-color: #c12e2a; 189 | background-position: 0 -15px; 190 | } 191 | .btn-danger:active, 192 | .btn-danger.active { 193 | background-color: #c12e2a; 194 | border-color: #b92c28; 195 | } 196 | .btn-danger.disabled, 197 | .btn-danger:disabled, 198 | .btn-danger[disabled] { 199 | background-color: #c12e2a; 200 | background-image: none; 201 | } 202 | .thumbnail, 203 | .img-thumbnail { 204 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 205 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 206 | } 207 | .dropdown-menu > li > a:hover, 208 | .dropdown-menu > li > a:focus { 209 | background-color: #e8e8e8; 210 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 211 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 212 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 213 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 214 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 215 | background-repeat: repeat-x; 216 | } 217 | .dropdown-menu > .active > a, 218 | .dropdown-menu > .active > a:hover, 219 | .dropdown-menu > .active > a:focus { 220 | background-color: #2e6da4; 221 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 222 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 223 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 224 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 225 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 226 | background-repeat: repeat-x; 227 | } 228 | .navbar-default { 229 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 230 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 231 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 232 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 233 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 234 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 235 | background-repeat: repeat-x; 236 | border-radius: 4px; 237 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 238 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 239 | } 240 | .navbar-default .navbar-nav > .open > a, 241 | .navbar-default .navbar-nav > .active > a { 242 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 243 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 244 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 245 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 246 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 247 | background-repeat: repeat-x; 248 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 249 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 250 | } 251 | .navbar-brand, 252 | .navbar-nav > li > a { 253 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 254 | } 255 | .navbar-inverse { 256 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 257 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 258 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 259 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 260 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 261 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 262 | background-repeat: repeat-x; 263 | } 264 | .navbar-inverse .navbar-nav > .open > a, 265 | .navbar-inverse .navbar-nav > .active > a { 266 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 267 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 268 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 269 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 270 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 271 | background-repeat: repeat-x; 272 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 273 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 274 | } 275 | .navbar-inverse .navbar-brand, 276 | .navbar-inverse .navbar-nav > li > a { 277 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 278 | } 279 | .navbar-static-top, 280 | .navbar-fixed-top, 281 | .navbar-fixed-bottom { 282 | border-radius: 0; 283 | } 284 | @media (max-width: 767px) { 285 | .navbar .navbar-nav .open .dropdown-menu > .active > a, 286 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, 287 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { 288 | color: #fff; 289 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 290 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 291 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 292 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 293 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 294 | background-repeat: repeat-x; 295 | } 296 | } 297 | .alert { 298 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 299 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 300 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 301 | } 302 | .alert-success { 303 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 304 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 305 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 306 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 307 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 308 | background-repeat: repeat-x; 309 | border-color: #b2dba1; 310 | } 311 | .alert-info { 312 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 313 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 314 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 315 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 316 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 317 | background-repeat: repeat-x; 318 | border-color: #9acfea; 319 | } 320 | .alert-warning { 321 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 322 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 323 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 324 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 325 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 326 | background-repeat: repeat-x; 327 | border-color: #f5e79e; 328 | } 329 | .alert-danger { 330 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 331 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 332 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 333 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 334 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 335 | background-repeat: repeat-x; 336 | border-color: #dca7a7; 337 | } 338 | .progress { 339 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 340 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 342 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 344 | background-repeat: repeat-x; 345 | } 346 | .progress-bar { 347 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); 348 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); 349 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); 350 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); 351 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); 352 | background-repeat: repeat-x; 353 | } 354 | .progress-bar-success { 355 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 356 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 357 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 358 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 359 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 360 | background-repeat: repeat-x; 361 | } 362 | .progress-bar-info { 363 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 364 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 365 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 366 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 367 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 368 | background-repeat: repeat-x; 369 | } 370 | .progress-bar-warning { 371 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 372 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 374 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 376 | background-repeat: repeat-x; 377 | } 378 | .progress-bar-danger { 379 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 380 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 381 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 382 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 383 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 384 | background-repeat: repeat-x; 385 | } 386 | .progress-bar-striped { 387 | 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); 388 | 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); 389 | 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); 390 | } 391 | .list-group { 392 | border-radius: 4px; 393 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 394 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 395 | } 396 | .list-group-item.active, 397 | .list-group-item.active:hover, 398 | .list-group-item.active:focus { 399 | text-shadow: 0 -1px 0 #286090; 400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); 401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); 403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); 405 | background-repeat: repeat-x; 406 | border-color: #2b669a; 407 | } 408 | .list-group-item.active .badge, 409 | .list-group-item.active:hover .badge, 410 | .list-group-item.active:focus .badge { 411 | text-shadow: none; 412 | } 413 | .panel { 414 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 415 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 416 | } 417 | .panel-default > .panel-heading { 418 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 419 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 420 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 421 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 422 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 423 | background-repeat: repeat-x; 424 | } 425 | .panel-primary > .panel-heading { 426 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 427 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 428 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 429 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 430 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 431 | background-repeat: repeat-x; 432 | } 433 | .panel-success > .panel-heading { 434 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 435 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 436 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 437 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 438 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 439 | background-repeat: repeat-x; 440 | } 441 | .panel-info > .panel-heading { 442 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 443 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 444 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 445 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 446 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 447 | background-repeat: repeat-x; 448 | } 449 | .panel-warning > .panel-heading { 450 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 451 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 453 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 455 | background-repeat: repeat-x; 456 | } 457 | .panel-danger > .panel-heading { 458 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 459 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 461 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 463 | background-repeat: repeat-x; 464 | } 465 | .well { 466 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 467 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 469 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 471 | background-repeat: repeat-x; 472 | border-color: #dcdcdc; 473 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 474 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 475 | } 476 | /*# sourceMappingURL=bootstrap-theme.css.map */ 477 | -------------------------------------------------------------------------------- /static/bootstrap/css/bootstrap-theme.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","file":"bootstrap-theme.css","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",".btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default:disabled,\n.btn-default[disabled] {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary:disabled,\n.btn-primary[disabled] {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success:disabled,\n.btn-success[disabled] {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info:disabled,\n.btn-info[disabled] {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning:disabled,\n.btn-warning[disabled] {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger:disabled,\n.btn-danger[disabled] {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} -------------------------------------------------------------------------------- /static/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.4 (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 .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,.btn-default[disabled]{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,.btn-primary[disabled]{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,.btn-success[disabled]{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,.btn-info[disabled]{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,.btn-warning[disabled]{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,.btn-danger[disabled]{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}.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)} -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /static/bootstrap/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.4 (http://getbootstrap.com) 3 | * Copyright 2011-2015 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){"use strict";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.4",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.4",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=null,this.sliding=null,this.interval=null,this.$active=null,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.4",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=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},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=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,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(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),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|hide/.test(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('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][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.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},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.children(".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":e.data();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.4",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(this.options.viewport.selector||this.options.viewport),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.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),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.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)),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);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.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.width&&(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(){return this.$tip=this.$tip||a(this.options.template)},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))),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)})};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.4",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.4",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.4",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=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); -------------------------------------------------------------------------------- /static/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') -------------------------------------------------------------------------------- /static/img/alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/img/alipay.jpg -------------------------------------------------------------------------------- /static/img/donate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liqueur/skydrivesearcher/6ed2bdf393aebb8c0161962508e2b7c58c806ede/static/img/donate.jpg -------------------------------------------------------------------------------- /static/script/angular-sanitize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.0-rc.3 3 | * (c) 2010-2012 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | var $sanitizeMinErr = angular.$$minErr('$sanitize'); 9 | 10 | /** 11 | * @ngdoc overview 12 | * @name ngSanitize 13 | * @description 14 | * 15 | * # ngSanitize 16 | * 17 | * The `ngSanitize` module provides functionality to sanitize HTML. 18 | * 19 | * {@installModule sanitize} 20 | * 21 | * See {@link ngSanitize.$sanitize `$sanitize`} for usage. 22 | */ 23 | 24 | /* 25 | * HTML Parser By Misko Hevery (misko@hevery.com) 26 | * based on: HTML Parser By John Resig (ejohn.org) 27 | * Original code by Erik Arvidsson, Mozilla Public License 28 | * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js 29 | * 30 | * // Use like so: 31 | * htmlParser(htmlString, { 32 | * start: function(tag, attrs, unary) {}, 33 | * end: function(tag) {}, 34 | * chars: function(text) {}, 35 | * comment: function(text) {} 36 | * }); 37 | * 38 | */ 39 | 40 | 41 | /** 42 | * @ngdoc service 43 | * @name ngSanitize.$sanitize 44 | * @function 45 | * 46 | * @description 47 | * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are 48 | * then serialized back to properly escaped html string. This means that no unsafe input can make 49 | * it into the returned string, however, since our parser is more strict than a typical browser 50 | * parser, it's possible that some obscure input, which would be recognized as valid HTML by a 51 | * browser, won't make it through the sanitizer. 52 | * 53 | * @param {string} html Html input. 54 | * @returns {string} Sanitized html. 55 | * 56 | * @example 57 | 58 | 59 | 70 |
71 | Snippet: 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 |
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
</div>
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
98 |
99 |
100 | 101 | it('should sanitize the html snippet by default', function() { 102 | expect(using('#bind-html-with-sanitize').element('div').html()). 103 | toBe('

an html\nclick here\nsnippet

'); 104 | }); 105 | 106 | it('should inline raw snippet if bound to a trusted value', function() { 107 | expect(using('#bind-html-with-trust').element("div").html()). 108 | toBe("

an html\n" + 109 | "click here\n" + 110 | "snippet

"); 111 | }); 112 | 113 | it('should escape snippet without any filter', function() { 114 | expect(using('#bind-default').element('div').html()). 115 | toBe("<p style=\"color:blue\">an html\n" + 116 | "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + 117 | "snippet</p>"); 118 | }); 119 | 120 | it('should update', function() { 121 | input('snippet').enter('new text'); 122 | expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new text'); 123 | expect(using('#bind-html-with-trust').element('div').html()).toBe('new text'); 124 | expect(using('#bind-default').element('div').html()).toBe("new <b onclick=\"alert(1)\">text</b>"); 125 | }); 126 |
127 |
128 | */ 129 | var $sanitize = function(html) { 130 | var buf = []; 131 | htmlParser(html, htmlSanitizeWriter(buf)); 132 | return buf.join(''); 133 | }; 134 | 135 | 136 | // Regular Expressions for parsing tags and attributes 137 | var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, 138 | END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, 139 | ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, 140 | BEGIN_TAG_REGEXP = /^/g, 143 | DOCTYPE_REGEXP = /]*?)>/i, 144 | CDATA_REGEXP = //g, 145 | URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/i, 146 | NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character) 147 | 148 | 149 | // Good source of info about elements and attributes 150 | // http://dev.w3.org/html5/spec/Overview.html#semantics 151 | // http://simon.html5.org/html-elements 152 | 153 | // Safe Void Elements - HTML5 154 | // http://dev.w3.org/html5/spec/Overview.html#void-elements 155 | var voidElements = makeMap("area,br,col,hr,img,wbr"); 156 | 157 | // Elements that you can, intentionally, leave open (and which close themselves) 158 | // http://dev.w3.org/html5/spec/Overview.html#optional-tags 159 | var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), 160 | optionalEndTagInlineElements = makeMap("rp,rt"), 161 | optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements); 162 | 163 | // Safe Block Elements - HTML5 164 | var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," + 165 | "blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," + 166 | "header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); 167 | 168 | // Inline Elements - HTML5 169 | var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," + 170 | "big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," + 171 | "span,strike,strong,sub,sup,time,tt,u,var")); 172 | 173 | 174 | // Special Elements (can contain anything) 175 | var specialElements = makeMap("script,style"); 176 | 177 | var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements); 178 | 179 | //Attributes that have href and hence need to be sanitized 180 | var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); 181 | var validAttrs = angular.extend({}, uriAttrs, makeMap( 182 | 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ 183 | 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ 184 | 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ 185 | 'scope,scrolling,shape,span,start,summary,target,title,type,'+ 186 | 'valign,value,vspace,width')); 187 | 188 | function makeMap(str) { 189 | var obj = {}, items = str.split(','), i; 190 | for (i = 0; i < items.length; i++) obj[items[i]] = true; 191 | return obj; 192 | } 193 | 194 | 195 | /** 196 | * @example 197 | * htmlParser(htmlString, { 198 | * start: function(tag, attrs, unary) {}, 199 | * end: function(tag) {}, 200 | * chars: function(text) {}, 201 | * comment: function(text) {} 202 | * }); 203 | * 204 | * @param {string} html string 205 | * @param {object} handler 206 | */ 207 | function htmlParser( html, handler ) { 208 | var index, chars, match, stack = [], last = html; 209 | stack.last = function() { return stack[ stack.length - 1 ]; }; 210 | 211 | while ( html ) { 212 | chars = true; 213 | 214 | // Make sure we're not in a script or style element 215 | if ( !stack.last() || !specialElements[ stack.last() ] ) { 216 | 217 | // Comment 218 | if ( html.indexOf("", index) === index) { 223 | if (handler.comment) handler.comment( html.substring( 4, index ) ); 224 | html = html.substring( index + 3 ); 225 | chars = false; 226 | } 227 | // DOCTYPE 228 | } else if ( DOCTYPE_REGEXP.test(html) ) { 229 | match = html.match( DOCTYPE_REGEXP ); 230 | 231 | if ( match ) { 232 | html = html.replace( match[0] , ''); 233 | chars = false; 234 | } 235 | // end tag 236 | } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { 237 | match = html.match( END_TAG_REGEXP ); 238 | 239 | if ( match ) { 240 | html = html.substring( match[0].length ); 241 | match[0].replace( END_TAG_REGEXP, parseEndTag ); 242 | chars = false; 243 | } 244 | 245 | // start tag 246 | } else if ( BEGIN_TAG_REGEXP.test(html) ) { 247 | match = html.match( START_TAG_REGEXP ); 248 | 249 | if ( match ) { 250 | html = html.substring( match[0].length ); 251 | match[0].replace( START_TAG_REGEXP, parseStartTag ); 252 | chars = false; 253 | } 254 | } 255 | 256 | if ( chars ) { 257 | index = html.indexOf("<"); 258 | 259 | var text = index < 0 ? html : html.substring( 0, index ); 260 | html = index < 0 ? "" : html.substring( index ); 261 | 262 | if (handler.chars) handler.chars( decodeEntities(text) ); 263 | } 264 | 265 | } else { 266 | html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){ 267 | text = text. 268 | replace(COMMENT_REGEXP, "$1"). 269 | replace(CDATA_REGEXP, "$1"); 270 | 271 | if (handler.chars) handler.chars( decodeEntities(text) ); 272 | 273 | return ""; 274 | }); 275 | 276 | parseEndTag( "", stack.last() ); 277 | } 278 | 279 | if ( html == last ) { 280 | throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block of html: {0}", html); 281 | } 282 | last = html; 283 | } 284 | 285 | // Clean up any remaining tags 286 | parseEndTag(); 287 | 288 | function parseStartTag( tag, tagName, rest, unary ) { 289 | tagName = angular.lowercase(tagName); 290 | if ( blockElements[ tagName ] ) { 291 | while ( stack.last() && inlineElements[ stack.last() ] ) { 292 | parseEndTag( "", stack.last() ); 293 | } 294 | } 295 | 296 | if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { 297 | parseEndTag( "", tagName ); 298 | } 299 | 300 | unary = voidElements[ tagName ] || !!unary; 301 | 302 | if ( !unary ) 303 | stack.push( tagName ); 304 | 305 | var attrs = {}; 306 | 307 | rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { 308 | var value = doubleQuotedValue 309 | || singleQuotedValue 310 | || unquotedValue 311 | || ''; 312 | 313 | attrs[name] = decodeEntities(value); 314 | }); 315 | if (handler.start) handler.start( tagName, attrs, unary ); 316 | } 317 | 318 | function parseEndTag( tag, tagName ) { 319 | var pos = 0, i; 320 | tagName = angular.lowercase(tagName); 321 | if ( tagName ) 322 | // Find the closest opened tag of the same type 323 | for ( pos = stack.length - 1; pos >= 0; pos-- ) 324 | if ( stack[ pos ] == tagName ) 325 | break; 326 | 327 | if ( pos >= 0 ) { 328 | // Close all the open elements, up the stack 329 | for ( i = stack.length - 1; i >= pos; i-- ) 330 | if (handler.end) handler.end( stack[ i ] ); 331 | 332 | // Remove the open elements from the stack 333 | stack.length = pos; 334 | } 335 | } 336 | } 337 | 338 | /** 339 | * decodes all entities into regular string 340 | * @param value 341 | * @returns {string} A string with decoded entities. 342 | */ 343 | var hiddenPre=document.createElement("pre"); 344 | function decodeEntities(value) { 345 | hiddenPre.innerHTML=value.replace(//g, '>'); 364 | } 365 | 366 | /** 367 | * create an HTML/XML writer which writes to buffer 368 | * @param {Array} buf use buf.jain('') to get out sanitized html string 369 | * @returns {object} in the form of { 370 | * start: function(tag, attrs, unary) {}, 371 | * end: function(tag) {}, 372 | * chars: function(text) {}, 373 | * comment: function(text) {} 374 | * } 375 | */ 376 | function htmlSanitizeWriter(buf){ 377 | var ignore = false; 378 | var out = angular.bind(buf, buf.push); 379 | return { 380 | start: function(tag, attrs, unary){ 381 | tag = angular.lowercase(tag); 382 | if (!ignore && specialElements[tag]) { 383 | ignore = tag; 384 | } 385 | if (!ignore && validElements[tag] == true) { 386 | out('<'); 387 | out(tag); 388 | angular.forEach(attrs, function(value, key){ 389 | var lkey=angular.lowercase(key); 390 | if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) { 391 | out(' '); 392 | out(key); 393 | out('="'); 394 | out(encodeEntities(value)); 395 | out('"'); 396 | } 397 | }); 398 | out(unary ? '/>' : '>'); 399 | } 400 | }, 401 | end: function(tag){ 402 | tag = angular.lowercase(tag); 403 | if (!ignore && validElements[tag] == true) { 404 | out(''); 407 | } 408 | if (tag == ignore) { 409 | ignore = false; 410 | } 411 | }, 412 | chars: function(chars){ 413 | if (!ignore) { 414 | out(encodeEntities(chars)); 415 | } 416 | } 417 | }; 418 | } 419 | 420 | 421 | // define ngSanitize module and register $sanitize service 422 | angular.module('ngSanitize', []).value('$sanitize', $sanitize); 423 | 424 | /** 425 | * @ngdoc filter 426 | * @name ngSanitize.filter:linky 427 | * @function 428 | * 429 | * @description 430 | * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and 431 | * plain email address links. 432 | * 433 | * Requires the {@link ngSanitize `ngSanitize`} module to be installed. 434 | * 435 | * @param {string} text Input text. 436 | * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. 437 | * @returns {string} Html-linkified text. 438 | * 439 | * @usage 440 | 441 | * 442 | * @example 443 | 444 | 445 | 456 |
457 | Snippet: 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 469 | 472 | 473 | 474 | 475 | 478 | 481 | 482 | 483 | 484 | 485 | 486 | 487 |
FilterSourceRendered
linky filter 467 |
<div ng-bind-html="snippet | linky">
</div>
468 |
470 |
471 |
linky target 476 |
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
477 |
479 |
480 |
no filter
<div ng-bind="snippet">
</div>
488 | 489 | 490 | it('should linkify the snippet with urls', function() { 491 | expect(using('#linky-filter').binding('snippet | linky')). 492 | toBe('Pretty text with some links: ' + 493 | 'http://angularjs.org/, ' + 494 | 'us@somewhere.org, ' + 495 | 'another@somewhere.org, ' + 496 | 'and one more: ftp://127.0.0.1/.'); 497 | }); 498 | 499 | it ('should not linkify snippet without the linky filter', function() { 500 | expect(using('#escaped-html').binding('snippet')). 501 | toBe("Pretty text with some links:\n" + 502 | "http://angularjs.org/,\n" + 503 | "mailto:us@somewhere.org,\n" + 504 | "another@somewhere.org,\n" + 505 | "and one more: ftp://127.0.0.1/."); 506 | }); 507 | 508 | it('should update', function() { 509 | input('snippet').enter('new http://link.'); 510 | expect(using('#linky-filter').binding('snippet | linky')). 511 | toBe('new http://link.'); 512 | expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); 513 | }); 514 | 515 | it('should work with the target property', function() { 516 | expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")). 517 | toBe('http://angularjs.org/'); 518 | }); 519 | 520 | 521 | */ 522 | angular.module('ngSanitize').filter('linky', function() { 523 | var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, 524 | MAILTO_REGEXP = /^mailto:/; 525 | 526 | return function(text, target) { 527 | if (!text) return text; 528 | var match; 529 | var raw = text; 530 | var html = []; 531 | // TODO(vojta): use $sanitize instead 532 | var writer = htmlSanitizeWriter(html); 533 | var url; 534 | var i; 535 | var properties = {}; 536 | if (angular.isDefined(target)) { 537 | properties.target = target; 538 | } 539 | while ((match = raw.match(LINKY_URL_REGEXP))) { 540 | // We can not end in these as they are sometimes found at the end of the sentence 541 | url = match[0]; 542 | // if we did not match ftp/http/mailto then assume mailto 543 | if (match[2] == match[3]) url = 'mailto:' + url; 544 | i = match.index; 545 | writer.chars(raw.substr(0, i)); 546 | properties.href = url; 547 | writer.start('a', properties); 548 | writer.chars(match[0].replace(MAILTO_REGEXP, '')); 549 | writer.end('a'); 550 | raw = raw.substring(i + match[0].length); 551 | } 552 | writer.chars(raw); 553 | return html.join(''); 554 | }; 555 | }); 556 | 557 | 558 | })(window, window.angular); 559 | -------------------------------------------------------------------------------- /static/script/angular-sanitize.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.0-rc.3 3 | (c) 2010-2012 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(m,g,n){'use strict';function h(a){var d={};a=a.split(",");var c;for(c=0;c=c;k--)d.end&&d.end(e[k]);e.length= 7 | c}}var b,f,e=[],l=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(e.last()&&v[e.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(F,"$1").replace(G,"$1");d.chars&&d.chars(p(b));return""}),k("",e.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(w.test(a)){if(b=a.match(w))a=a.replace(b[0],""),f=!1}else if(H.test(a)){if(b=a.match(x))a= 8 | a.substring(b[0].length),b[0].replace(x,k),f=!1}else I.test(a)&&(b=a.match(y))&&(a=a.substring(b[0].length),b[0].replace(y,c),f=!1);f&&(b=a.indexOf("<"),f=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),d.chars&&d.chars(p(f)))}if(a==l)throw J("badparse",a);l=a}k()}function p(a){q.innerHTML=a.replace(//g,">")}function A(a){var d= 9 | !1,c=g.bind(a,a.push);return{start:function(a,b,f){a=g.lowercase(a);!d&&v[a]&&(d=a);d||!0!=B[a]||(c("<"),c(a),g.forEach(b,function(a,b){var d=g.lowercase(b);!0!=L[d]||!0===C[d]&&!a.match(M)||(c(" "),c(b),c('="'),c(z(a)),c('"'))}),c(f?"/>":">"))},end:function(a){a=g.lowercase(a);d||!0!=B[a]||(c(""));a==d&&(d=!1)},chars:function(a){d||c(z(a))}}}var J=g.$$minErr("$sanitize"),y=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,x=/^<\s*\/\s*([\w:-]+)[^>]*>/, 10 | E=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,I=/^]*?)>/i,G=/]/,d=/^mailto:/;return function(c,k){if(!c)return c;var b,f=c,e=[],l=A(e),h,m,n={};g.isDefined(k)&&(n.target=k);for(;b=f.match(a);)h=b[0],b[2]==b[3]&&(h="mailto:"+h),m=b.index,l.chars(f.substr(0,m)),n.href=h,l.start("a",n),l.chars(b[0].replace(d, 13 | "")),l.end("a"),f=f.substring(m+b[0].length);l.chars(f);return e.join("")}})})(window,window.angular); 14 | //# sourceMappingURL=angular-sanitize.min.js.map 15 | -------------------------------------------------------------------------------- /static/script/angular-sanitize.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-sanitize.min.js", 4 | "lineCount":13, 5 | "mappings":"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", 6 | "sources":["angular-sanitize.js"], 7 | "names":["window","angular","undefined","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","chars","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","hiddenPre","innerHTML","innerText","textContent","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","htmlSanitizeWriter","buf","ignore","out","bind","validElements","forEach","key","lkey","validAttrs","uriAttrs","URI_REGEXP","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","$sanitize","join","filter","LINKY_URL_REGEXP","MAILTO_REGEXP","target","raw","writer","url","properties","isDefined","substr","href"] 8 | } 9 | -------------------------------------------------------------------------------- /static/script/sanitize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4 | * Any commits to this file should be reviewed with security in mind. * 5 | * Changes to this file can potentially create security vulnerabilities. * 6 | * An approval from 2 Core members with history of modifying * 7 | * this file is required. * 8 | * * 9 | * Does the change somehow allow for arbitrary javascript to be executed? * 10 | * Or allows for someone to change the prototype of built-in objects? * 11 | * Or gives undesired access to variables likes document or window? * 12 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 13 | 14 | var $sanitizeMinErr = angular.$$minErr('$sanitize'); 15 | 16 | /** 17 | * @ngdoc module 18 | * @name ngSanitize 19 | * @description 20 | * 21 | * # ngSanitize 22 | * 23 | * The `ngSanitize` module provides functionality to sanitize HTML. 24 | * 25 | * 26 | *
27 | * 28 | * See {@link ngSanitize.$sanitize `$sanitize`} for usage. 29 | */ 30 | 31 | /* 32 | * HTML Parser By Misko Hevery (misko@hevery.com) 33 | * based on: HTML Parser By John Resig (ejohn.org) 34 | * Original code by Erik Arvidsson, Mozilla Public License 35 | * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js 36 | * 37 | * // Use like so: 38 | * htmlParser(htmlString, { 39 | * start: function(tag, attrs, unary) {}, 40 | * end: function(tag) {}, 41 | * chars: function(text) {}, 42 | * comment: function(text) {} 43 | * }); 44 | * 45 | */ 46 | 47 | 48 | /** 49 | * @ngdoc service 50 | * @name $sanitize 51 | * @kind function 52 | * 53 | * @description 54 | * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are 55 | * then serialized back to properly escaped html string. This means that no unsafe input can make 56 | * it into the returned string, however, since our parser is more strict than a typical browser 57 | * parser, it's possible that some obscure input, which would be recognized as valid HTML by a 58 | * browser, won't make it through the sanitizer. The input may also contain SVG markup. 59 | * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and 60 | * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. 61 | * 62 | * @param {string} html HTML input. 63 | * @returns {string} Sanitized HTML. 64 | * 65 | * @example 66 | 67 | 68 | 80 |
81 | Snippet: 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 |
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value 99 |
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
100 | </div>
101 |
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
111 |
112 |
113 | 114 | it('should sanitize the html snippet by default', function() { 115 | expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). 116 | toBe('

an html\nclick here\nsnippet

'); 117 | }); 118 | 119 | it('should inline raw snippet if bound to a trusted value', function() { 120 | expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). 121 | toBe("

an html\n" + 122 | "click here\n" + 123 | "snippet

"); 124 | }); 125 | 126 | it('should escape snippet without any filter', function() { 127 | expect(element(by.css('#bind-default div')).getInnerHtml()). 128 | toBe("<p style=\"color:blue\">an html\n" + 129 | "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + 130 | "snippet</p>"); 131 | }); 132 | 133 | it('should update', function() { 134 | element(by.model('snippet')).clear(); 135 | element(by.model('snippet')).sendKeys('new text'); 136 | expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). 137 | toBe('new text'); 138 | expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( 139 | 'new text'); 140 | expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( 141 | "new <b onclick=\"alert(1)\">text</b>"); 142 | }); 143 |
144 |
145 | */ 146 | function $SanitizeProvider() { 147 | this.$get = ['$$sanitizeUri', function($$sanitizeUri) { 148 | return function(html) { 149 | var buf = []; 150 | htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { 151 | return !/^unsafe/.test($$sanitizeUri(uri, isImage)); 152 | })); 153 | return buf.join(''); 154 | }; 155 | }]; 156 | } 157 | 158 | function sanitizeText(chars) { 159 | var buf = []; 160 | var writer = htmlSanitizeWriter(buf, angular.noop); 161 | writer.chars(chars); 162 | return buf.join(''); 163 | } 164 | 165 | 166 | // Regular Expressions for parsing tags and attributes 167 | var START_TAG_REGEXP = 168 | /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/, 169 | END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/, 170 | ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, 171 | BEGIN_TAG_REGEXP = /^/g, 174 | DOCTYPE_REGEXP = /]*?)>/i, 175 | CDATA_REGEXP = //g, 176 | SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 177 | // Match everything outside of normal chars and " (quote character) 178 | NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; 179 | 180 | 181 | // Good source of info about elements and attributes 182 | // http://dev.w3.org/html5/spec/Overview.html#semantics 183 | // http://simon.html5.org/html-elements 184 | 185 | // Safe Void Elements - HTML5 186 | // http://dev.w3.org/html5/spec/Overview.html#void-elements 187 | var voidElements = makeMap("area,br,col,hr,img,wbr"); 188 | 189 | // Elements that you can, intentionally, leave open (and which close themselves) 190 | // http://dev.w3.org/html5/spec/Overview.html#optional-tags 191 | var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), 192 | optionalEndTagInlineElements = makeMap("rp,rt"), 193 | optionalEndTagElements = angular.extend({}, 194 | optionalEndTagInlineElements, 195 | optionalEndTagBlockElements); 196 | 197 | // Safe Block Elements - HTML5 198 | var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + 199 | "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + 200 | "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); 201 | 202 | // Inline Elements - HTML5 203 | var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + 204 | "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + 205 | "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); 206 | 207 | // SVG Elements 208 | // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements 209 | // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. 210 | // They can potentially allow for arbitrary javascript to be executed. See #11290 211 | var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," + 212 | "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," + 213 | "radialGradient,rect,stop,svg,switch,text,title,tspan,use"); 214 | 215 | // Special Elements (can contain anything) 216 | var specialElements = makeMap("script,style"); 217 | 218 | var validElements = angular.extend({}, 219 | voidElements, 220 | blockElements, 221 | inlineElements, 222 | optionalEndTagElements, 223 | svgElements); 224 | 225 | //Attributes that have href and hence need to be sanitized 226 | var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href"); 227 | 228 | var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 229 | 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 230 | 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + 231 | 'scope,scrolling,shape,size,span,start,summary,target,title,type,' + 232 | 'valign,value,vspace,width'); 233 | 234 | // SVG attributes (without "id" and "name" attributes) 235 | // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes 236 | var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + 237 | 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + 238 | 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + 239 | 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + 240 | 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + 241 | 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + 242 | 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + 243 | 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + 244 | 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + 245 | 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + 246 | 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + 247 | 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + 248 | 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + 249 | 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + 250 | 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true); 251 | 252 | var validAttrs = angular.extend({}, 253 | uriAttrs, 254 | svgAttrs, 255 | htmlAttrs); 256 | 257 | function makeMap(str, lowercaseKeys) { 258 | var obj = {}, items = str.split(','), i; 259 | for (i = 0; i < items.length; i++) { 260 | obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true; 261 | } 262 | return obj; 263 | } 264 | 265 | 266 | /** 267 | * @example 268 | * htmlParser(htmlString, { 269 | * start: function(tag, attrs, unary) {}, 270 | * end: function(tag) {}, 271 | * chars: function(text) {}, 272 | * comment: function(text) {} 273 | * }); 274 | * 275 | * @param {string} html string 276 | * @param {object} handler 277 | */ 278 | function htmlParser(html, handler) { 279 | if (typeof html !== 'string') { 280 | if (html === null || typeof html === 'undefined') { 281 | html = ''; 282 | } else { 283 | html = '' + html; 284 | } 285 | } 286 | var index, chars, match, stack = [], last = html, text; 287 | stack.last = function() { return stack[stack.length - 1]; }; 288 | 289 | while (html) { 290 | text = ''; 291 | chars = true; 292 | 293 | // Make sure we're not in a script or style element 294 | if (!stack.last() || !specialElements[stack.last()]) { 295 | 296 | // Comment 297 | if (html.indexOf("", index) === index) { 302 | if (handler.comment) handler.comment(html.substring(4, index)); 303 | html = html.substring(index + 3); 304 | chars = false; 305 | } 306 | // DOCTYPE 307 | } else if (DOCTYPE_REGEXP.test(html)) { 308 | match = html.match(DOCTYPE_REGEXP); 309 | 310 | if (match) { 311 | html = html.replace(match[0], ''); 312 | chars = false; 313 | } 314 | // end tag 315 | } else if (BEGING_END_TAGE_REGEXP.test(html)) { 316 | match = html.match(END_TAG_REGEXP); 317 | 318 | if (match) { 319 | html = html.substring(match[0].length); 320 | match[0].replace(END_TAG_REGEXP, parseEndTag); 321 | chars = false; 322 | } 323 | 324 | // start tag 325 | } else if (BEGIN_TAG_REGEXP.test(html)) { 326 | match = html.match(START_TAG_REGEXP); 327 | 328 | if (match) { 329 | // We only have a valid start-tag if there is a '>'. 330 | if (match[4]) { 331 | html = html.substring(match[0].length); 332 | match[0].replace(START_TAG_REGEXP, parseStartTag); 333 | } 334 | chars = false; 335 | } else { 336 | // no ending tag found --- this piece should be encoded as an entity. 337 | text += '<'; 338 | html = html.substring(1); 339 | } 340 | } 341 | 342 | if (chars) { 343 | index = html.indexOf("<"); 344 | 345 | text += index < 0 ? html : html.substring(0, index); 346 | html = index < 0 ? "" : html.substring(index); 347 | 348 | if (handler.chars) handler.chars(decodeEntities(text)); 349 | } 350 | 351 | } else { 352 | // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w]. 353 | html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), 354 | function(all, text) { 355 | text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); 356 | 357 | if (handler.chars) handler.chars(decodeEntities(text)); 358 | 359 | return ""; 360 | }); 361 | 362 | parseEndTag("", stack.last()); 363 | } 364 | 365 | if (html == last) { 366 | throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + 367 | "of html: {0}", html); 368 | } 369 | last = html; 370 | } 371 | 372 | // Clean up any remaining tags 373 | parseEndTag(); 374 | 375 | function parseStartTag(tag, tagName, rest, unary) { 376 | tagName = angular.lowercase(tagName); 377 | if (blockElements[tagName]) { 378 | while (stack.last() && inlineElements[stack.last()]) { 379 | parseEndTag("", stack.last()); 380 | } 381 | } 382 | 383 | if (optionalEndTagElements[tagName] && stack.last() == tagName) { 384 | parseEndTag("", tagName); 385 | } 386 | 387 | unary = voidElements[tagName] || !!unary; 388 | 389 | if (!unary) { 390 | stack.push(tagName); 391 | } 392 | 393 | var attrs = {}; 394 | 395 | rest.replace(ATTR_REGEXP, 396 | function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { 397 | var value = doubleQuotedValue 398 | || singleQuotedValue 399 | || unquotedValue 400 | || ''; 401 | 402 | attrs[name] = decodeEntities(value); 403 | }); 404 | if (handler.start) handler.start(tagName, attrs, unary); 405 | } 406 | 407 | function parseEndTag(tag, tagName) { 408 | var pos = 0, i; 409 | tagName = angular.lowercase(tagName); 410 | if (tagName) { 411 | // Find the closest opened tag of the same type 412 | for (pos = stack.length - 1; pos >= 0; pos--) { 413 | if (stack[pos] == tagName) break; 414 | } 415 | } 416 | 417 | if (pos >= 0) { 418 | // Close all the open elements, up the stack 419 | for (i = stack.length - 1; i >= pos; i--) 420 | if (handler.end) handler.end(stack[i]); 421 | 422 | // Remove the open elements from the stack 423 | stack.length = pos; 424 | } 425 | } 426 | } 427 | 428 | var hiddenPre=document.createElement("pre"); 429 | /** 430 | * decodes all entities into regular string 431 | * @param value 432 | * @returns {string} A string with decoded entities. 433 | */ 434 | function decodeEntities(value) { 435 | if (!value) { return ''; } 436 | 437 | hiddenPre.innerHTML = value.replace(//g, '>'); 463 | } 464 | 465 | /** 466 | * create an HTML/XML writer which writes to buffer 467 | * @param {Array} buf use buf.jain('') to get out sanitized html string 468 | * @returns {object} in the form of { 469 | * start: function(tag, attrs, unary) {}, 470 | * end: function(tag) {}, 471 | * chars: function(text) {}, 472 | * comment: function(text) {} 473 | * } 474 | */ 475 | function htmlSanitizeWriter(buf, uriValidator) { 476 | var ignore = false; 477 | var out = angular.bind(buf, buf.push); 478 | return { 479 | start: function(tag, attrs, unary) { 480 | tag = angular.lowercase(tag); 481 | if (!ignore && specialElements[tag]) { 482 | ignore = tag; 483 | } 484 | if (!ignore && validElements[tag] === true) { 485 | out('<'); 486 | out(tag); 487 | angular.forEach(attrs, function(value, key) { 488 | var lkey=angular.lowercase(key); 489 | var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); 490 | if (validAttrs[lkey] === true && 491 | (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { 492 | out(' '); 493 | out(key); 494 | out('="'); 495 | out(encodeEntities(value)); 496 | out('"'); 497 | } 498 | }); 499 | out(unary ? '/>' : '>'); 500 | } 501 | }, 502 | end: function(tag) { 503 | tag = angular.lowercase(tag); 504 | if (!ignore && validElements[tag] === true) { 505 | out(''); 508 | } 509 | if (tag == ignore) { 510 | ignore = false; 511 | } 512 | }, 513 | chars: function(chars) { 514 | if (!ignore) { 515 | out(encodeEntities(chars)); 516 | } 517 | } 518 | }; 519 | } 520 | 521 | 522 | // define ngSanitize module and register $sanitize service 523 | angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); 524 | -------------------------------------------------------------------------------- /static/script/tools.js: -------------------------------------------------------------------------------- 1 | function urljoin(url, params){ 2 | param_string = url + "?"; 3 | $.each(params, function(k, v){ 4 | param_string += k + "=" + v + "&"; 5 | }); 6 | param_string = param_string.slice(0, param_string.length - 1) 7 | return param_string 8 | } 9 | -------------------------------------------------------------------------------- /static/style/dashboard.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Base structure 3 | */ 4 | 5 | /* Move down content because we have a fixed navbar that is 50px tall */ 6 | body { 7 | padding-top: 50px; 8 | } 9 | 10 | 11 | /* 12 | * Global add-ons 13 | */ 14 | 15 | .sub-header { 16 | padding-bottom: 10px; 17 | border-bottom: 1px solid #eee; 18 | } 19 | 20 | /* 21 | * Top navigation 22 | * Hide default border to remove 1px line. 23 | */ 24 | .navbar-fixed-top { 25 | border: 0; 26 | } 27 | 28 | /* 29 | * Sidebar 30 | */ 31 | 32 | /* Hide for mobile, show later */ 33 | .sidebar { 34 | display: none; 35 | } 36 | @media (min-width: 768px) { 37 | .sidebar { 38 | position: fixed; 39 | top: 51px; 40 | bottom: 0; 41 | left: 0; 42 | z-index: 1000; 43 | display: block; 44 | padding: 20px; 45 | overflow-x: hidden; 46 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ 47 | background-color: #f5f5f5; 48 | border-right: 1px solid #eee; 49 | } 50 | } 51 | 52 | /* Sidebar navigation */ 53 | .nav-sidebar { 54 | margin-right: -21px; /* 20px padding + 1px border */ 55 | margin-bottom: 20px; 56 | margin-left: -20px; 57 | } 58 | .nav-sidebar > li > a { 59 | padding-right: 20px; 60 | padding-left: 20px; 61 | } 62 | .nav-sidebar > .active > a, 63 | .nav-sidebar > .active > a:hover, 64 | .nav-sidebar > .active > a:focus { 65 | color: #fff; 66 | background-color: #428bca; 67 | } 68 | 69 | 70 | /* 71 | * Main content 72 | */ 73 | 74 | .main { 75 | padding: 20px; 76 | } 77 | @media (min-width: 768px) { 78 | .main { 79 | padding-right: 40px; 80 | padding-left: 40px; 81 | } 82 | } 83 | .main .page-header { 84 | margin-top: 0; 85 | } 86 | 87 | 88 | /* 89 | * Placeholder dashboard ideas 90 | */ 91 | 92 | .placeholders { 93 | margin-bottom: 30px; 94 | text-align: center; 95 | } 96 | .placeholders h4 { 97 | margin-bottom: 0; 98 | } 99 | .placeholder { 100 | margin-bottom: 20px; 101 | } 102 | .placeholder img { 103 | display: inline-block; 104 | border-radius: 50%; 105 | } 106 | -------------------------------------------------------------------------------- /template/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 观云·网盘搜索·后台管理 12 | 13 | 14 | 15 | 16 | 17 | 18 | 39 | 40 | 41 | 53 |
54 |
55 | 63 |
64 |

用户统计 65 | 下载CSV 66 |

67 | 68 |

资源统计 69 | 下载CSV 70 |

71 | 72 |

流量统计 73 | 下载CSV 74 |

75 | 76 |
77 |
78 |
79 |
80 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
标记时间发送人标题操作
未阅2015-05-29 01:40liqueur敏感词列表详情
已阅2015-05-29 01:40liqueur敏感词列表详情
108 | 110 |
111 | 112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | 123 | 206 | 207 | -------------------------------------------------------------------------------- /template/donate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 观云·网盘搜索·捐赠 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 |
19 |
20 | 25 |
26 |
27 |
28 |
29 | 30 |

每一枚硬币都对观云意义重大哦

31 |

(image via 萌娘百科)

32 |
33 |

非常感谢您打开捐赠页面,无论您是否准备捐款,由衷感谢您对于观云的支持!

34 |

观云最开始只是一个大学生心血来潮的爬虫脚本,目的是弥补百度云网盘的搜索功能,让网盘资源真正地共享。虽然目前只支持百度云盘搜索,但希望随着日后不断的改善,能够提供其它类型的网盘搜索服务。

35 |

目前观云搜索服务运行于阿里云香港主机,配置 CPU 1核,内存 1G,数据盘 20G,带宽 1Mbps。每月需支付117元人民币以维持服务器的正常运行,每年花费60元人民币维护万网注册.me域名。尽管这样,作为一个大学生对此还是囊中羞涩。

36 |

至此,如果您有意愿捐助观云,可以用支付宝钱包扫描下面二维码进行捐助,您会被记录在捐赠者名单中,您的每一笔捐赠具体用途都会在财报中详细说明。支付即时到帐,量力而行。感激不尽!

37 | 38 |

via Liqueur

39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 | 125 | 126 | -------------------------------------------------------------------------------- /template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 网盘搜索·Beta 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 48 | 49 | 67 |
68 |
69 |

网盘搜索·Beta

70 |
至今收录 {$ resource_count $} 个资源
71 | 72 |
73 |
74 |
75 | 77 | 78 | 79 | 80 |
81 |
82 |
83 |
84 |
85 | 86 |
87 | 103 |
    104 |
  • 105 | 找到 {$ total_count $} 个结果 106 |
  • 107 |
  • 108 | 搜索耗时 {$ cost_time $} 109 |
  • 110 |
111 |
    112 |
  • 113 |

    114 | 115 | 分享时间: span{$ item.feed_time $} 116 | 文件大小: {$ item.size $} 117 | 浏览次数: {$ item.v_cnt $} 118 | 下载次数: {$ item.d_cnt $} 119 | 保存次数: {$ item.t_cnt $} 120 | 121 |

    {$ item.url $}

    122 |
  • 123 |
  • 124 |

    Σ( ° △ °|||)︴没有找到资源

    125 |
      126 |
    • 增加关键字
    • 127 |
    • 128 | 反馈作者 129 |
    • 130 |
    131 |
  • 132 |
  • 133 |
    135 |
    136 |
    137 | 139 |
    140 |
    141 | 143 |
    144 |
    145 | 第 / {$ paging.page_num $} 页 147 |
    148 |
    149 | 151 |
    152 |
    153 | 155 |
    156 |
    157 |
  • 158 |
159 |
160 | 178 |
179 | 180 | 257 | 258 | -------------------------------------------------------------------------------- /template/testchinese.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | {{ content }} 14 |
15 | 16 | 17 |
18 | 结果: 19 | {% if items %} 20 | {% for item in items %} 21 |
    22 |
  • {% raw item %}
  • 23 |
24 | {% end %} 25 | {% end %} 26 | 27 | 28 | -------------------------------------------------------------------------------- /tools.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | 3 | import logging 4 | from logging.handlers import TimedRotatingFileHandler 5 | from os.path import join, dirname, abspath 6 | from settings import LOG_DIR 7 | 8 | def gen_logger(filename, filemode): 9 | format = '[%(filename)s:%(lineno)d %(asctime)s] %(levelname)s %(message)s' 10 | filename = filename.rsplit('.', 1)[0] 11 | filename = '.'.join([filename, 'log']) 12 | filename = join(LOG_DIR, filename) 13 | logging.basicConfig( 14 | level=logging.DEBUG, 15 | filename=filename, 16 | filemode=filemode, 17 | format=format, 18 | ) 19 | 20 | # rotate = TimedRotatingFileHandler(filename, when="h", interval=1, backupCount=7) 21 | # rotate.setFormatter(formatter) 22 | # logger.addHandler(rotate) 23 | 24 | formatter = logging.Formatter(format) 25 | logger = logging.getLogger(filename) 26 | console = logging.StreamHandler() 27 | console.setLevel(logging.DEBUG) 28 | console.setFormatter(formatter) 29 | logger.addHandler(console) 30 | 31 | return logger 32 | 33 | def pagination(seq, page, page_size): 34 | r1, r2 = divmod(len(seq), page_size) 35 | page_num = r1 + int(r2 > 0) 36 | if page > page_num: 37 | page = 1 38 | 39 | objects = seq[(page - 1) * page_size:page * page_size] 40 | previous_page = page - 1 if page > 1 else None 41 | next_page = page + 1 if page < page_num else None 42 | is_empty = len(objects) == 0 43 | 44 | return dict(objects=objects, 45 | page=page, 46 | page_num=page_num, 47 | previous_page=previous_page, 48 | next_page=next_page, 49 | is_empty=is_empty) 50 | -------------------------------------------------------------------------------- /traffic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding:utf-8 3 | 4 | from __future__ import unicode_literals 5 | from settings import db 6 | from time import time 7 | 8 | _time = int(time()) 9 | count = db.monitor.find_one()['traffic'] 10 | db.traffic_log.insert({'ctime':_time, 'count':count}) 11 | --------------------------------------------------------------------------------