Repository: SecurityPaper/SecurityPaper-web Branch: master Commit: cbe1d19c3b80 Files: 122 Total size: 1.8 MB Directory structure: gitextract_uoldwxkc/ ├── .gitignore ├── LICENSE ├── README.md ├── SecurityPaper-themes/ │ ├── 404.html │ ├── __init__.py │ ├── assets/ │ │ ├── fonts/ │ │ │ ├── font-awesome.css │ │ │ └── material-icons.css │ │ ├── javascripts/ │ │ │ ├── application.js │ │ │ ├── lunr/ │ │ │ │ ├── lunr.da.js │ │ │ │ ├── lunr.de.js │ │ │ │ ├── lunr.du.js │ │ │ │ ├── lunr.es.js │ │ │ │ ├── lunr.fi.js │ │ │ │ ├── lunr.fr.js │ │ │ │ ├── lunr.hu.js │ │ │ │ ├── lunr.it.js │ │ │ │ ├── lunr.jp.js │ │ │ │ ├── lunr.multi.js │ │ │ │ ├── lunr.no.js │ │ │ │ ├── lunr.pt.js │ │ │ │ ├── lunr.ro.js │ │ │ │ ├── lunr.ru.js │ │ │ │ ├── lunr.stemmer.support.js │ │ │ │ ├── lunr.sv.js │ │ │ │ ├── lunr.tr.js │ │ │ │ └── tinyseg.js │ │ │ └── modernizr.js │ │ └── stylesheets/ │ │ ├── application-palette.css │ │ └── application.css │ ├── base.html │ ├── main.html │ ├── mkdocs_theme.yml │ └── partials/ │ ├── footer.html │ ├── header.html │ ├── hero.html │ ├── integrations/ │ │ ├── analytics.html │ │ └── disqus.html │ ├── language/ │ │ ├── ar.html │ │ ├── ca.html │ │ ├── cs.html │ │ ├── da.html │ │ ├── de.html │ │ ├── en.html │ │ ├── es.html │ │ ├── fa.html │ │ ├── fi.html │ │ ├── fr.html │ │ ├── gl.html │ │ ├── he.html │ │ ├── hi.html │ │ ├── hr.html │ │ ├── hu.html │ │ ├── id.html │ │ ├── it.html │ │ ├── ja.html │ │ ├── kr.html │ │ ├── nl.html │ │ ├── no.html │ │ ├── pl.html │ │ ├── pt.html │ │ ├── ru.html │ │ ├── sh.html │ │ ├── sk.html │ │ ├── sr.html │ │ ├── sv.html │ │ ├── tr.html │ │ ├── uk.html │ │ ├── vi.html │ │ ├── zh-Hant.html │ │ ├── zh-TW.html │ │ └── zh.html │ ├── language.html │ ├── nav-item.html │ ├── nav.html │ ├── palette.html │ ├── search.html │ ├── social.html │ ├── source.html │ ├── tabs-item.html │ ├── tabs.html │ ├── toc-item.html │ └── toc.html ├── docs/ │ ├── 1.SDL介绍/ │ │ ├── 1-什么是SDL.md │ │ ├── 2-企业为什么需求SDL.md │ │ ├── 3-哪些企业需要SDL.md │ │ └── 4-SDL所带来的优缺点.md │ ├── 2.SDL规范文档/ │ │ ├── 1-安全设计Checklist.md │ │ ├── 10-SDL上线规定文档.md │ │ ├── 11-web应用安全业务自查checklist.md │ │ ├── 2-php安全编码规范.md │ │ ├── 3-java安全编码规范.md │ │ ├── 4-python安全编码规范.md │ │ ├── 5-nodejs安全编码规范.md │ │ ├── 6-移动安全规范.md │ │ ├── 7-产品设计开发最佳实践.md │ │ ├── 8-常见协议安全开发实践.md │ │ └── 9-MySQL安全配置.md │ ├── 3.SDL落地方案/ │ │ ├── 1-安全培训.md │ │ ├── 2-需求评估.md │ │ ├── 3-产品设计.md │ │ ├── 4-代码编写.md │ │ ├── 5-渗透测试.md │ │ ├── 6-上线发布.md │ │ └── 7-应急响应.md │ ├── 4.构建企业安全/ │ │ ├── 1-内功修炼第一步-挖漏洞.md │ │ ├── 2-内功修炼第二步-引起重视.md │ │ ├── 3-互联网安全运营的思考.md │ │ ├── 4-如何利用Flink实现超大规模用户行为分析.md │ │ └── 5-APT 攻击基础科普.md │ ├── 5.附录/ │ │ ├── 01.相关术语.md │ │ ├── 02.文档变更规范.md │ │ ├── 03.GitHub工作流.md │ │ └── 04.NAXSI安装测试与简介.md │ ├── 6.Project/ │ │ ├── 1-内部钓鱼系统.md │ │ ├── 2-工作流自动化代码审计.md │ │ └── 3-泰式感知.md │ ├── 7.安全前瞻/ │ │ └── 1-BeyondCorp-以全新方式保障企业安全.md │ ├── _headers │ ├── index.md │ └── update.md ├── mkdocs.yml └── requirements.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ site/ .DS_Store ================================================ FILE: LICENSE ================================================ Copyright (c) Anti 996 License Version 1.0 (Draft) Permission is hereby granted to any individual or legal entity obtaining a copy of this licensed work (including the source code, documentation and/or related items, hereinafter collectively referred to as the "licensed work"), free of charge, to deal with the licensed work for any purpose, including without limitation, the rights to use, reproduce, modify, prepare derivative works of, distribute, publish and sublicense the licensed work, subject to the following conditions: 1. The individual or the legal entity must conspicuously display, without modification, this License and the notice on each redistributed or derivative copy of the Licensed Work. 2. The individual or the legal entity must strictly comply with all applicable laws, regulations, rules and standards of the jurisdiction relating to labor and employment where the individual is physically located or where the individual was born or naturalized; or where the legal entity is registered or is operating (whichever is stricter). In case that the jurisdiction has no such laws, regulations, rules and standards or its laws, regulations, rules and standards are unenforceable, the individual or the legal entity are required to comply with Core International Labor Standards. 3. The individual or the legal entity shall not induce or force its employee(s), whether full-time or part-time, or its independent contractor(s), in any methods, to agree in oral or written form, to directly or indirectly restrict, weaken or relinquish his or her rights or remedies under such laws, regulations, rules and standards relating to labor and employment as mentioned above, no matter whether such written or oral agreement are enforceable under the laws of the said jurisdiction, nor shall such individual or the legal entity limit, in any methods, the rights of its employee(s) or independent contractor(s) from reporting or complaining to the copyright holder or relevant authorities monitoring the compliance of the license about its violation(s) of the said license. THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. ================================================ FILE: README.md ================================================ ## SecurityPaper 所有文档都来自中国互联网一线安全工程师编写整理 ## 官网 ``` https://www.SecurityPaper.org ``` 官网状态:[![Build Status](https://travis-ci.com/SecurityPaper/SecurityPaper-web.svg?branch=master)](https://travis-ci.com/SecurityPaper/SecurityPaper-web) ## 下载文档方法 clone 项目到本地 所有文档都在**docs**目录下,以markdown文件进行存储,可以直接保存 ## 提交文章和改进 请参考git工作流方法 fork项目到自己账户,修改后提交给主分支,审核后即可展示。 提交可以多种方式,如web、命令、客户端,这里演示web提交方式 提交SDL落地方案-产品设计 1. 选择相应的文件,所有文档都在**_post**目录下 ``` SecurityPaper-web/_posts/3.SDL落地方案/2018-08-17-SDL-3-产品设计.md ``` 选择**edit**或者**create new file**,文件名必须要符合: ```YEAR-MONTH-DAY-title.md``` ![图片1](https://github.com/SecurityPaper/SecurityPaper-web/raw/master/docs/images/2018/10/github/1.png) 2. 编辑文档 所有博客文章顶部必须有一段YAML头信息(YAML front- matter),文章可以使用markdown格式编写 ``` --- date: 2018-08-17 title: 03.产品设计 categories: - 3.SDL落地方案 description: 和研发同学进行产品设计定框架部分应该怎么去执行 type: Document --- ``` 编辑完成之后点击**commit changes**(同命令```git add . && git commit -m "添加产品设计" && git pusht origin master```) ![图片2](https://github.com/SecurityPaper/SecurityPaper-web/raw/master/docs/images/2018/10/github/2.png) 3. 提交pull请求 点击**New pull request** ![图片3](https://github.com/SecurityPaper/SecurityPaper-web/raw/master/docs/images/2018/10/github/3.png) 检查没有问题,点击**Create pull request** ![图片4](https://github.com/SecurityPaper/SecurityPaper-web/raw/master/docs/images/2018/10/github/4.png) 提交成功,等待管理员**Merge**之后就成功了 ![图片5](https://github.com/SecurityPaper/SecurityPaper-web/raw/master/docs/images/2018/10/github/5.png) ## 署名 原则上对文章修改后即可进行署名在协作者添加上自己的ID。 ## About页面变更 需要对网站文档进行提交建议以及文档改进或者文档编写方可在About页面添加自己ID 排序需要按照字母顺序排序。 ================================================ FILE: SecurityPaper-themes/404.html ================================================ {% extends "base.html" %} {% block content %}

404 - Not found

{% endblock %} ================================================ FILE: SecurityPaper-themes/__init__.py ================================================ ================================================ FILE: SecurityPaper-themes/assets/fonts/font-awesome.css ================================================ /*! * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url("specimen/FontAwesome.woff2") format("woff2"),url("specimen/FontAwesome.woff") format("woff"),url("specimen/FontAwesome.ttf") format("truetype")}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} ================================================ FILE: SecurityPaper-themes/assets/fonts/material-icons.css ================================================ /*! * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE * DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND * LIMITATIONS UNDER THE LICENSE. */@font-face{font-family:"Material Icons";font-style:normal;font-weight:400;src:local("Material Icons"),local("MaterialIcons-Regular"),url("specimen/MaterialIcons-Regular.woff2") format("woff2"),url("specimen/MaterialIcons-Regular.woff") format("woff"),url("specimen/MaterialIcons-Regular.ttf") format("truetype")} ================================================ FILE: SecurityPaper-themes/assets/javascripts/application.js ================================================ (function(e, a) { for(var i in a) e[i] = a[i]; }(window, /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 6); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; exports.__esModule = true; /* * Copyright (c) 2016-2018 Martin Donath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /* ---------------------------------------------------------------------------- * Module * ------------------------------------------------------------------------- */ /* eslint-disable no-underscore-dangle */ exports.default = /* JSX */{ /** * Create a native DOM node from JSX's intermediate representation * * @param {string} tag - Tag name * @param {?Object} properties - Properties * @param {Array>} * children - Child nodes * @return {HTMLElement} Native DOM node */ createElement: function createElement(tag, properties) { var el = document.createElement(tag); /* Set all properties */ if (properties) Array.prototype.forEach.call(Object.keys(properties), function (attr) { el.setAttribute(attr, properties[attr]); }); /* Iterate child nodes */ var iterateChildNodes = function iterateChildNodes(nodes) { Array.prototype.forEach.call(nodes, function (node) { /* Directly append text content */ if (typeof node === "string" || typeof node === "number") { el.textContent += node; /* Recurse, if we got an array */ } else if (Array.isArray(node)) { iterateChildNodes(node); /* Append raw HTML */ } else if (typeof node.__html !== "undefined") { el.innerHTML += node.__html; /* Append regular nodes */ } else if (node instanceof Node) { el.appendChild(node); } }); }; /* Iterate child nodes and return element */ for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { children[_key - 2] = arguments[_key]; } iterateChildNodes(children); return el; } }; module.exports = exports.default; /***/ }), /* 1 */ /***/ (function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || Function("return this")() || (1,eval)("this"); } catch(e) { // This works if the window reference is available if(typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }), /* 2 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); var index = typeof fetch=='function' ? fetch.bind() : function(url, options) { options = options || {}; return new Promise( function (resolve, reject) { var request = new XMLHttpRequest(); request.open(options.method || 'get', url, true); for (var i in options.headers) { request.setRequestHeader(i, options.headers[i]); } request.withCredentials = options.credentials=='include'; request.onload = function () { resolve(response()); }; request.onerror = reject; request.send(options.body || null); function response() { var keys = [], all = [], headers = {}, header; request.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, function (m, key, value) { keys.push(key = key.toLowerCase()); all.push([key, value]); header = headers[key]; headers[key] = header ? (header + "," + value) : value; }); return { ok: (request.status/100|0) == 2, // 200-299 status: request.status, statusText: request.statusText, url: request.responseURL, clone: response, text: function () { return Promise.resolve(request.responseText); }, json: function () { return Promise.resolve(request.responseText).then(JSON.parse); }, blob: function () { return Promise.resolve(new Blob([request.response])); }, headers: { keys: function () { return keys; }, entries: function () { return all; }, get: function (n) { return headers[n.toLowerCase()]; }, has: function (n) { return n.toLowerCase() in headers; } } }; } }); }; /* harmony default export */ __webpack_exports__["default"] = (index); //# sourceMappingURL=unfetch.es.js.map /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; exports.__esModule = true; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /* * Copyright (c) 2016-2018 Martin Donath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /* ---------------------------------------------------------------------------- * Class * ------------------------------------------------------------------------- */ var Listener = function () { /** * Generic event listener * * @constructor * * @property {(Array)} els_ - Event targets * @property {Object} handler_- Event handlers * @property {Array} events_ - Event names * @property {Function} update_ - Update handler * * @param {?(string|EventTarget|NodeList)} els - * Selector or Event targets * @param {(string|Array)} events - Event names * @param {(Object|Function)} handler - Handler to be invoked */ function Listener(els, events, handler) { var _this = this; _classCallCheck(this, Listener); this.els_ = Array.prototype.slice.call(typeof els === "string" ? document.querySelectorAll(els) : [].concat(els)); /* Set handler as function or directly as object */ this.handler_ = typeof handler === "function" ? { update: handler } : handler; /* Initialize event names and update handler */ this.events_ = [].concat(events); this.update_ = function (ev) { return _this.handler_.update(ev); }; } /** * Register listener for all relevant events */ Listener.prototype.listen = function listen() { var _this2 = this; this.els_.forEach(function (el) { _this2.events_.forEach(function (event) { el.addEventListener(event, _this2.update_, false); }); }); /* Execute setup handler, if implemented */ if (typeof this.handler_.setup === "function") this.handler_.setup(); }; /** * Unregister listener for all relevant events */ Listener.prototype.unlisten = function unlisten() { var _this3 = this; this.els_.forEach(function (el) { _this3.events_.forEach(function (event) { el.removeEventListener(event, _this3.update_); }); }); /* Execute reset handler, if implemented */ if (typeof this.handler_.reset === "function") this.handler_.reset(); }; return Listener; }(); exports.default = Listener; /***/ }), /* 4 */, /* 5 */, /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(JSX) { exports.__esModule = true; exports.app = undefined; __webpack_require__(7); __webpack_require__(8); __webpack_require__(9); __webpack_require__(10); __webpack_require__(11); __webpack_require__(12); __webpack_require__(13); var _promisePolyfill = __webpack_require__(14); var _promisePolyfill2 = _interopRequireDefault(_promisePolyfill); var _clipboard = __webpack_require__(19); var _clipboard2 = _interopRequireDefault(_clipboard); var _fastclick = __webpack_require__(20); var _fastclick2 = _interopRequireDefault(_fastclick); var _Material = __webpack_require__(21); var _Material2 = _interopRequireDefault(_Material); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* * Copyright (c) 2016-2018 Martin Donath * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ window.Promise = window.Promise || _promisePolyfill2.default; /* ---------------------------------------------------------------------------- * Dependencies * ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- * Polyfills * ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- * Functions * ------------------------------------------------------------------------- */ /** * Return the meta tag value for the given key * * @param {string} key - Meta name * * @return {string} Meta content value */ var translate = function translate(key) { var meta = document.getElementsByName("lang:" + key)[0]; if (!(meta instanceof HTMLMetaElement)) throw new ReferenceError(); return meta.content; }; /* ---------------------------------------------------------------------------- * Application * ------------------------------------------------------------------------- */ /** * Initialize Material for MkDocs * * @param {Object} config - Configuration */ function initialize(config) { // eslint-disable-line func-style /* Initialize Modernizr and FastClick */ new _Material2.default.Event.Listener(document, "DOMContentLoaded", function () { if (!(document.body instanceof HTMLElement)) throw new ReferenceError(); /* Attach FastClick to mitigate 300ms delay on touch devices */ _fastclick2.default.attach(document.body); /* Test for iOS */ Modernizr.addTest("ios", function () { return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g); }); /* Wrap all data tables for better overflow scrolling */ var tables = document.querySelectorAll("table:not([class])"); // TODO: this is JSX, we should rename the file Array.prototype.forEach.call(tables, function (table) { var wrap = JSX.createElement( "div", { "class": "md-typeset__scrollwrap" }, JSX.createElement("div", { "class": "md-typeset__table" }) ); if (table.nextSibling) { table.parentNode.insertBefore(wrap, table.nextSibling); } else { table.parentNode.appendChild(wrap); } wrap.children[0].appendChild(table); }); /* Clipboard integration */ if (_clipboard2.default.isSupported()) { var blocks = document.querySelectorAll(".codehilite > pre, pre > code"); Array.prototype.forEach.call(blocks, function (block, index) { var id = "__code_" + index; /* Create button with message container */ var button = JSX.createElement( "button", { "class": "md-clipboard", title: translate("clipboard.copy"), "data-clipboard-target": "#" + id + " pre, #" + id + " code" }, JSX.createElement("span", { "class": "md-clipboard__message" }) ); /* Link to block and insert button */ var parent = block.parentNode; parent.id = id; parent.insertBefore(button, block); }); /* Initialize Clipboard listener */ var copy = new _clipboard2.default(".md-clipboard"); /* Success handler */ copy.on("success", function (action) { var message = action.trigger.querySelector(".md-clipboard__message"); if (!(message instanceof HTMLElement)) throw new ReferenceError(); /* Clear selection and reset debounce logic */ action.clearSelection(); if (message.dataset.mdTimer) clearTimeout(parseInt(message.dataset.mdTimer, 10)); /* Set message indicating success and show it */ message.classList.add("md-clipboard__message--active"); message.innerHTML = translate("clipboard.copied"); /* Hide message after two seconds */ message.dataset.mdTimer = setTimeout(function () { message.classList.remove("md-clipboard__message--active"); message.dataset.mdTimer = ""; }, 2000).toString(); }); } /* Polyfill details/summary functionality */ if (!Modernizr.details) { var _blocks = document.querySelectorAll("details > summary"); Array.prototype.forEach.call(_blocks, function (summary) { summary.addEventListener("click", function (ev) { var details = ev.target.parentNode; if (details.hasAttribute("open")) { details.removeAttribute("open"); } else { details.setAttribute("open", ""); } }); }); } /* Open details after anchor jump */ var details = function details() { if (document.location.hash) { var el = document.getElementById(document.location.hash.substring(1)); if (!el) return; /* Walk up as long as we're not in a details tag */ var parent = el.parentNode; while (parent && !(parent instanceof HTMLDetailsElement)) { parent = parent.parentNode; } /* If there's a details tag, open it */ if (parent && !parent.open) { parent.open = true; /* Force reload, so the viewport repositions */ var loc = location.hash; location.hash = " "; location.hash = loc; } } }; window.addEventListener("hashchange", details); details(); /* Force 1px scroll offset to trigger overflow scrolling */ if (Modernizr.ios) { var scrollable = document.querySelectorAll("[data-md-scrollfix]"); Array.prototype.forEach.call(scrollable, function (item) { item.addEventListener("touchstart", function () { var top = item.scrollTop; /* We're at the top of the container */ if (top === 0) { item.scrollTop = 1; /* We're at the bottom of the container */ } else if (top + item.offsetHeight === item.scrollHeight) { item.scrollTop = top - 1; } }); }); } }).listen(); /* Component: header shadow toggle */ new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Header.Shadow("[data-md-component=container]", "[data-md-component=header]")).listen(); /* Component: header title toggle */ new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Header.Title("[data-md-component=title]", ".md-typeset h1")).listen(); /* Component: hero visibility toggle */ if (document.querySelector("[data-md-component=hero]")) new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Tabs.Toggle("[data-md-component=hero]")).listen(); /* Component: tabs visibility toggle */ if (document.querySelector("[data-md-component=tabs]")) new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Tabs.Toggle("[data-md-component=tabs]")).listen(); /* Component: sidebar with navigation */ new _Material2.default.Event.MatchMedia("(min-width: 1220px)", new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Sidebar.Position("[data-md-component=navigation]", "[data-md-component=header]"))); /* Component: sidebar with table of contents (missing on 404 page) */ if (document.querySelector("[data-md-component=toc]")) new _Material2.default.Event.MatchMedia("(min-width: 960px)", new _Material2.default.Event.Listener(window, ["scroll", "resize", "orientationchange"], new _Material2.default.Sidebar.Position("[data-md-component=toc]", "[data-md-component=header]"))); /* Component: link blurring for table of contents */ new _Material2.default.Event.MatchMedia("(min-width: 960px)", new _Material2.default.Event.Listener(window, "scroll", new _Material2.default.Nav.Blur("[data-md-component=toc] [href]"))); /* Component: collapsible elements for navigation */ var collapsibles = document.querySelectorAll("[data-md-component=collapsible]"); Array.prototype.forEach.call(collapsibles, function (collapse) { new _Material2.default.Event.MatchMedia("(min-width: 1220px)", new _Material2.default.Event.Listener(collapse.previousElementSibling, "click", new _Material2.default.Nav.Collapse(collapse))); }); /* Component: active pane monitor for iOS scrolling fixes */ new _Material2.default.Event.MatchMedia("(max-width: 1219px)", new _Material2.default.Event.Listener("[data-md-component=navigation] [data-md-toggle]", "change", new _Material2.default.Nav.Scrolling("[data-md-component=navigation] nav"))); /* Initialize search, if available */ if (document.querySelector("[data-md-component=search]")) { /* Component: search body lock for mobile */ new _Material2.default.Event.MatchMedia("(max-width: 959px)", new _Material2.default.Event.Listener("[data-md-toggle=search]", "change", new _Material2.default.Search.Lock("[data-md-toggle=search]"))); /* Component: search results */ new _Material2.default.Event.Listener("[data-md-component=query]", ["focus", "keyup", "change"], new _Material2.default.Search.Result("[data-md-component=result]", function () { return fetch(config.url.base + "/" + (config.version < "0.17" ? "mkdocs" : "search") + "/search_index.json", { credentials: "same-origin" }).then(function (response) { return response.json(); }).then(function (data) { return data.docs.map(function (doc) { doc.location = config.url.base + "/" + doc.location; return doc; }); }); })).listen(); /* Listener: focus input after form reset */ new _Material2.default.Event.Listener("[data-md-component=reset]", "click", function () { setTimeout(function () { var query = document.querySelector("[data-md-component=query]"); if (!(query instanceof HTMLInputElement)) throw new ReferenceError(); query.focus(); }, 10); }).listen(); /* Listener: focus input after opening search */ new _Material2.default.Event.Listener("[data-md-toggle=search]", "change", function (ev) { setTimeout(function (toggle) { if (!(toggle instanceof HTMLInputElement)) throw new ReferenceError(); if (toggle.checked) { var query = document.querySelector("[data-md-component=query]"); if (!(query instanceof HTMLInputElement)) throw new ReferenceError(); query.focus(); } }, 400, ev.target); }).listen(); /* Listener: open search on focus */ new _Material2.default.Event.MatchMedia("(min-width: 960px)", new _Material2.default.Event.Listener("[data-md-component=query]", "focus", function () { var toggle = document.querySelector("[data-md-toggle=search]"); if (!(toggle instanceof HTMLInputElement)) throw new ReferenceError(); if (!toggle.checked) { toggle.checked = true; toggle.dispatchEvent(new CustomEvent("change")); } })); /* Listener: keyboard handlers */ // eslint-disable-next-line complexity new _Material2.default.Event.Listener(window, "keydown", function (ev) { // TODO: split up into component to reduce complexity var toggle = document.querySelector("[data-md-toggle=search]"); if (!(toggle instanceof HTMLInputElement)) throw new ReferenceError(); var query = document.querySelector("[data-md-component=query]"); if (!(query instanceof HTMLInputElement)) throw new ReferenceError(); /* Abort if meta key (macOS) or ctrl key (Windows) is pressed */ if (ev.metaKey || ev.ctrlKey) return; /* Search is open */ if (toggle.checked) { /* Enter: prevent form submission */ if (ev.keyCode === 13) { if (query === document.activeElement) { ev.preventDefault(); /* Go to current active/focused link */ var focus = document.querySelector("[data-md-component=search] [href][data-md-state=active]"); if (focus instanceof HTMLLinkElement) { window.location = focus.getAttribute("href"); /* Close search */ toggle.checked = false; toggle.dispatchEvent(new CustomEvent("change")); query.blur(); } } /* Escape or Tab: close search */ } else if (ev.keyCode === 9 || ev.keyCode === 27) { toggle.checked = false; toggle.dispatchEvent(new CustomEvent("change")); query.blur(); /* Horizontal arrows and backspace: focus input */ } else if ([8, 37, 39].indexOf(ev.keyCode) !== -1) { if (query !== document.activeElement) query.focus(); /* Vertical arrows: select previous or next search result */ } else if ([38, 40].indexOf(ev.keyCode) !== -1) { var key = ev.keyCode; /* Retrieve all results */ var links = Array.prototype.slice.call(document.querySelectorAll("[data-md-component=query], [data-md-component=search] [href]")); /* Retrieve current active/focused result */ var _focus = links.find(function (link) { if (!(link instanceof HTMLElement)) throw new ReferenceError(); return link.dataset.mdState === "active"; }); if (_focus) _focus.dataset.mdState = ""; /* Calculate index depending on direction, add length to form ring */ var index = Math.max(0, (links.indexOf(_focus) + links.length + (key === 38 ? -1 : +1)) % links.length); /* Set active state and focus */ if (links[index]) { links[index].dataset.mdState = "active"; links[index].focus(); } /* Prevent scrolling of page */ ev.preventDefault(); ev.stopPropagation(); /* Return false prevents the cursor position from changing */ return false; } /* Search is closed and we're not inside a form */ } else if (document.activeElement && !document.activeElement.form) { /* F/S: Open search if not in input field */ if (ev.keyCode === 70 || ev.keyCode === 83) { query.focus(); ev.preventDefault(); } } }).listen(); /* Listener: focus query if in search is open and character is typed */ new _Material2.default.Event.Listener(window, "keypress", function () { var toggle = document.querySelector("[data-md-toggle=search]"); if (!(toggle instanceof HTMLInputElement)) throw new ReferenceError(); if (toggle.checked) { var query = document.querySelector("[data-md-component=query]"); if (!(query instanceof HTMLInputElement)) throw new ReferenceError(); if (query !== document.activeElement) query.focus(); } }).listen(); } /* Listener: handle tabbing context for better accessibility */ new _Material2.default.Event.Listener(document.body, "keydown", function (ev) { if (ev.keyCode === 9) { var labels = document.querySelectorAll("[data-md-component=navigation] .md-nav__link[for]:not([tabindex])"); Array.prototype.forEach.call(labels, function (label) { if (label.offsetHeight) label.tabIndex = 0; }); } }).listen(); /* Listener: reset tabbing behavior */ new _Material2.default.Event.Listener(document.body, "mousedown", function () { var labels = document.querySelectorAll("[data-md-component=navigation] .md-nav__link[tabindex]"); Array.prototype.forEach.call(labels, function (label) { label.removeAttribute("tabIndex"); }); }).listen(); document.body.addEventListener("click", function () { if (document.body.dataset.mdState === "tabbing") document.body.dataset.mdState = ""; }); /* Listener: close drawer when anchor links are clicked */ new _Material2.default.Event.MatchMedia("(max-width: 959px)", new _Material2.default.Event.Listener("[data-md-component=navigation] [href^='#']", "click", function () { var toggle = document.querySelector("[data-md-toggle=drawer]"); if (!(toggle instanceof HTMLInputElement)) throw new ReferenceError(); if (toggle.checked) { toggle.checked = false; toggle.dispatchEvent(new CustomEvent("change")); } })) /* Retrieve facts for the given repository type */ ;(function () { var el = document.querySelector("[data-md-source]"); if (!el) return _promisePolyfill2.default.resolve([]);else if (!(el instanceof HTMLAnchorElement)) throw new ReferenceError(); switch (el.dataset.mdSource) { case "github": return new _Material2.default.Source.Adapter.GitHub(el).fetch(); default: return _promisePolyfill2.default.resolve([]); } /* Render repository information */ })().then(function (facts) { var sources = document.querySelectorAll("[data-md-source]"); Array.prototype.forEach.call(sources, function (source) { new _Material2.default.Source.Repository(source).initialize(facts); }); }); } /* ---------------------------------------------------------------------------- * Exports * ------------------------------------------------------------------------- */ /* Provide this for downward compatibility for now */ var app = { initialize: initialize }; exports.app = app; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__.p + "assets/images/icons/bitbucket.svg"; /***/ }), /* 8 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__.p + "assets/images/icons/github.svg"; /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__.p + "assets/images/icons/gitlab.svg"; /***/ }), /* 10 */ /***/ (function(module, exports) { // removed by extract-text-webpack-plugin /***/ }), /* 11 */ /***/ (function(module, exports) { // removed by extract-text-webpack-plugin /***/ }), /* 12 */ /***/ (function(module, exports) { // Polyfill for creating CustomEvents on IE9/10/11 // code pulled from: // https://github.com/d4tocchini/customevent-polyfill // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill (function() { if (typeof window === 'undefined') { return; } try { var ce = new window.CustomEvent('test', { cancelable: true }); ce.preventDefault(); if (ce.defaultPrevented !== true) { // IE has problems with .preventDefault() on custom events // http://stackoverflow.com/questions/23349191 throw new Error('Could not prevent default'); } } catch (e) { var CustomEvent = function(event, params) { var evt, origPrevent; params = params || { bubbles: false, cancelable: false, detail: undefined }; evt = document.createEvent('CustomEvent'); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); origPrevent = evt.preventDefault; evt.preventDefault = function() { origPrevent.call(this); try { Object.defineProperty(this, 'defaultPrevented', { get: function() { return true; } }); } catch (e) { this.defaultPrevented = true; } }; return evt; }; CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; // expose definition to window } })(); /***/ }), /* 13 */ /***/ (function(module, exports, __webpack_require__) { if (!window.fetch) window.fetch = __webpack_require__(2).default || __webpack_require__(2); /***/ }), /* 14 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* WEBPACK VAR INJECTION */(function(setImmediate) {/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__finally__ = __webpack_require__(18); // Store setTimeout reference so promise-polyfill will be unaffected by // other code modifying setTimeout (like sinon.useFakeTimers()) var setTimeoutFunc = setTimeout; function noop() {} // Polyfill for Function.prototype.bind function bind(fn, thisArg) { return function() { fn.apply(thisArg, arguments); }; } /** * @constructor * @param {Function} fn */ function Promise(fn) { if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); if (typeof fn !== 'function') throw new TypeError('not a function'); /** @type {!number} */ this._state = 0; /** @type {!boolean} */ this._handled = false; /** @type {Promise|undefined} */ this._value = undefined; /** @type {!Array} */ this._deferreds = []; doResolve(fn, this); } function handle(self, deferred) { while (self._state === 3) { self = self._value; } if (self._state === 0) { self._deferreds.push(deferred); return; } self._handled = true; Promise._immediateFn(function() { var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; } var ret; try { ret = cb(self._value); } catch (e) { reject(deferred.promise, e); return; } resolve(deferred.promise, ret); }); } function resolve(self, newValue) { try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); if ( newValue && (typeof newValue === 'object' || typeof newValue === 'function') ) { var then = newValue.then; if (newValue instanceof Promise) { self._state = 3; self._value = newValue; finale(self); return; } else if (typeof then === 'function') { doResolve(bind(then, newValue), self); return; } } self._state = 1; self._value = newValue; finale(self); } catch (e) { reject(self, e); } } function reject(self, newValue) { self._state = 2; self._value = newValue; finale(self); } function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { Promise._immediateFn(function() { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }); } for (var i = 0, len = self._deferreds.length; i < len; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } /** * @constructor */ function Handler(onFulfilled, onRejected, promise) { this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; this.onRejected = typeof onRejected === 'function' ? onRejected : null; this.promise = promise; } /** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */ function doResolve(fn, self) { var done = false; try { fn( function(value) { if (done) return; done = true; resolve(self, value); }, function(reason) { if (done) return; done = true; reject(self, reason); } ); } catch (ex) { if (done) return; done = true; reject(self, ex); } } Promise.prototype['catch'] = function(onRejected) { return this.then(null, onRejected); }; Promise.prototype.then = function(onFulfilled, onRejected) { // @ts-ignore var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; }; Promise.prototype['finally'] = __WEBPACK_IMPORTED_MODULE_0__finally__["a" /* default */]; Promise.all = function(arr) { return new Promise(function(resolve, reject) { if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array'); var args = Array.prototype.slice.call(arr); if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { try { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call( val, function(val) { res(i, val); }, reject ); return; } } args[i] = val; if (--remaining === 0) { resolve(args); } } catch (ex) { reject(ex); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); }; Promise.resolve = function(value) { if (value && typeof value === 'object' && value.constructor === Promise) { return value; } return new Promise(function(resolve) { resolve(value); }); }; Promise.reject = function(value) { return new Promise(function(resolve, reject) { reject(value); }); }; Promise.race = function(values) { return new Promise(function(resolve, reject) { for (var i = 0, len = values.length; i < len; i++) { values[i].then(resolve, reject); } }); }; // Use polyfill for setImmediate for performance gains Promise._immediateFn = (typeof setImmediate === 'function' && function(fn) { setImmediate(fn); }) || function(fn) { setTimeoutFunc(fn, 0); }; Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { if (typeof console !== 'undefined' && console) { console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console } }; /* harmony default export */ __webpack_exports__["default"] = (Promise); /* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(15).setImmediate)) /***/ }), /* 15 */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {var scope = (typeof global !== "undefined" && global) || (typeof self !== "undefined" && self) || window; var apply = Function.prototype.apply; // DOM APIs, for completeness exports.setTimeout = function() { return new Timeout(apply.call(setTimeout, scope, arguments), clearTimeout); }; exports.setInterval = function() { return new Timeout(apply.call(setInterval, scope, arguments), clearInterval); }; exports.clearTimeout = exports.clearInterval = function(timeout) { if (timeout) { timeout.close(); } }; function Timeout(id, clearFn) { this._id = id; this._clearFn = clearFn; } Timeout.prototype.unref = Timeout.prototype.ref = function() {}; Timeout.prototype.close = function() { this._clearFn.call(scope, this._id); }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { clearTimeout(item._idleTimeoutId); item._idleTimeout = msecs; }; exports.unenroll = function(item) { clearTimeout(item._idleTimeoutId); item._idleTimeout = -1; }; exports._unrefActive = exports.active = function(item) { clearTimeout(item._idleTimeoutId); var msecs = item._idleTimeout; if (msecs >= 0) { item._idleTimeoutId = setTimeout(function onTimeout() { if (item._onTimeout) item._onTimeout(); }, msecs); } }; // setimmediate attaches itself to the global object __webpack_require__(16); // On some exotic environments, it's not clear which object `setimmediate` was // able to install onto. Search each possibility in the same order as the // `setimmediate` library. exports.setImmediate = (typeof self !== "undefined" && self.setImmediate) || (typeof global !== "undefined" && global.setImmediate) || (this && this.setImmediate); exports.clearImmediate = (typeof self !== "undefined" && self.clearImmediate) || (typeof global !== "undefined" && global.clearImmediate) || (this && this.clearImmediate); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1))) /***/ }), /* 16 */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { "use strict"; if (global.setImmediate) { return; } var nextHandle = 1; // Spec says greater than zero var tasksByHandle = {}; var currentlyRunningATask = false; var doc = global.document; var registerImmediate; function setImmediate(callback) { // Callback can either be a function or a string if (typeof callback !== "function") { callback = new Function("" + callback); } // Copy function arguments var args = new Array(arguments.length - 1); for (var i = 0; i < args.length; i++) { args[i] = arguments[i + 1]; } // Store and register the task var task = { callback: callback, args: args }; tasksByHandle[nextHandle] = task; registerImmediate(nextHandle); return nextHandle++; } function clearImmediate(handle) { delete tasksByHandle[handle]; } function run(task) { var callback = task.callback; var args = task.args; switch (args.length) { case 0: callback(); break; case 1: callback(args[0]); break; case 2: callback(args[0], args[1]); break; case 3: callback(args[0], args[1], args[2]); break; default: callback.apply(undefined, args); break; } } function runIfPresent(handle) { // From the spec: "Wait until any invocations of this algorithm started before this one have completed." // So if we're currently running a task, we'll need to delay this invocation. if (currentlyRunningATask) { // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a // "too much recursion" error. setTimeout(runIfPresent, 0, handle); } else { var task = tasksByHandle[handle]; if (task) { currentlyRunningATask = true; try { run(task); } finally { clearImmediate(handle); currentlyRunningATask = false; } } } } function installNextTickImplementation() { registerImmediate = function(handle) { process.nextTick(function () { runIfPresent(handle); }); }; } function canUsePostMessage() { // The test against `importScripts` prevents this implementation from being installed inside a web worker, // where `global.postMessage` means something completely different and can't be used for this purpose. if (global.postMessage && !global.importScripts) { var postMessageIsAsynchronous = true; var oldOnMessage = global.onmessage; global.onmessage = function() { postMessageIsAsynchronous = false; }; global.postMessage("", "*"); global.onmessage = oldOnMessage; return postMessageIsAsynchronous; } } function installPostMessageImplementation() { // Installs an event handler on `global` for the `message` event: see // * https://developer.mozilla.org/en/DOM/window.postMessage // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages var messagePrefix = "setImmediate$" + Math.random() + "$"; var onGlobalMessage = function(event) { if (event.source === global && typeof event.data === "string" && event.data.indexOf(messagePrefix) === 0) { runIfPresent(+event.data.slice(messagePrefix.length)); } }; if (global.addEventListener) { global.addEventListener("message", onGlobalMessage, false); } else { global.attachEvent("onmessage", onGlobalMessage); } registerImmediate = function(handle) { global.postMessage(messagePrefix + handle, "*"); }; } function installMessageChannelImplementation() { var channel = new MessageChannel(); channel.port1.onmessage = function(event) { var handle = event.data; runIfPresent(handle); }; registerImmediate = function(handle) { channel.port2.postMessage(handle); }; } function installReadyStateChangeImplementation() { var html = doc.documentElement; registerImmediate = function(handle) { // Create a {% endblock %} {% block fonts %} {% if font != false %} {% endif %} {% endblock %} {% if config.extra.manifest %} {% endif %} {% for path in config["extra_css"] %} {% endfor %} {% block extrahead %}{% endblock %} {% if palette.primary or palette.accent %} {% set primary = palette.primary | replace(" ", "-") | lower %} {% set accent = palette.accent | replace(" ", "-") | lower %} {% else %} {% endif %} {% set platform = config.extra.repo_icon or config.repo_url %} {% if "github" in platform %} {% include "/assets/images/icons/github.svg" %} {% elif "gitlab" in platform %} {% include "/assets/images/icons/gitlab.svg" %} {% elif "bitbucket" in platform %} {% include "/assets/images/icons/bitbucket.svg" %} {% endif %} {% if page.toc | first is defined %} {{ lang.t('skip.link.title') }} {% endif %} {% block header %} {% include "partials/header.html" %} {% endblock %}
{% block hero %} {% if page and page.meta and page.meta.hero %} {% include "partials/hero.html" with context %} {% endif %} {% endblock %} {% if feature.tabs %} {% include "partials/tabs.html" %} {% endif %}
{% block site_nav %} {% if nav %}
{% include "partials/nav.html" %}
{% endif %} {% if page.toc %}
{% include "partials/toc.html" %}
{% endif %} {% endblock %}
{% block content %} {% if page.edit_url %} {% endif %} {% if not "\x3ch1" in page.content %}

{{ page.title | default(config.site_name, true)}}

{% endif %} {{ page.content }} {% block source %} {% if page and page.meta and page.meta.source %}

{{ lang.t("meta.source") }}

{% set repo = config.repo_url %} {% if repo | last == "/" %} {% set repo = repo[:-1] %} {% endif %} {% set path = page.meta.path | default([""]) %} {% set file = page.meta.source %} {{ file }} {% endif %} {% endblock %} {% endblock %} {% block disqus %} {% include "partials/integrations/disqus.html" %} {% endblock %}
{% block footer %} {% include "partials/footer.html" %} {% endblock %}
{% block scripts %} {% if lang.t("search.language") != "en" %} {% set languages = lang.t("search.language").split(",") %} {% if languages | length and languages[0] != "" %} {% set path = "/assets/javascripts/lunr/" %} {% for language in languages | map("trim") %} {% if language != "en" %} {% if language == "jp" %} {% endif %} {% if language in ("da", "de", "du", "es", "fi", "fr", "hu", "it", "jp", "no", "pt", "ro", "ru", "sv", "tr") %} {% endif %} {% endif %} {% endfor %} {% if languages | length > 1 %} {% endif %} {% endif %} {% endif %} {% for path in config["extra_javascript"] %} {% endfor %} {% endblock %} {% block analytics %} {% if config.google_analytics %} {% include "partials/integrations/analytics.html" %} {% endif %} {% endblock %} ================================================ FILE: SecurityPaper-themes/main.html ================================================ {% extends "base.html" %} ================================================ FILE: SecurityPaper-themes/mkdocs_theme.yml ================================================ # Copyright (c) 2016-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # Language for theme localization language: en # Text direction (can be ltr or rtl), default: ltr direction: # Feature flags for functionality that alters behavior significantly, and thus # may be a matter of taste feature: # Another layer on top of the main navigation for larger screens in the form # of tabs, especially useful for larger documentation projects tabs: false # Sets the primary and accent color palettes as defined in the Material Design # documentation - possible values can be looked up in the getting started guide palette: # Primary color used for header, sidebar and links, default: indigo primary: # Accent color for highlighting user interaction, default: indigo accent: # Fonts used by Material, automatically loaded from Google Fonts - see the site # for a list of available fonts font: # Default font for text text: Roboto # Fixed-width font for code listings code: Roboto Mono # Favicon to be rendered favicon: assets/images/favicon.png # The logo of the documentation shown in the header and navigation can either # be a Material Icon ligature (see https://material.io/icons/) or an image URL logo: icon: "\uE80C" # Material includes the search in the header as a partial, not as a separate # template, so it's correct that search.html is missing include_search_page: false # Material doesn't use MkDocs search functionality but provides its own. For # this reason, only the search index needs to be built search_index_only: true # Static pages to build static_templates: - 404.html ================================================ FILE: SecurityPaper-themes/partials/footer.html ================================================ {% import "partials/language.html" as lang with context %} ================================================ FILE: SecurityPaper-themes/partials/header.html ================================================
================================================ FILE: SecurityPaper-themes/partials/hero.html ================================================ {% set feature = config.theme.feature %} {% set class = "md-hero" %} {% if not feature.tabs %} {% set class = "md-hero md-hero--expand" %} {% endif %}
{{ page.meta.hero }}
================================================ FILE: SecurityPaper-themes/partials/integrations/analytics.html ================================================ ================================================ FILE: SecurityPaper-themes/partials/integrations/disqus.html ================================================ {% set disqus = config.extra.disqus %} {% if page and page.meta and page.meta.disqus is string %} {% set disqus = page.meta.disqus %} {% endif %} {% if not page.is_homepage and disqus %}

{{ lang.t("meta.comments") }}

{% endif %} ================================================ FILE: SecurityPaper-themes/partials/language/ar.html ================================================ {% macro t(key) %}{{ { "language": "ar", "direction": "rtl", "clipboard.copy": "نسخ إلى الحافظة", "clipboard.copied": "تم النسخ الى الحافظة", "edit.link.title": "عدل الصفحة", "footer.previous": "السابقة", "footer.next": "التالية", "meta.comments": "التعليقات", "meta.source": "المصدر", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "بحث", "search.result.placeholder": "اكتب لبدء البحث", "search.result.none": "لا توجد نتائج", "search.result.one": "نتائج البحث مستند واحد", "search.result.other": "نتائج البحث # مستندات", "skip.link.title": "انتقل إلى المحتوى", "source.link.title": "اذهب إلى المصدر", "toc.title": "جدول المحتويات" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/ca.html ================================================ {% macro t(key) %}{{ { "language": "ca", "clipboard.copy": "Còpia al porta-retalls", "clipboard.copied": "Copiat al porta-retalls", "edit.link.title": "Edita aquesta pàgina", "footer.previous": "Anterior", "footer.next": "Següent", "meta.comments": "Comentaris", "meta.source": "Codi font", "search.language": "", "search.placeholder": "Cerca", "search.result.placeholder": "Escriu per a començar a cercar", "search.result.none": "Cap document coincideix", "search.result.one": "1 document coincident", "search.result.other": "# documents coincidents", "skip.link.title": "Salta el contingut", "source.link.title": "Ves al repositori", "toc.title": "Taula de continguts" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/cs.html ================================================ {% macro t(key) %}{{ { "language": "cs", "clipboard.copy": "Kopírovat do schránky", "clipboard.copied": "Zkopírováno do schránky", "edit.link.title": "Upravit tuto stránku", "footer.previous": "Předchozí", "footer.next": "Další", "meta.comments": "Komentáře", "meta.source": "Zdroj", "search.language": "ro", "search.placeholder": "Hledat", "search.result.placeholder": "Pište co se má vyhledat", "search.result.none": "Nenalezeny žádné dokumenty", "search.result.one": "Nalezený dokument: 1", "search.result.other": "Nalezené dokumenty: #", "skip.link.title": "Přeskočit obsah", "source.link.title": "Přejít do repozitáře", "toc.title": "Obsah" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/da.html ================================================ {% macro t(key) %}{{ { "language": "da", "clipboard.copy": "Kopiér til udklipsholderen", "clipboard.copied": "Kopieret til udklipsholderen", "edit.link.title": "Redigér denne side", "footer.previous": "Forrige", "footer.next": "Næste", "meta.comments": "Kommentarer", "meta.source": "Kilde", "search.language": "da", "search.placeholder": "Søg", "search.result.placeholder": "Indtask søgeord", "search.result.none": "Ingen resultater fundet", "search.result.one": "1 resultat", "search.result.other": "# resultater", "skip.link.title": "Gå til indholdet", "source.link.title": "Åbn arkiv", "toc.title": "Indholdsfortegnelse" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/de.html ================================================ {% macro t(key) %}{{ { "language": "de", "clipboard.copy": "In Zwischenablage kopieren", "clipboard.copied": "In Zwischenablage kopiert", "edit.link.title": "Seite editieren", "footer.previous": "Zurück", "footer.next": "Weiter", "meta.comments": "Kommentare", "meta.source": "Quellcode", "search.language": "de", "search.placeholder": "Suche", "search.result.placeholder": "Suchbegriff eingeben", "search.result.none": "Keine Suchergebnisse", "search.result.one": "1 Suchergebnis", "search.result.other": "# Suchergebnisse", "skip.link.title": "Zum Inhalt", "source.link.title": "Quellcode", "toc.title": "Inhaltsverzeichnis" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/en.html ================================================ {% macro t(key) %}{{ { "language": "en", "direction": "ltr", "clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "edit.link.title": "Edit this page", "footer.previous": "Previous", "footer.next": "Next", "meta.comments": "Comments", "meta.source": "Source", "search.language": "en", "search.pipeline.stopwords": true, "search.pipeline.trimmer": true, "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.tokenizer": "[\s\-]+", "skip.link.title": "Skip to content", "source.link.title": "Go to repository", "toc.title": "Table of contents" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/es.html ================================================ {% macro t(key) %}{{ { "language": "es", "clipboard.copy": "Copiar al portapapeles", "clipboard.copied": "Copiado al portapapeles", "edit.link.title": "Editar esta página", "footer.previous": "Anterior", "footer.next": "Siguiente", "meta.comments": "Comentarios", "meta.source": "Fuente", "search.language": "es", "search.placeholder": "Búsqueda", "search.result.placeholder": "Teclee para comenzar búsqueda", "search.result.none": "No se encontraron documentos", "search.result.one": "1 documento encontrado", "search.result.other": "# documentos encontrados", "skip.link.title": "Saltar a contenido", "source.link.title": "Ir al repositorio", "toc.title": "Tabla de contenidos" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/fa.html ================================================ {% macro t(key) %}{{ { "language": "fa", "direction": "rtl", "clipboard.copy": "کپی کردن", "clipboard.copied": "کپی شد", "edit.link.title": "این صفحه را ویرایش کنید", "footer.previous": "قبلی", "footer.next": "بعدی", "meta.comments": "نظرات", "meta.source": "منبع", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "جستجو", "search.result.placeholder": "برای شروع جستجو تایپ کنید", "search.result.none": "سندی یافت نشد", "search.result.one": "1 سند یافت شد", "search.result.other": "# سند یافت شد", "skip.link.title": "پرش به محتویات", "source.link.title": "رفتن به مخزن", "toc.title": "فهرست موضوعات" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/fi.html ================================================ {% macro t(key) %}{{ { "language": "fi", "clipboard.copy": "Kopioi leikepöydälle", "clipboard.copied": "Kopioitu leikepöydälle", "edit.link.title": "Muokkaa tätä sivua", "footer.previous": "Edellinen", "footer.next": "Seuraava", "meta.comments": "Kommentit", "meta.source": "Lähdekodi", "search.language": "fi", "search.placeholder": "Hae", "search.result.placeholder": "Kirjoita aloittaaksesi haun", "search.result.none": "Ei täsmääviä dokumentteja", "search.result.one": "1 täsmäävä dokumentti", "search.result.other": "# täsmäävää dokumenttia", "skip.link.title": "Hyppää sisältöön", "source.link.title": "Mene repositoryyn", "toc.title": "Sisällysluettelo" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/fr.html ================================================ {% macro t(key) %}{{ { "language": "fr", "clipboard.copy": "Copier dans le presse-papier", "clipboard.copied": "Copié dans le presse-papier", "edit.link.title": "Editer cette page", "footer.previous": "Précédent", "footer.next": "Suivant", "meta.comments": "Commentaires", "meta.source": "Source", "search.language": "fr", "search.placeholder": "Rechercher", "search.result.placeholder": "Taper pour démarrer la recherche", "search.result.none": "Aucun document trouvé", "search.result.one": "1 document trouvé", "search.result.other": "# documents trouvés", "source.link.title": "Aller au dépôt", "toc.title": "Table des matières" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/gl.html ================================================ {% macro t(key) %}{{ { "language": "gl", "clipboard.copy": "Copiar no cortapapeis", "clipboard.copied": "Copiado no cortapapeis", "edit.link.title": "Editar esta páxina", "footer.previous": "Anterior", "footer.next": "Seguinte", "meta.comments": "Comentarios", "meta.source": "Fonte", "search.language": "es", "search.placeholder": "Busca", "search.result.placeholder": "Insira un termo", "search.result.none": "Sen resultados", "search.result.one": "1 resultado atopado", "search.result.other": "# resultados atopados", "skip.link.title": "Ir ao contido", "source.link.title": "Ir ao repositorio", "toc.title": "Táboa de contidos" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/he.html ================================================ {% macro t(key) %}{{ { "language": "he", "direction": "rtl", "clipboard.copy": "העתק ללוח", "clipboard.copied": "הועתק ללוח", "edit.link.title": "ערוך דף זה", "footer.previous": "קודם", "footer.next": "הַבָּא", "meta.comments": "הערות", "meta.source": "מָקוֹר", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "לחפש", "search.result.placeholder": "הקלד כדי להתחיל לחפש", "search.result.none": "אין מסמכים תואמים", "search.result.one": "1 מסמך תואם", "search.result.other": "# מסמך תואם", "skip.link.title": "דלג לתוכן", "source.link.title": "עבור אל מאגר", "toc.title": "תוכן העניינים" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/hi.html ================================================ {% macro t(key) %}{{ { "language": "hi", "clipboard.copy": "क्लिपबोर्ड पर कॉपी करें", "clipboard.copied": "क्लिपबोर्ड पर कॉपी कर दिया गया", "edit.link.title": "इस पृष्ठ को संपादित करें", "footer.previous": "पिछला", "footer.next": "आगामी", "meta.comments": "टिप्पणियाँ", "meta.source": "स्रोत", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "खोज", "search.result.placeholder": "खोज शुरू करने के लिए टाइप करें", "search.result.none": "कोई मिलान डॉक्यूमेंट नहीं", "search.result.one": "1 मिलान डॉक्यूमेंट", "search.result.other": "# मिलान डाक्यूमेंट्स", "skip.link.title": "विषय पर बढ़ें", "source.link.title": "रिपॉजिटरी पर जाएं", "toc.title": "विषय - सूची" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/hr.html ================================================ {% macro t(key) %}{{ { "language": "hr", "clipboard.copy": "Kopirajte u međuspremnik", "clipboard.copied": "Kopirano u međuspremnik", "edit.link.title": "Uredi stranicu", "footer.previous": "Prethodno", "footer.next": "Sljedeće", "meta.comments": "Komentari", "meta.source": "Izvor", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "Pretraživanje", "search.result.placeholder": "Unesite pojam pretraživanja", "search.result.none": "Ništa nije pronađeno", "search.result.one": "1 rezultat pretraživanja", "search.result.other": "# rezultata pretraživanja", "skip.link.title": "Preskočite na sadržaj", "source.link.title": "Idite u repozitorij", "toc.title": "Sadržaj" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/hu.html ================================================ {% macro t(key) %}{{ { "language": "hu", "clipboard.copy": "Másolás vágólapra", "clipboard.copied": "Vágólapra másolva", "edit.link.title": "Oldal szerkesztése", "footer.previous": "Előző", "footer.next": "Következő", "meta.comments": "Hozzászólások", "meta.source": "Forrás", "search.language": "hu", "search.placeholder": "Keresés", "search.result.placeholder": "Kereséshez írj ide valamit", "search.result.none": "Nincs találat", "search.result.one": "1 egyező dokumentum", "search.result.other": "# egyező dokumentum", "skip.link.title": "Kihagyás", "source.link.title": "Főoldalra ugrás", "toc.title": "Tartalomjegyzék" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/id.html ================================================ {% macro t(key) %}{{ { "language": "id", "clipboard.copy": "Salin ke memori", "clipboard.copied": "Tersalin ke memori", "edit.link.title": "Ubah halaman ini", "footer.previous": "Sebelumnya", "footer.next": "Selanjutnya", "meta.comments": "Komentar", "meta.source": "Sumber", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "Cari", "search.result.placeholder": "Ketik untuk mulai pencarian", "search.result.none": "Tidak ada dokumen yang sesuai", "search.result.one": "1 dokumen ditemukan", "search.result.other": "# dokumen ditemukan", "skip.link.title": "Lewati ke isi", "source.link.title": "Menuju repositori", "toc.title": "Daftar isi" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/it.html ================================================ {% macro t(key) %}{{ { "language": "it", "clipboard.copy": "Copia", "clipboard.copied": "Copiato", "edit.link.title": "Modifica", "footer.previous": "Precedente", "footer.next": "Prossimo", "meta.comments": "Commenti", "meta.source": "Sorgente", "search.language": "it", "search.placeholder": "Cerca", "search.result.placeholder": "Scrivi per iniziare a cercare", "search.result.none": "Nessun documento trovato", "search.result.one": "1 documento trovato", "search.result.other": "# documenti trovati", "skip.link.title": "Vai al contenuto", "source.link.title": "Apri repository", "toc.title": "Indice" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/ja.html ================================================ {% macro t(key) %}{{ { "language": "ja", "clipboard.copy": "クリップボードへコピー", "clipboard.copied": "コピーしました", "edit.link.title": "編集", "footer.previous": "前", "footer.next": "次", "meta.comments": "コメント", "meta.source": "ソース", "search.language": "jp", "search.placeholder": "検索", "search.result.placeholder": "検索キーワードを入力してください", "search.result.none": "何も見つかりませんでした", "search.result.one": "1件見つかりました", "search.result.other": "#件見つかりました", "search.tokenizer": "[\s\- 、。,.]+", "source.link.title": "リポジトリへ", "toc.title": "目次" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/kr.html ================================================ {% macro t(key) %}{{ { "language": "kr", "clipboard.copy": "클립보드로 복사", "clipboard.copied": "클립보드에 복사됨", "edit.link.title": "이 페이지를 편집", "footer.previous": "이전", "footer.next": "다음", "meta.comments": "댓글", "meta.source": "출처", "search.language": "jp", "search.placeholder": "검색", "search.result.placeholder": "검색어를 입력하세요", "search.result.none": "검색어와 일치하는 문서가 없습니다", "search.result.one": "1개의 일치하는 문서", "search.result.other": "#개의 일치하는 문서", "source.link.title": "저장소로 이동", "toc.title": "목차" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/nl.html ================================================ {% macro t(key) %}{{ { "language": "nl", "clipboard.copy": "Kopiëren naar klembord", "clipboard.copied": "Gekopieerd naar klembord", "edit.link.title": "Wijzig deze pagina", "footer.previous": "Vorige", "footer.next": "Volgende", "meta.comments": "Reacties", "meta.source": "Bron", "search.language": "du", "search.placeholder": "Zoeken", "search.result.placeholder": "Typ om te beginnen met zoeken", "search.result.none": "Geen overeenkomende documenten", "search.result.one": "1 overeenkomende document", "search.result.other": "# overeenkomende documenten", "skip.link.title": "Ga naar inhoud", "source.link.title": "Ga naar repository", "toc.title": "Inhoudsopgave" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/no.html ================================================ {% macro t(key) %}{{ { "language": "no", "clipboard.copy": "Kopier til utklippstavlen", "clipboard.copied": "Kopiert til utklippstavlen", "edit.link.title": "Rediger denne siden", "footer.previous": "Forrige", "footer.next": "Neste", "meta.comments": "Kommentarer", "meta.source": "Kilde", "search.language": "no", "search.placeholder": "Søk", "search.result.placeholder": "Skriv søkeord", "search.result.none": "Ingen treff", "search.result.one": "1 treff", "search.result.other": "# treff", "skip.link.title": "Gå til innhold", "source.link.title": "Gå til kilde", "toc.title": "Innholdsfortegnelse" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/pl.html ================================================ {% macro t(key) %}{{ { "language": "pl", "clipboard.copy": "Kopiuj do schowka", "clipboard.copied": "Skopiowane", "edit.link.title": "Edytuj tę stronę", "footer.previous": "Poprzednia strona", "footer.next": "Następna strona", "meta.comments": "Komentarze", "meta.source": "Kod źródłowy", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "Szukaj", "search.result.placeholder": "Zacznij pisać, aby szukać", "search.result.none": "Brak wyników wyszukiwania", "search.result.one": "Wyniki wyszukiwania: 1", "search.result.other": "Wyniki wyszukiwania: #", "skip.link.title": "Przejdź do treści", "source.link.title": "Idź do repozytorium", "toc.title": "Spis treści" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/pt.html ================================================ {% macro t(key) %}{{ { "language": "pt", "clipboard.copy": "Copiar para área de transferência", "clipboard.copied": "Copiado para área de transferência", "edit.link.title": "Editar esta página", "footer.previous": "Anterior", "footer.next": "Próximo", "meta.comments": "Comentários", "meta.source": "Fonte", "search.language": "pt", "search.placeholder": "Buscar", "search.result.placeholder": "Digite para iniciar a busca", "search.result.none": "Nenhum resultado encontrado", "search.result.one": "1 resultado encontrado", "search.result.other": "# resultados encontrados", "skip.link.title": "Ir para o conteúdo", "source.link.title": "Ir ao repositório", "toc.title": "Índice" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/ru.html ================================================ {% macro t(key) %}{{ { "language": "ru", "clipboard.copy": "Копировать в буфер", "clipboard.copied": "Скопировано в буфер", "edit.link.title": "Редактировать страницу", "footer.previous": "Назад", "footer.next": "Вперед", "meta.comments": "Комментарии", "meta.source": "Исходный код", "search.language": "ru", "search.placeholder": "Поиск", "search.result.placeholder": "Начните печатать для поиска", "search.result.none": "Совпадений не найдено", "search.result.one": "Найдено 1 совпадение", "search.result.other": "Найдено # совпадений", "skip.link.title": "Перейти к содержанию", "source.link.title": "Перейти к репозиторию", "toc.title": "Содержание" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/sh.html ================================================ {% macro t(key) %}{{ { "language": "sh", "clipboard.copy": "Kopiraj u klipbord", "clipboard.copied": "Iskopirano u klipbord", "edit.link.title": "Uredi stranicu", "footer.previous": "Prethodno", "footer.next": "Sledeće", "meta.comments": "Komentari", "meta.source": "Izvor", "search.language": "ro", "search.placeholder": "Pretraga", "search.result.placeholder": "Unesite pojam pretrage", "search.result.none": "Ništa nije pronađeno", "search.result.one": "1 rezultat pretrage", "search.result.other": "# rezultata pretrage", "skip.link.title": "Idi na tekst", "source.link.title": "Idi u repozitorijum", "toc.title": "Sadržaj" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/sk.html ================================================ {% macro t(key) %}{{ { "language": "sk", "clipboard.copy": "Kopírovať do schránky", "clipboard.copied": "Skopírované do schránky", "edit.link.title": "Upraviť túto stránku", "footer.previous": "Späť", "footer.next": "Ďalej", "meta.comments": "Komentáre", "meta.source": "Zdroj", "search.language": "sk", "search.placeholder": "Hľadať", "search.result.placeholder": "Pre vyhľadávanie začni písať", "search.result.none": "Žiadne vyhovujúce dokumenty", "search.result.one": "Vyhovujúci dokument: 1", "search.result.other": "Vyhovujúce dokumenty: #", "skip.link.title": "Preskočiť na obsah", "source.link.title": "Zobraziť repozitár", "toc.title": "Obsah" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/sr.html ================================================ {% macro t(key) %}{{ { "language": "sr", "clipboard.copy": "Копирај у клипборд", "clipboard.copied": "Ископирано у клипборд", "edit.link.title": "Уреди страницу", "footer.previous": "Претходно", "footer.next": "Следеће", "meta.comments": "Коментари", "meta.source": "Извор", "search.language": "", "search.pipeline.stopwords": false, "search.pipeline.trimmer": false, "search.placeholder": "Претрага", "search.result.placeholder": "Унесите појам претраге", "search.result.none": "Нису пронађени документи", "search.result.one": "1 резултат претраге", "search.result.other": "# резултата претраге", "skip.link.title": "Иди на текст", "source.link.title": "Иди у репозиторијум", "toc.title": "Садржај" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/sv.html ================================================ {% macro t(key) %}{{ { "language": "sv", "clipboard.copy": "Kopiera till urklipp", "clipboard.copied": "Kopierat till urklipp", "edit.link.title": "Redigera sidan", "footer.previous": "Föregående", "footer.next": "Nästa", "meta.comments": "Kommentarer", "meta.source": "Källa", "search.language": "sv", "search.placeholder": "Sök", "search.result.placeholder": "Skriv sökord", "search.result.none": "Inga sökresultat", "search.result.one": "1 sökresultat", "search.result.other": "# sökresultat", "skip.link.title": "Gå till innehållet", "source.link.title": "Gå till datakatalog", "toc.title": "Innehållsförteckning" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/tr.html ================================================ {% macro t(key) %}{{ { "language": "tr", "clipboard.copy": "Kopyala", "clipboard.copied": "Kopyalandı", "edit.link.title": "Düzenle", "footer.previous": "Önceki", "footer.next": "Sonraki", "meta.comments": "Yorumlar", "meta.source": "Kaynak", "search.language": "tr", "search.placeholder": "Ara", "search.result.placeholder": "Aramaya başlamak için yazın", "search.result.none": "Eşleşen doküman bulunamadı", "search.result.one": "1 doküman bulundu", "search.result.other": "# doküman bulundu", "source.link.title": "Depoya git", "toc.title": "İçindekiler" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/uk.html ================================================ {% macro t(key) %}{{ { "language": "uk", "clipboard.copy": "Скопіювати в буфер", "clipboard.copied": "Скопійовано в буфер", "edit.link.title": "Редагувати сторінку", "footer.previous": "Назад", "footer.next": "Вперед", "meta.comments": "Коментарі", "meta.source": "Вихідний код", "search.language": "ru", "search.placeholder": "Пошук", "search.result.placeholder": "Розпочніть писати для пошуку", "search.result.none": "Збігів не знайдено", "search.result.one": "Знайдено 1 збіг", "search.result.other": "Знайдено # збігів", "skip.link.title": "Перейти до змісту", "source.link.title": "Перейти до репозиторію", "toc.title": "Зміст" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/vi.html ================================================ {% macro t(key) %}{{ { "language": "vi", "clipboard.copy": "Sao chép vào bộ nhớ", "clipboard.copied": "Sao chép xong", "edit.link.title": "Chỉnh sửa", "footer.previous": "Trước", "footer.next": "Sau", "meta.comments": "Bình luận", "meta.source": "Mã nguồn", "search.placeholder": "Tìm kiếm", "search.result.placeholder": "Nhập để bắt đầu tìm kiếm", "search.result.none": "Không tìm thấy tài liệu liên quan", "search.result.one": "1 tài liệu liên quan", "search.result.other": "# tài liệu liên quan", "skip.link.title": "Vào thẳng nội dung", "source.link.title": "Đến kho lưu trữ mã nguồn", "toc.title": "Mục lục" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/zh-Hant.html ================================================ {% macro t(key) %}{{ { "language": "zh-Hant", "clipboard.copy": "拷貝", "clipboard.copied": "已拷貝", "edit.link.title": "編輯此頁", "footer.previous": "上一頁", "footer.next": "下一頁", "meta.comments": "評論", "meta.source": "來源", "search.language": "jp", "search.placeholder": "搜尋", "search.result.placeholder": "鍵入以開始檢索", "search.result.none": "沒有找到符合條件的結果", "search.result.one": "找到 1 个符合條件的結果", "search.result.other": "# 個符合條件的結果", "search.tokenizer": "[\,\。]+", "skip.link.title": "跳轉至", "source.link.title": "前往 Github 倉庫", "toc.title": "目錄" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/zh-TW.html ================================================ {% macro t(key) %}{{ { "language": "zh-Hant", "clipboard.copy": "複製", "clipboard.copied": "已複製", "edit.link.title": "編輯此頁", "footer.previous": "上一頁", "footer.next": "下一頁", "meta.comments": "留言", "meta.source": "來源", "search.language": "jp", "search.placeholder": "搜尋", "search.result.placeholder": "打字進行搜尋", "search.result.none": "沒有符合的項目", "search.result.one": "找到 1 個符合的項目", "search.result.other": "找到 # 個符合的項目", "search.tokenizer": "[\,\。]+", "skip.link.title": "跳轉到", "source.link.title": "前往倉庫", "toc.title": "本頁目錄" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language/zh.html ================================================ {% macro t(key) %}{{ { "language": "zh", "clipboard.copy": "复制", "clipboard.copied": "已复制", "edit.link.title": "编辑此页", "footer.previous": "后退", "footer.next": "前进", "meta.comments": "评论", "meta.source": "来源", "search.language": "jp", "search.placeholder": "搜索", "search.result.placeholder": "键入以开始搜索", "search.result.none": "没有找到符合条件的结果", "search.result.one": "找到 1 个符合条件的结果", "search.result.other": "# 个符合条件的结果", "search.tokenizer": "[\,\。]+", "skip.link.title": "跳转至", "source.link.title": "前往 Github 仓库", "toc.title": "目录" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/language.html ================================================ {% import "partials/language/" + config.theme.language + ".html" as lang %} {% import "partials/language/en.html" as fallback %} {% macro t(key) %}{{ { "direction": config.theme.direction, "search.language": ( config.extra.search | default({}) ).language, "search.tokenizer": ( config.extra.search | default({}) ).tokenizer | default("", true), }[key] or lang.t(key) or fallback.t(key) }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/nav-item.html ================================================ {% set class = "md-nav__item" %} {% if nav_item.active %} {% set class = "md-nav__item md-nav__item--active" %} {% endif %} {% if nav_item.children %}
  • {% if nav_item.active %} {% else %} {% endif %}
  • {% elif nav_item == page %}
  • {% set toc_ = page.toc %} {% if toc_ | first is defined and "\x3ch1 id=" in page.content %} {% set toc_ = (toc_ | first).children %} {% endif %} {% if toc_ | first is defined %} {% endif %} {{ nav_item.title }} {% if toc_ | first is defined %} {% include "partials/toc.html" %} {% endif %}
  • {% else %}
  • {{ nav_item.title }}
  • {% endif %} ================================================ FILE: SecurityPaper-themes/partials/nav.html ================================================ ================================================ FILE: SecurityPaper-themes/partials/palette.html ================================================ {% macro primary(key) %}{{ { "red": "#ef5350", "pink": "#e91e63", "purple": "#ab47bc", "deep-purple": "#7e57c2", "indigo": "#3f51b5", "blue": "#2196f3", "light-blue": "#03a9f4", "cyan": "#00bcd4", "teal": "#009688", "green": "#4caf50", "light-green": "#7cb342", "lime": "#c0ca33", "yellow": "#f9a825", "amber": "#ffa000", "orange": "#fb8c00", "deep-orange": "#ff7043", "brown": "#795548", "grey": "#757575", "blue-grey": "#546e7a" }[key] }}{% endmacro %} {% macro accent(key) %}{{ { "red": "#ff1744", "pink": "#f50057", "purple": "#e040fb", "deep-purple": "#7c4dff", "indigo": "#536dfe", "blue": "#448aff", "light-blue": "#0091ea", "cyan": "#00b8d4", "teal": "#00bfa5", "green": "#00c853", "light-green": "#64dd17", "lime": "#aeea00", "yellow": "#ffd600", "amber": "#ffab00", "orange": "#ff9100", "deep-orange": "#ff6e40" }[key] }}{% endmacro %} ================================================ FILE: SecurityPaper-themes/partials/search.html ================================================ {% import "partials/language.html" as lang with context %} ================================================ FILE: SecurityPaper-themes/partials/social.html ================================================ {% if config.extra.social %} {% endif %} ================================================ FILE: SecurityPaper-themes/partials/source.html ================================================ {% import "partials/language.html" as lang with context %} {% set platform = config.extra.repo_icon or config.repo_url %} {% if "github" in platform %} {% set repo_type = "github" %} {% elif "gitlab" in platform %} {% set repo_type = "gitlab" %} {% elif "bitbucket" in platform %} {% set repo_type = "bitbucket" %} {% else %} {% set repo_type = "" %} {% endif %} {% block repo %} {% if repo_type %}
    {% endif %}
    {{ config.repo_name }}
    {% endblock %} ================================================ FILE: SecurityPaper-themes/partials/tabs-item.html ================================================ {% if nav_item.is_homepage %}
  • {% if not page.ancestors | length and nav | selectattr("url", page.url) %} {{ nav_item.title }} {% else %} {{ nav_item.title }} {% endif %}
  • {% elif nav_item.children and nav_item.children | length > 0 %} {% set title = title | default(nav_item.title) %} {% if (nav_item.children | first).children %} {% set nav_item = nav_item.children | first %} {% include "partials/tabs-item.html" %} {% else %}
  • {% if nav_item.active %} {{ title }} {% else %} {{ title }} {% endif %}
  • {% endif %} {% endif %} ================================================ FILE: SecurityPaper-themes/partials/tabs.html ================================================ {% set class = "md-tabs" %} {% if page.ancestors | length > 0 %} {% set class = "md-tabs md-tabs--active" %} {% endif %} ================================================ FILE: SecurityPaper-themes/partials/toc-item.html ================================================
  • {{ toc_item.title }} {% if toc_item.children %} {% endif %}
  • ================================================ FILE: SecurityPaper-themes/partials/toc.html ================================================ {% import "partials/language.html" as lang with context %} ================================================ FILE: docs/1.SDL介绍/1-什么是SDL.md ================================================ # 01.什么是SDL 作者:Lost Maniac ------ SDL是微软提出的一种软件开发安全生命周期管理的一种最佳安全实践,全称为Security Development Lifecycle。 SDL是微软软件开发安全保障流程,结合了软件开发整个生命周期,将安全工程师嵌入到整个开发流程,和研发一起来协同工作保障整个软件生命周期内的安全。 SDL分为7个步骤和16种最佳安全实践的方式来保证整体安全流程周期内的可控性。 ================================================ FILE: docs/1.SDL介绍/2-企业为什么需求SDL.md ================================================ # 02.企业为什么需求SDL 作者:Murviet ----- 在SDL方法中,目的是为了从安全漏洞产生的根源上解决应用安全问题,通过对软件开发流程的控制,保证产品的安全性。 当一个企业对安全相对重视的情况下,在每年进行安全轮询时还总能找到各种各样的安全问题。每年的漏洞数量并没有明显的下降。这个时候就应该 考虑从根源解决问题。 由于企业的开发人员的技术参差不齐,部分相关开发者心中没有安全的相关概念、项目的上线及迭代更新没有相应的规范等等,这些问题都将会是导致出现安全问题的根本原因。 而SDL规范流程正是从根本原因解决这些问题。SDL对软件开发过程中所有参与该项目的相关工种,都将引入相关的安全概念,形成一个闭环,从而解决出现安全的根本问题。 ================================================ FILE: docs/1.SDL介绍/3-哪些企业需要SDL.md ================================================ # 03.哪些企业需要SDL 作者:Murviet ---- 哪些企业需要SDL 随着社会的发展,现在基本上所有的企业都在利用计算机网络进行办公,几乎所有的商业信息都存储在了网络之上。如果对信息安全不够重视,一旦商业机密被他人窃取,受到的经济损失将是无法估计的,有可能影响着企业的生死存亡。 理论上来讲对于信息安全,无论企业规模大小,无论企业信息的重要程度如何,注重信息安全是非常有必要的。但部分企业无法承担网络安全所带来的花销以及人力成本问题,所以企业要衡量一下网络安全在公司所占有的资源以及地位是否能够承受。对于互联网企业、软件开发商以及注重商业机密或大量用户信息依赖在网络环境中的相关企业都应重视网络安全问题。 对于拥有庞大的开发团队的企业,由于大量的开发人员以及产品的频繁迭代,推动SDL规范流程是目前最好的减少企业相关网络应用产品的安全问题。 推动SDL需企业具备以下条件: 1. 重视信息安全 2. 拥有成熟的开发和管理团队 3. 规范的产品研发和迭代流程 ================================================ FILE: docs/1.SDL介绍/4-SDL所带来的优缺点.md ================================================ # 04.SDL所带来的优缺点 作者: ---- 未完成 ================================================ FILE: docs/2.SDL规范文档/1-安全设计Checklist.md ================================================ # 01.安全设计Checklist 作者:WeiHo@破晓团队(整理) 协作:Lost Maniac、1024、pa55w0rd、doubiduo ------- ## 输入验证 - 校验跨信任边界传递的不可信数据(策略检查数据合法性,含白名单机制等)格式化字符串时,依然要检验用户输入的合法性,避免可造成系统信息泄露或者拒绝服务 - 禁止向Java Runtime.exec()方法传递不可信、未净化的数据(当参数中包含空格,双引号,以-或者/符号开头表示一个参数开关时,可能会导致参数注入漏洞),建议如果可以禁止JVM执行外部命令,未知漏洞的危害性会大大降低,可以大大提高JVM的安全性。 - 验证路径之前应该先将其标准化为实际路径(特殊的文件名,比如“..”,symbolic links、hard links、shortcuts) - 从ZipInputStream提取文件,如果不在程序预期计划的目录之内时,应拒绝将其提取出来,或者将其提取到一个安全的位置 - 从ZipInputStream提取文件,若解压之后的文件大小超过一定的限制时,必须拒绝将其解压 - 在处理以前,验证所有来自客户端的数据,包括:所有参数、URL、HTTP头信息(比如:cookie名字和数据值),确定包括了来自 JavaScript、Flash 或其他嵌入代码的post 返回信息 - 如果任何潜在的危险字符必须被作为输入,请确保您执行了额外的安全控制,比如:输入转义、输出编码、特定的安全 API等。部分常见的危险字符,包含但不限于: < > " ' % ( ) & + \ \' \" - 如果您使用的标准验证规则无法验证下面的输入,那么它们需要被单独验证,比如验证空字节 (%00); 验证换行符 (%0d, %0a, \r, \n); 验证路径替代字符“点-点-斜杠”(../或 ..\);如果支持 UTF-8 扩展字符集编码,验证替代字符: %c0%ae%c0%ae/ (使用规范化验证双编码或其他类型的编码) - 严格验证来自重定向输入的数据(一个攻击者可能向重定向的目标直接提交恶意代码,从而避开应用程序逻辑以及在重定向前执行的任何验证) - 验证数据类型 - 验证数据范围 - 验证数据长度 --- ## 输出编码 - 为每一种输出编码方法采用一个标准的、已通过测试的规则 - 通过语义输出编码方式,对所有从服务端返回到客户端的数据进行编码。比如HTML编码、URL编码等,编码形式需根据具体的应用场景选择 - 除非对目标编译器是安全的,否则请对所有字符进行编码 - 针对 SQL、XML 和 LDAP 查询,语义净化所有不可信数据的输出 - 对于操作系统命令,净化所有不可信数据输出 --- ## 异常处理 - 禁止在异常中泄露敏感信息(敏感数据的范围应该基于应用场景以及产品威胁分析的结果来确定。典型的敏感数据包括口令、银行账号、个人信息、通讯记录、密钥等) - 禁止在异常中泄露应用服务器的指纹信息(如版本,路径,架构) - 方法发生异常时要恢复到之前的对象状态(业务操作失败时,进行回滚业务;或者避免去修改对象状态,维持对象状态一致性) - I/O操作- 临时文件使用完毕应及时删除 - 不要将Buffer对象封装的数据暴露给不可信代码 - 在多用户系统中创建文件时指定合适的访问许可,以防止未授权的文件访问 - 当一个外部进程通过其输出流对外输出信息或错误时,必须及时清空其输出流,以防止输出流中的缓冲区被耗尽而导致外部进程被阻塞。 - 白名单控制共享目录操作文件权限,比如读/写/可执行权限 --- ## 运行环境 - 不要使用危险的许可与目标组合(比如不要将AllPermission许可赋予给不信任的代码,不要将ReflectPermission许可和suppressAccessChecks目标组合使用,不要将java.lang.RuntimePermission许可与createClassLoader目标组合) - 不要禁用JVM字节码验证,如果使用的字节码,如class文件被恶意篡改过,将会存在安全风险 - 建议监控平台不要对互联网开放,仅限于内网环境访问;如果监控平台存在远程执行漏洞,将会给所监控的应用带来安全风险 - 建议将所有安全敏感代码(例如进行权限控制或者用户名密码校验的代码)都放在一个jar包中 - 生产代码不能包含任何调试代码或接口 --- ## 身份验证 - 除了那些特定设为“公开”的内容以外,对所有的网页和资源都要求进行身份验证,并正确设计身份验证功能 - 所有的身份验证过程必须在服务器后端上执行 - 在任何可能的情况下,建立并使用标准的、已通过安全测试的身份验证服务(比如 C4A) - 所有的身份验证控制应当安全的处理未成功的身份验证,比如给出错误模糊提示,隐藏敏感信息 - 登录入口应具有防止暴力猜解及撞库猜解(利用已泄漏的密码字典进行批量登录尝试)的措施,超过设定失败次数需要启用锁定或图片随机码进行访问限制 - 采用https post请求方式传输身份验证的凭据信息 - 身份验证的失败提示信息采用模糊处理,比如可以使用“用户名或密码错误”,而不要使用“用户名错误”或者“密码错误”明确提示。 - 涉及敏感信息或功能的外部系统连接应配置身份验证功能,并进行有效身份验证控制 - 在执行关键操作(如个人信息密码修改操作)时,应对用户身份进行再次验证 - 为高度敏感或重要的交易账户使用多因子身份验证机制,如支付密码、短信验证码等 --- ## 短信验证码 - 一次一用 - 发送频率控制(建议60s获取一次) - 验证码有效期(建议60s内有效,发短信时进行友好提示) - 复杂度(短信验证码建议6位数字) - 安全提示:是否是个人自己操作等风险提示信息 - 在前端校验(客户端的校验只能作为辅助手段,很容易被绕过),必须使用服务端代码对输入数据进行最终校验 - 短信验证码需要限制频率使用,例如:每天一个手机号码只允许发送5次,防止被黑客恶意消耗短信 - 不同场景的短信验证码不可通用 - 单个短信验证码限制有效验证次数 - 验证码需要对应手机号不可通用 - 限制对短信接口的调用(1.推荐添加验证码保证需要人类交互才可以发送短信2.根据自己的业务特点限制每个IP每天的最大发送量) --- ## 图形验证码 - 一次一用 - 验证码有效期(10分钟内有效,可根据场景兼容安全和体验灵活设置) - 复杂度(4位及以上数字、字母交替),根据需要也可采用当下流行的拖拽验证码或计算值的验证方式 - 服务器端进行认证 - 从用户体验和安全角度出发,可设计为当用户输3次错误密码后自动弹出验证码输入框进行验证操作 --- ## 密码管理 - 禁止使用私有或者弱加密算法(比如禁止使用DES,SHA1等,推荐使用AES: 128位,RSA: 2048位,DSA: 2048位) - 采用基于哈希算法和加入盐值(salt)方式安全存储口令信息 - 数据库连接配置中的用户密码要以加密的形式存储(建议所有涉及密码存储的功能点进行加密存储) - 保证密码传输过程需要加密(建议使用https) - 密码输入框,可设计为显示密码和隐藏密码切换功能 - 密码重设和更改操作,需要进行二次合法身份验证 - 密码重设时,应对注册手机号和邮箱进行有效验证,链接只能发送到预先注册的邮件地址或预先绑定的手机号 - 临时密码和链接应设计一个短暂的有效期(比如5分钟),防止暴力破解 - 当密码重新设置时,应短信通知用户是否是本人在操作,告知安全风险 - 密码复杂度设置:建议8个字符以上,包含字母、数字及特殊字符等 - 密码设置场景中应具有密码复杂度检查功能(建议在后台验证密码复杂度) - 密码不能输出到日志和控制台 - 建议设计密码定期修改提醒机制 --- ## 会话安全 - 用户登出后应立即清理会话及其相关登录信息 - 注销功能应当完全终止相关的会话或连接 - 增加Cookie 安全性,添加“HttpOnly”和“secure”属性(当“secure”属性设置为true时表示创建的 Cookie 会被以安全的形式向服务器传输,也就是只能在HTTPS 连接中被浏览器传递到服务器端进行会话验证,在 HTTP 连接中不会传递该信息,也就不会存在Cookie被窃取的问题;设置了"HttpOnly"属性,通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样也能减少XSS跨站脚本攻击风险) - 会话cookie应设计有效期,超时后立即失效 - 当设计允许用户在多渠道终端同时登录时,建议应进行常用设备登录限制 - 为包含已验证的会话标识符的 cookie 设置域和路径,为站点设置一个恰当的限制值。默认cookie的域是当前域名,默认cookie的路径是当前页面的目录路径。如果想要跨域或者在其他的路径下访问cookie就必须要重新设置这两个属性,domain和path。 - 注销功能应当可用于所有受身份验证保护的网页 - 在平衡风险和业务功能需求的基础上,设置一个尽量短的会话超时时间。通常情况下,应当不超过几个小时。 - 不要在URL、错误信息或日志中暴露会话标识符,会话标识符应当只出现在http头信息中,不要将会话标识符以 GET 参数进行传递 - 定期生成一个新的会话标识符并周期性地使上一个会话标识符失效(这可以缓解那些原标识符被获得的特定会话劫持情况) - 在身份验证的时候,如果连接从 HTTP 变为 HTTPS,则会生成一个新的会话标识符。在应用程序中,推荐持续使用 HTTPS,不应在 HTTP 和 HTTPS 之间来回转换,有效避免切换过程会话被劫持篡改。 - 为服务器端的操作执行标准的安全会话管理,为每个会话执行合法的身份验证和权限控制,防止存在CSRF跨站点请求伪造漏洞 --- ## 访问控制 - 将具有特权的逻辑从其他应用程序代码中隔离开 - 限制只有授权的用户才能访问文件资源 - 限制只有授权的用户才能访问受保护的URL - 限制只有授权的用户才能访问受保护的功能或服务 - 建议只有授权的用户才能访问直接对象引用 - 限制只有授权的用户才能访问受保护的应用程序数据 - 限制只有授权的用户才能访问与安全相关的配置信息 - 限制只有授权的外部应用程序或接口才能访问受保护的本地程序或资源 - 服务器端执行的访问控制规则和前端实施的访问控制规则必须匹配 - 服务器中创建文件时需指定合理的访问权限(读/写/可执行) - 当权限重新设置发生变更时,应记录好日志,并短信通知用户是否是本人在操作,告知可能存在的安全风险 --- ## 日志规范 - 不要在日志中保存敏感信息,包括系统指纹信息、会话标识符、账号密码、证件、ID等 - 确保日志记录包含了重要的日志事件数据 - 记录所有失败和成功的输入验证 - 记录所有失败和成功的身份验证记录 - 记录所有失败和成功的访问和操作记录 - 记录明显的修改事件,包括对于状态数据的修改 - 记录连接无效或者已过期的会话令牌尝试 - 记录所有的管理功能操作行为,包含但不限于安全配置设置的变更 - 记录所有失败和成功的后端连接 - 记录加密模块的错误信息 - 禁止将日志直接保存在可被浏览器访问到的WEB目录中 --- ## 敏感信息 - 临时产生的敏感数据(写入内存或文件),应具有及时清除和释放机制 - 不要在 HTTP GET 请求参数中包含敏感信息,如用户名、密码、卡号、ID等 - 禁止表单中的自动填充功能,因为表单中可能包含敏感信息,包括身份验证信息 - 不要在客户端上以明文形式保存密码或其他敏感信息 - 为所有敏感信息采用SSL加密传输 - 禁止将敏感信息(包含加密秘钥等)硬编码在程序中 - 禁止明文存储用户的密码、身份证号、银行卡号、持卡人姓名等敏感信息 - 不要在日志中保存敏感信息,包含但不限于系统详细信息、会话标识符、密码等 - 禁止在异常中泄露应用服务器的指纹信息,如版本,路径,组件版本等 - 禁止将源码或sql上传到开源平台或社区,如github、开源中国等 - 请求中含有敏感参数(如订单号、ID等),应进行混淆方式处理,防止产生参数遍历获取信息风险 - 敏感信息需要展示在web页面上时,应在后台进行敏感字段脱敏处理 - 请求返回数据不应包含请求之外的业务数据,特别是敏感信息数据 --- ## 密码找回安全 - 服务器端要做认证,避免绕过前端控制 - 增加二次认证因子,如验证码 - 涉及登录验证token之类的,不要直接将验证内容直接返回给用户 - 认证凭证加密,推荐强算法(推荐使用AES: 128位,RSA: 2048位,DSA: 2048位) - 认证凭证中的参数应进行混淆处理 - 在多个验证操作中,要对各验证机制进行排序,以防出现跳过前面验证机制直接到最后一步认证的安全风险 - 手机短信码验证,需同时校验手机号和短信是否对应 - 输入框中,应校验输入数据合法性,防止产生XSS跨站脚本攻击 - 密码找回链接限制有效访问时间和复用次数(不可重复使用) --- ## SQL注入 - 永远不要信任用户的输入,要对用户的所有输入进行校验,包含SQL语句的过滤和转义 - 永远不要使用动态拼装SQL,可以使用参数化的SQL或者使用存储过程进行数据查询存取 - 永远不要使用管理员权限进行数据库连接,为每个应用使用单独的非特权权限,且配置有限的数据库连接数 - 不要把敏感信息明文存放,采用加密或者哈希、混淆等方式对敏感信息进行脱敏存储 - 应用的异常信息应不带有敏感信息,给出尽可能少的提示;建议使用自定义的错误信息对原始错误信息进行包装,可把异常信息存放在独立的数据库表中 - XML注入- 不要使用字符串/StringBuffer/StringBuilder/StringFormat组装XML - 建议对XML元素属性或者内容进行转义 --- ## XSS跨站脚本攻击 - 对输入的数据进行过滤和转义,包含但不限于< >" ' % ( ) & + \ \' \"等危险特殊字符 - 数据添加到html元素属性或者内容中时,对数据进行HTML转义 - 数据添加到script脚本中时,对数据进行script转义 - 数据添加到style中时,对数据进行css转义 --- ## CSRF跨站请求伪造 - 建议在每个关键表单中引入了CSRF Token验证(会话中生成的随机串,提交后校验) - 在关键表单提交时要求用户进行二次身份验证(录入密码、插KEY、输入图片验证码、短信验证码) - 对请求referer做验证(比如跨域、系统内部应用) --- ## 文件上传安全 - 上传操作应设计身份验证机制,并进行合法身份校验 - 只允许上传满足业务需要的相关文档类型 - 通过检查文件头信息,比如JPEG (jpg)文件头信息(十六进制):FFD8FF,验证上传文档是否是所期待的类型 - 不要把文件保存在与应用程序相同的 Web 环境中,建议将文件保存在专用的文档服务器中,单独给文档服务器配置域名访问更好 - 限制上传任意可能被 Web 服务器解析的文件 ,比如jsp、php等 - 上传文件以二进制形式下载,建议不提供直接访问(防止木马文件直接执行) - 禁止授予上传文件存储目录的可执行权限 - 禁止客户端自定义文件上传/下载路径(如:使用../../../../进行跳转) - 文件上传后重命名(需根据业务实际需求制定命名规则) --- ## 组件安全 - 在使用随机数函数时,推荐使用强随机数函数(例如java.security.SecureRandom类) - 精简组件中不需要的功能、方法,以免带来未知的安全风险 - 不可将系统内部使用的锁对象暴露给不可信代码 - 建议使用SSL Socket代替Socket来进行安全数据交互 - 封装本地方法调用(所有的本地方法都应该被定义为私有的,然后仅通过一个封装方法来调用) - 使用安全管理器(比如java.security或第三方安全组件)来保护敏感操作 - 编写自定义类加载器必须覆盖getPermissions()函数时,在为代码源分配任意权限前,应调用超类super.getPermissions()函数,实现除了自定义策略外,系统全局的默认安全策略也被应用。 - 避免完全依赖URLClassLoader和java.util.jar提供的默认自动签名认证机制,应从加载类的代码源(Code-Source)中获取证书链,然后检查证书是否属于本地密钥库(KeyStore)中的受信任签名者 --- ## 接口安全 - 调用方来源IP控制,比如可通过防火墙、主机host deny、Nginx deny等技术措施进行实施 - 调用方身份认证,比如key、secret、证书等技术措施进行实施 - 调用参数认证,需设计参数容错机制,避免出现参数可遍历敏感数据安全问题 - 采用数字签名保障接口身份来源可信,数据防篡改 - 调用方权限控制设置 - 调用频率、有效期进行控制 - 调用行为实时检测,对异常阻拦 - 幂等性校验,保持数据一致性 - 采用应用接入安全网关,实现APPID/KEY身份认证,加密传输,摘要签名安全保障 --- ## Dubbo调用安全 - 采用token验证访问控制,防止消费者绕过注册中心访问提供者;在注册中心控制权限以决定要不要下发令牌给消费者 - 采用filter IP白名单访问控制,同时也可预防生产系统和测试系统之间Dubbo混乱调用问题 - 在必要情况下(如敏感信息操作),连接注册中心Dubbo时要进行用户名和密码校验 --- ## Redis调用安全 - 应启用客户端IP访问控制验证功能 - 应启用客户端身份验证功能 - 敏感信息不要明文存储于Redis ================================================ FILE: docs/2.SDL规范文档/10-SDL上线规定文档.md ================================================ # 11. SDL上线规定文档 作者:Lost Maniac 协作: --- ## 1. 概述 ### 1.1. 编制目的 为了提升公司各业务线产品的安全质量,降低安全风险,进一步提升公司整体安全水平,结合公司现有产品设计、开发、测试及上线流程,特制定此《XX产品安全开发流程》。 ### 1.2. 适用范围 此流程适用于 **XX** 所有业务线产品的安全设计、开发、测试及上线。 ## 2. 什么是安全开发流程(SDL)? SDL 的全称是 **Security Development Lifecycle**,即:安全开发生命周期。它是由微软最早提出的,是一种帮助解决软件安全问题的方法。SDL 中的方法,试图从安全漏洞产生的根源上解决问题。SDL 是一个安全保证的过程,通过对软件工程的控制,从而保证产品的安全性。它能够帮助企业以最小的成本提高产品的安全性,对企业安全的发展来说,可以起到事半功倍的效果。 ## 3. 实施 SDL 的目的 实施 SDL 的核心目的只有一个,那就是通过在开发过程中加入安全控制的方法,提升各业务线项目、系统的安全性。避免因项目上线后存在安全漏洞被攻击者恶意利用而造成不必要的安全风险和损失。 ## 4. 实施 SDL 的好处 * 提前主动发现安全漏洞,降低安全风险和漏洞修复成本 * 在项目开发前期就引入安全控制的方法,构建标准化安全开发流程,从根源上减少安全漏洞和降低安全风险 * 保证所有项目在上线前都通知到安全团队 ## 5. 如何实施安全开发流程 ### 5.1. XX SDL 整体流程 ![整体流程](/images/2018/10/01.jpeg) ### 5.2. 项目立项 要求:需要保证所有项目在立项时都通知到安全团队。 通知方式:邮件+企业微信、立项会议 ### 5.3. 需求分析 要求:所有需求必须通过安全评审,由安全团队来评估需求是否存在安全风险或是否需要设计安全功能;如果安全评审未通过,不允许进入下一步研发流程 > 安全评审流程: ![安全评审流程](/images/2018/10/02.jpeg) 安全评审成果:安全评审报告 安全评审沟通方式:邮件+企业微信、jira安全评审提交 ### 5.4. 设计 在设计阶段,由产品和研发团队自查,确认是否有违反《XX开发安全红线准则》的行为。 ### 5.5. 编码实现 在编码实现阶段,研发工程师应遵循 **《XX安全开发手册》**。 ### 5.6. 测试验证 在开发工作完成后,应与功能测试同步进行安全测试,安全测试过程中发现的安全漏洞通过“jira XX安全团队漏洞提交”管理。 安全测试需求提交方式:邮件+企业微信、项目安全提测系统 ### 5.7. 业务验收 在业务验收时,应同步进行安全验收,完成后由安全团队发布《XX项目安全验收报告》,如 果在安全验收过程中发现存在未修复的高危及严重级别安全漏洞,不允许进入上线发布环节。 ### 5.8. 上线与维护 * 如果未收到“通过安全验收”的报告,不允许私自上线发布项目。 * 在项目上线前,由安全团队添加相应必要的安全监控、定期漏洞扫描。 ================================================ FILE: docs/2.SDL规范文档/11-web应用安全业务自查checklist.md ================================================ # 11. Web应用安全业务自查checklist 作者:realjac 协作:Melody --- ## 1. 概述 ### 1.1. 编制目的 * 此checklist用于业务线测试或开发人员在上线前进行安全自查 * 安全前置落地实施,是将安全需求嵌入开发流程的急先锋 ### 1.2. 编写原则 - 便于业务理解常见安全风险 - 方便业务检查项目中存在的最显而易见的风险点 - 不求覆盖最全,保证能在业务落地使用 - 基于公司常见场景出发的经验归纳 ## 2. checklist内容 | 业务功能 | 自查安全项 | 风险等级 | 满足/不满足/不适用 | 备注 | |:-------|:------------------------------------------------------------------------------------------|:-----|:-----------|:---| | 登录 | 1.系统应接入账号安全组统一登录平台 | 中 | | | | | 2.自建登录功能应使用验证码等二次验证机制,且验证码应在每次登录成功或失败后失效刷新; | 中 | | | | | 3.如密码等敏感信息应加密传输; | 中 | | | | | 4.外网系统应使用https传输登录信息; | 高 | | | | | 5.用户登录失败的提示信息应为“用户名或密码错误”/“登录失败”等模糊提示; | 低 | | | | 注册 | 1.应有二次审核机制,如手机/邮箱等方式验证 | 高 | | | | | 2.短信发送接口应限制针对同一手机号的请求频率; | 低 | | | | 密码找回 | 1.应有二次审核机制,如手机/邮箱等方式验证,不可修改需要验证的手机号/邮箱等; | 高 | | | | | 2.短信发送接口应限制针对同一手机号的请求频率; | 低 | | | | | 3.在每一步环节应判断上一步的合法性; | 中 | | | | 退出登录 | 1.session认证会话应配置过期时间,一般建议60min; | 低 | | | | | 2.点击退出后应销毁服务端认证session,使用户端cookie在退出登录后失效; | 中 | | | | 上传 | 1.上传功能文件后缀应使用白名单限制为业务需要的文件类型; | 高 | | | | | 2.应限制上传目录的权限,不允许赋予上传目录和上传的文件执行权限; | 中 | | | | | 3.建议使用公司统一的文件存储系统,如… | 中 | | | | 下载 | 1.下载目录应被限定在固定目录内,不允许被../../等路径操作跨目录访问其他文件; | 高 | | | | | 2.敏感资源应设置访问控制权限,只允许拥有授权的角色下载; | 高 | | | | 跨域需求接口 | 使用CORS跨域时,CORS安全配置: | | | | | | 1.应设置Access-Control-Allow-Origin及Origin白名单域名为可信域(xx.test.com); | 中 | | | | | 2.只有需要携带Cookie时,才允许设置Access-Control-Allow-Credentials头,且Origin白名单必须精细化设置,不允许如*.test.com的配置。 | 高 | | | | | JSONP接口: | | | | | | 1.必须使用白名单严格限制请求来源referer; | 高 | | | | 网络资源调用 | 1.应使用白名单限定允许调用的URL,特别针对内网的请求应严格限定; | 高 | | | | 调用系统命令 | 1.应使用白名单限定允许调用的系统命令; | 高 | | | | 敏感操作接口 | 1.应使用白名单限制请求来源referer或增加token等机制验证请求发起者身份; | 高 | | | | | 2.应记录应用操作日志; | 中 | | | | | 3.敏感操作接口如订单支付等,应使用悲观锁或乐观锁保证事务的ACID特性,解决并发竞争问题; | 高 | | | | | 4.对敏感资源进行操作时,应在服务端校验资源标识归属人是否与当前登录人一致; | 高 | | | | | | | | | | 漏洞扫描 | 1.上线前应使用自动化漏洞扫描工具扫描测试,确定无漏洞和安全风险; | 必须 | | | | 源代码审计 | 1.上线前应使用代码扫描工具进行扫描,确定无漏洞和安全风险; | 必须 | | | | 数据安全 | 数据处理:(参考公司数据分级标准) | | | | | | 1.对用户可控输入且最终会回显输出到页面的数据,应使用公司安全防护组件进行转义安全编码后再输出; | 中 | | | | | 2.应将SQL语句预编译处理,未能预编译处理的语句如order by子句应使用白名单控制用户允许的输入; | 高 | | | | | 3.应在前端对敏感字段(如手机号、身份证、银行卡号)脱敏展示; | 中 | | | | | 数据传输: | | | | | | 1.外网系统应使用https传输数据; | 中 | | | | | 2.敏感字段应脱敏/加密处理; | 中 | | | | | 数据存储: | | | | | | 1.日志中不应包含明文或未脱敏敏感数据; | 低 | | | | | 2.敏感数据应加密存储; | 中 | | | ================================================ FILE: docs/2.SDL规范文档/2-php安全编码规范.md ================================================ # 02.php安全编码规范 作者:tinker 协作: 注解:请根据业务安全等级需要自行协调以下建议。 --- ## 1.配置 php.ini基本安全配置 --- ### 1.1应启用“cgi.force_redirect” cgi.force_redirect在php.ini中修改,默认是开启的,它可以防止当PHP运行的CGI脚本未经验证的访问。在IIS,OmniHTTPD和Xitami上是禁用的,但在所有其他情况下它应该打开。 ```php ; php.ini cgi.force_redirect=1 ; ``` --- ### 1.2应禁用“enable_dl” 该指令仅对Apache模块版本的PHP有效。你可以针对每个虚拟机或每个目录开启或关闭dl()动态加载PHP模块。关闭动态加载的主要原因是为了安全。通过动态加载,有可能忽略所有open_basedir限制。默认允许动态加载,除了使用安全模式。在安全模式,总是无法使用dl()。 ```php ; php.ini enable_dl=0 ; ``` --- ### 1.3应禁用“file_uploads” file_uploads默认是开启的,允许将文件上传到您的站点。因为来自陌生人的文件本质上是不可信甚至危险的,除非您的网站绝对需要,否则应禁用此功能。如果开启请进行相应的限制,参考upload_max_filesize, upload_tmp_dir,和post_max_size。 ```php ; php.ini file_uploads = 0 ; ``` --- ### 1.4通过“open_basedir”限制文件访问权限 open_basedir默认是打开所有文件,它将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令不受安全模式打开或者关闭的影响。当一个脚本试图用例如 fopen() ,include或者 gzopen() 打开一个文件时,该文件的位置将被检查。当文件在指定的目录树之外时 PHP 将拒绝打开它。所有的符号连接都会被解析,所以不可能通过符号连接来避开此限制。 open_basedir应该配置一个目录,然后可以递归访问。但是,应该避免使用. (当前目录)作为open_basedir值,因为它在脚本执行期间动态解析特殊值 . 指明脚本的工作目录将被作为基准目录,但这有些危险,因为脚本的工作目录可以轻易被 chdir() 而改变。 在 httpd.conf 文件中,open_basedir 可以像其它任何配置选项一样用“php_admin_value open_basedir none”的方法关闭(例如某些虚拟主机中)。在 Windows 中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为 Apache 模块时,父目录中的 open_basedir 路径自动被继承。 用 open_basedir 指定的限制实际上是前缀,不是目录名。也就是说“open_basedir = /dir/incl”也会允许访问“/dir/include”和“/dir/incls”,如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:“open_basedir = /dir/incl/”。 ```php ; php.ini open_basedir="${USER}/scripts/data" ; ``` --- ### 1.5应禁用“session.use_trans_sid” 默认为 0(禁用)。当禁用cookie时,如果它开启,PHP会自动将用户的会话ID附加到URL。基于 URL 的会话管理比基于 cookie 的会话管理有更多安全风险,从表面上看,这似乎是让那些禁用cookie的用户正常使用您的网站的好方法。实际上,它使那些用户容易被任何人劫持他们的会话。例如用户有可能通过 email 将一个包含有效的会话 ID 的 URL 发给他的朋友,或者用户总是有可能在收藏夹中存有一个包含会话 ID 的 URL 来以同样的会话 ID 去访问站点。也可以从浏览器历史记录和服务器日志中检索URL获取会话ID。 ```php ; php.ini session.use_trans_sid = 0 ; ``` --- ### 1.6会话管理cookie不能是持久的 没有固定生命周期或到期日期的Cookie被称为非持久性或“会话”cookie,这意味着它们只会持续与浏览器会话一样长,并且在浏览器关闭时会消失。具有到期日期的Cookie叫做“持久性”Cookie,他们将被存储/保留到这些生存日期。 管理网站上的登录会话应用非持久性cookie。要使cookie非持久化,只需省略该 expires属性即可。也可以使用session.cookie_lifetime实现。 --- ### 1.7应禁用"allow_url_fopen"和"allow_url_include" allow_url_fopen和allow_url_include默认是开启的,他们允许代码从URL中读入脚本。从站点外部吸入可执行代码的能力,加上不完美的输入清理可能会使站点裸露给攻击者。即使该站点的输入过滤在今天是完美的,但不能保证以后也是。 ```php ; php.ini allow_url_fopen = 0 allow_url_include = 0 ``` ## 2.编码 php安全编码建议 --- ### 2.1慎用sleep()函数 sleep()有时用于通过限制响应率来防止拒绝服务(DoS)攻击。但是因为它占用了一个线程,每个请求需要更长的时间来服务,这会使应用程序更容易受到DoS攻击,而不是减少风险。 ```php if (is_bad_ip($requester)) { sleep(5); // 不合规的用法 } ``` --- ### 2.2禁止代码动态注入和执行 eval()函数是一种在运行时运行任意代码的方法。 函数eval()语言结构是非常危险的,因为它允许执行任意 PHP 代码。因此不鼓励使用它。如果您仔细的确认过,除了使用此结构以外别无方法,请多加注意,不要允许传入任何由用户提供的、未经完整验证过的数据。 ```php eval($code_to_be_dynamically_executed) // 不合规的用法 ``` --- ### 2.3禁止凭据硬编码 因为从编译的应用程序中提取字符串很容易,所以永远不应对凭证进行硬编码。对于分发的应用程序尤其如此。 凭据应存储在受强保护的加密配置文件或数据库中的代码之外。 ```php // 合规的用法 $uname = getEncryptedUser(); $password = getEncryptedPass(); connect($uname, $password); ``` ```php // 不合规的用法 $uname = "steve"; $password = "blue"; connect($uname, $password); ``` ### 2.4禁止危险函数 有时候,我们不希望执行包括system()等在那的能够执行命令的php函数,或者能够查看phpinfo信息的   phpinfo()等函数,那么我们就可以禁止它们:   disable_functions = system,passthru,exec,shell_exec,popen,phpinfo   如果你要禁止任何文件和目录的操作,那么可以关闭很多文件操作   disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir,   rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown   以上只是部分常用的文件处理函数,你也可以把上面执行命令函数和这个函数结合,应该就能够抵制大部分的phpshell了。 ================================================ FILE: docs/2.SDL规范文档/3-java安全编码规范.md ================================================ # 03.java安全编码规范 作者:108haili 协作:Lost Maniac ------- ## 1输入验证和数据合法性校验 程序接受数据可能来源于未经验证的用户,网络连接和其他不受信任的来源,如果未对程序接受数据进行校验,则可能会引发安全问题。 ### 1.1避免SQL注入 使用PreparedStatement预编译SQL,解决SQL注入问题,传递给PreparedStatement对象的参数可以被强制进行类型转换,确保在插入或查询数据时与底层的数据库格式匹配。  ```java String sqlString = "select * from db_user where username=? and password=?"; PreparedStatement stmt = connection.prepareStatement(sqlString); stmt.setString(1, username); stmt.setString(2, pwd); ResultSet rs = stmt.executeQuery(); ``` --- ### 1.2避免XML注入 通过StringBulider 或 StringBuffer 拼接XML文件时,需对输入数据进行合法性校验。 对数量quantity 进行合法性校验,控制只能传入0-9的数字: ```java if (!Pattern.matches("[0-9]+", quantity)) { // Format violation } String xmlString = "\nWidget\n" + "500\n" + "" + quantity + ""; outStream.write(xmlString.getBytes()); outStream.flush(); ``` --- ### 1.3避免跨站点脚本(XSS) 对产生跨站的参数进行严格过滤,禁止传入`