├── .gitignore ├── 3rdPartyOSS.txt ├── LICENSE.md ├── README.md ├── bin └── www ├── browser_versions.txt ├── config.js ├── csp-validator ├── README.md └── csp-validator.js ├── index.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── images │ └── spinner.gif ├── javascripts │ ├── jquery │ │ ├── jquery-1.11.2.min.js │ │ └── jquery-ui-1.11.2.min.js │ ├── test-share-script.js │ ├── test-window.js │ └── testscript.js └── stylesheets │ ├── jquery │ └── 1.11.2 │ │ └── themes │ │ └── smoothness │ │ └── jquery-ui.css │ ├── pure │ └── 0.5.0 │ │ └── pure-min.css │ └── style.css ├── routes └── index.js ├── run ├── views ├── cspreport.ejs ├── error.ejs ├── index.ejs ├── partials │ └── template │ │ ├── footer.ejs │ │ ├── head.ejs │ │ └── header.ejs ├── test-report.ejs ├── test-window.ejs ├── test.ejs └── webkit-tests.ejs └── webkit-tests ├── 1.1 ├── base-uri-allow.html ├── base-uri-deny.html ├── form-action-src-allowed.html ├── form-action-src-blocked.html ├── form-action-src-default-ignored.html ├── form-action-src-get-allowed.html ├── form-action-src-get-blocked.html ├── form-action-src-javascript-blocked.html ├── form-action-src-redirect-blocked.html ├── frame-allowed.html ├── frame-blocked.html ├── frame-redirect-blocked.html ├── meta-outside-head.html ├── plugintypes-notype-url.html ├── plugintypes-nourl-allowed.html ├── scripthash-allowed.html ├── scripthash-basic-blocked.html ├── scripthash-ignore-unsafeinline.html ├── scripthash-unicode-normalization.html ├── scriptnonce-allowed.html ├── scriptnonce-and-scripthash.html ├── scriptnonce-basic-blocked.html ├── scriptnonce-ignore-unsafeinline.html ├── stylehash-allowed.html ├── stylehash-basic-blocked.html ├── stylenonce-allowed.html └── stylenonce-blocked.html ├── blob-urls-match-self.html ├── combine-multiple-policies.html ├── csptest.html ├── default-src-inline-allowed.html ├── duplicate-directive.html ├── eval-allowed-in-report-only-mode.html ├── eval-allowed.html ├── eval-blocked.html ├── eval-scripts-setInterval-allowed.html ├── eval-scripts-setInterval-blocked.html ├── eval-scripts-setTimeout-allowed.html ├── eval-scripts-setTimeout-blocked.html ├── function-constructor-allowed.html ├── function-constructor-blocked.html ├── image-allowed.html ├── image-full-host-wildcard-allowed.html ├── image-host-wildcard-allowed.html ├── img-blocked-no-gc-crash.html ├── injected-inline-script-allowed.html ├── injected-inline-script-blocked.html ├── injected-inline-style-allowed.html ├── injected-inline-style-blocked.html ├── inline-script-allowed.html ├── inline-script-blocked-goofy.html ├── inline-style-allowed.html ├── inline-style-attribute-allowed.html ├── inline-style-attribute-blocked.html ├── inline-style-attribute-on-html.html ├── inline-style-blocked.html ├── media-src-track-block.html ├── no-policy.html ├── policy-does-not-affect-child.html ├── report-and-enforce.html ├── report-blocked-data-uri.html ├── report-only-report-uri-missing.html ├── report-only.html ├── report-uri.html ├── resources ├── abe.png ├── alert-fail.js ├── alert-pass.html ├── blue.css ├── document-write-alert-fail.js ├── dump-as-text.js ├── get.txt ├── go-to-echo-report.js ├── inject-script.js ├── inject-style.js ├── multiple-iframe-test.js ├── script.js ├── track.vtt ├── worker-eval.js ├── worker-function-function.js ├── worker-make-xhr.js └── worker-set-timeout.js ├── sandbox-allow-scripts-subframe.html ├── sandbox-allow-scripts.html ├── sandbox-empty-subframe.html ├── sandbox-empty.html ├── script-src-overrides-default-src.html ├── source-list-parsing-02.html ├── source-list-parsing-03.html ├── source-list-parsing-04.html ├── source-list-parsing-deprecated.html ├── source-list-parsing-no-semicolon.html ├── srcdoc-doesnt-bypass-script-src.html ├── style-allowed.html ├── style-blocked.html ├── worker-connect-src-allowed.html ├── worker-connect-src-blocked.html ├── worker-eval-blocked.html ├── worker-function-function-blocked.html ├── worker-script-src.html └── worker-set-timeout-blocked.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /3rdPartyOSS.txt: -------------------------------------------------------------------------------- 1 | Open source softwares: 2 | ---------------------- 3 | purecss.io (http://purecss.io/) 4 | license: https://github.com/yahoo/pure-site/blob/master/LICENSE.md 5 | 6 | jquery (http://jquery.com/) 7 | license: https://github.com/jquery/jquery/blob/master/LICENSE.txt 8 | 9 | nodejs ( http://nodejs.org/) 10 | license: https://github.com/joyent/node/blob/master/LICENSE 11 | 12 | redis (http://redis.io) 13 | license: https://github.com/antirez/redis/blob/unstable/COPYING 14 | 15 | NodeJs npm open source packages: 16 | -------------------------------- 17 | body-parser 18 | license: https://github.com/expressjs/body-parser/blob/master/LICENSE 19 | 20 | cookie-parser 21 | license: https://github.com/expressjs/cookie-parser/blob/master/LICENSE 22 | 23 | debug 24 | license: https://github.com/visionmedia/debug (MIT) 25 | 26 | ejs 27 | license: https://github.com/tj/ejs (MIT) 28 | 29 | express 30 | license: https://github.com/strongloop/express/blob/master/LICENSE 31 | 32 | express-busboy 33 | license: https://github.com/yahoo/express-busboy/blob/master/LICENSE 34 | 35 | morgan 36 | license: https://github.com/expressjs/morgan/blob/master/LICENSE 37 | 38 | randomstring 39 | license: https://github.com/klughammer/node-randomstring/blob/master/LICENSE 40 | 41 | redis 42 | license: https://github.com/mranney/node_redis (MIT) 43 | 44 | serve-favicon 45 | licenses: https://github.com/expressjs/serve-favicon/blob/master/LICENSE 46 | 47 | ua-parser 48 | license: https://github.com/tobie/ua-parser/blob/master/LICENSE.txt 49 | 50 | 51 | The application also contains modified version of CSP test scripts from: 52 | https://trac.webkit.org/browser#trunk/LayoutTests/http/tests/security/contentSecurityPolicy/ 53 | webkit 54 | licenses: https://www.webkit.org/coding/bsd-license.html & https://www.webkit.org/coding/lgpl-license.html 55 | and 56 | https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/&sq=package:chromium 57 | license: https://code.google.com/p/chromium/codesearch#chromium/src/LICENSE&sq=package:chromium&q=license 58 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | ======================================== 3 | 4 | Copyright (c) 2015, Yahoo Inc. All rights reserved. 5 | ---------------------------------------------------- 6 | 7 | Redistribution and use of this software in source and binary forms, 8 | with or without modification, are permitted provided that the following 9 | conditions are met: 10 | 11 | * Redistributions of source code must retain the above 12 | copyright notice, this list of conditions and the 13 | following disclaimer. 14 | * Redistributions in binary form must reproduce the above 15 | copyright notice, this list of conditions and the 16 | following disclaimer in the documentation and/or other 17 | materials provided with the distribution. 18 | * Neither the name of Yahoo Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Yahoo Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Note:** This library has known security vulnerabilities, use at your own risk! 2 | 3 | ## CSPTESTER 4 | 5 | A quick and easy way to test CSP behavior on modern browsers 6 | 7 | `csptester` is a Node.js-based web app that can frame a user's HTML content and allow them to test CSP policies in a browser of their choice to see what fails/works. You may optionally even try XSS attacks against your code. There are tools like http://caniuse.com/#search=csp that shows which browser versions support CSP, but it doesn't convey disparity in support between versions or browsers. And that's one reason `csptester` is helpful. 8 | 9 | **Features** 10 | * Test CSP on all modern browsers 11 | * CSP HTML meta tag support 12 | * Ability to render your HTML code on iframe and top-level window 13 | * Report-only and enforce mode options. Try an `alert()` in your code to see report-only and enforce in action! 14 | * Shareable links - To share with other users or to repeat the test on a different browser 15 | * Preloaded with curated subset of WebKit/Chrome tests (CSP level 1 & 2) to test various CSP features 16 | * Check 3rd party resources (eg. JavaScript) to find 4th party/recursive dependencies 17 | 18 | ## Using csptester 19 | 20 | CSP implementation differs between browsers. Even CSP 1.0 implementation is not consistent across all modern browsers. Therefore understanding browser's CSP support is important to implement CSP on your property. This is a tool to test policy behavior (with your sample script) across multiple browsers. However this is NOT intended to use to test a random site's CSP behavior. 21 | 22 | ### CSP Header 23 | The Content-Security-Policy (CSP) header value is made up of one or more directives. Multiple directives are separated with a semicolon (`;`) 24 | 25 | **NOTE:** Do not add CSP header name and report-uri field. The header and report-uri will be set by the application. 26 | 27 | **CSP header examples** 28 | 29 | [1] A server wishes to load resources only form its own origin 30 | ``` 31 | default-src 'self'; 32 | ``` 33 | 34 | [2] This policy allows images, scripts, AJAX, and CSS from the same origin, and does not allow any other resources to load (eg object, frame, media, etc). 35 | ``` 36 | default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; 37 | ``` 38 | 39 | [3] Allow all by default and restricts each resource type separately. 40 | ``` 41 | default-src *; 42 | script-src https://*.yahoo.com https://*.yimg.com 'unsafe-inline' 'unsafe-eval'; 43 | object-src https://*.yahoo.com https://*.yimg.com; 44 | style-src https://*.yahoo.com https://*.yimg.com 'unsafe-inline'; 45 | media-src https://*.yahoo.com https://*.yimg.com; 46 | frame-src https://*.yahoo.com https://*.yimg.com https://*.ymail.com; 47 | font-src https://*; 48 | connect-src https://*.yahoo.com https://*.flickr.com 49 | ``` 50 | 51 | ### HTML Code 52 | Provide your HTML code here. 53 | 54 | **Example** 55 | 56 | ```html 57 | 58 | 59 | 60 | CSP Tester 61 | 62 | 63 | 64 | 65 | 66 | 67 |

Hello, world!

68 | 69 | 70 | 71 | 72 | ``` 73 | 74 | If we set CSP header `default-src 'self'`, the above HTML code reports four violations. 75 | 76 | ### Report Only - CSP in monitoring mode 77 | Disable policy enforcement. This will render the page even with the violations. The number of CSP reports tend to increase with this option set. That is because a violated resource may embed other violated URIs - chain effect. 78 | 79 | ### CSP HTML meta tags 80 | `csptester` also supports testing CSP with HTML `meta` tag. `meta` tag is another way to set content security policy on a web page. To track violations with CSP meta tag on `csptester` tool, provide a URL variable called $CSP_REPORT_URI for `report-uri` field as shown below: 81 | 82 | ```html 83 | 84 | ``` 85 | 86 | **Example** 87 | 88 | The policy is set in the HTML code using `meta` tag. This is equivalent to setting an explicit CSP header. Setting a CSP header is optional in this case. 89 | 90 | ```html 91 | 92 | 93 | 94 | CSP Tester 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |

Hello, world!

104 | 105 | 106 | 107 | 108 | ``` 109 | 110 | ### Render on window.top 111 | `csptester` provides two options to render HTML code; (1) iframe (2) top-level window. iframe is the default option. The second option opens two new windows (or tabs). The first window renders HTML code and the other one shows violation reports. The second option is useful in the following cases: 112 | * Policy enforcement varies and the result wont be exactly same on iframe and top-level window. 113 | * If you copy paste a web page (eg yahoo mail page source), those web pages may have (javascript) checks to test the rendering window is an iframe or not, and may not even render on iframe. 114 | * Many browser plugins (adwares, malwares etc.) inject code only to top window pages. So we cannot detect such violations with iframe option. 115 | * Shareable links are supported only in this mode 116 | 117 | ### WebKit CSP Tests 118 | `csptester` is preloaded with curated subset of WebKit CSP tests to test various CSP features. Not all WebKit tests are available now in csptester. These scripts cover most common CSP user cases and serve as an excellent learning resource. 119 | 120 | All tests are adopted from [WebKit](https://trac.webkit.org/browser#trunk/LayoutTests/http/tests/security/contentSecurityPolicy/) and [Chrome](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/&sq=package:chromium) repositories 121 | 122 | ## Deploying csptester 123 | 124 | 1. Clone or download [csptester](https://github.com/yahoo/csptester) from git 125 | 2. Install npm packages: `% cd csptester && npm install` 126 | 3. Install [redis](http://redis.io/) 127 | 4. Start redis: `% redis-server /usr/local/etc/redis.conf` 128 | 5. `% node ./bin/www` 129 | 130 | For service management, use [forever](https://www.npmjs.com/package/forever) npm package 131 | 132 | ### Settings 133 | 134 | Application settings such as TLS, redis connection, default port are defined in `config.js` file. 135 | 136 | ### Known Issues 137 | 138 | 1. WebKit & Chrome CSP tests use HTML meta-tags to define policy. Since CSP meta-tag option is not implemented in Firefox, these tests may not work in Firefox. The workaroud is to take the CSP policy defined in the HTML meta-tag and put it in CSP header field. 139 | 2. If you are not seeing the desired behavior for CSP Level 2 tests with default option (iframe), try with enabling top-level window option. 140 | 141 | ### [csp-validator.js](https://github.com/yahoo/csptester/blob/master/csp-validator/csp-validator.js) 142 | `csp-validator.js` is a separate phantomjs based command-line script to validate CSP policy for the given URL. You may use this script during the web application build process (integration testing phase) to validate CSP policy to make sure your web page complies with the defined policy. Click [csp-validator](https://github.com/yahoo/csptester/blob/master/csp-validator/README.md) to find more details. 143 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var debug = require('debug')('csptester'); 3 | var app = require('../index'); 4 | var config = require('../config.js'); 5 | var https = require('https'); 6 | var fs = require('fs'); 7 | 8 | var port = process.env.PORT || config.port; 9 | 10 | if ((config.tls === 1) || (config.tls === 2)) { 11 | var options = { 12 | key: fs.readFileSync(config.tlsKey), 13 | cert: fs.readFileSync(config.tlsCert), 14 | }; 15 | 16 | var server = https.createServer(options, app).listen(config.tlsPort, function(){ 17 | console.log('CSP Tester HTTPS server listening on port ' + server.address().port); 18 | }); 19 | 20 | } 21 | 22 | if ((config.tls === 0) || (config.tls === 2)) { 23 | var server = app.listen(port, function() { 24 | console.log('CSP Tester HTTP server listening on port ' + server.address().port); 25 | }); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /browser_versions.txt: -------------------------------------------------------------------------------- 1 | [2015-01-31 21:45:41,7457] - Safari 8.0.2 2 | [2015-01-31 21:45:41,7458] - 8.0.2 3 | [2015-01-31 21:45:41,7459] - Safari 4 | [2015-01-31 21:45:41,7459] - 8 5 | [2015-01-31 21:45:41,7459] - 0 6 | [2015-01-31 21:45:41,7459] - 2 7 | [2015-01-31 21:45:41,7460] - Mac OS X 10.10.1 8 | [2015-01-31 21:45:41,7460] - 10.10.1 9 | [2015-01-31 21:45:41,7461] - Mac OS X 10 | [2015-01-31 21:45:41,7462] - 10 11 | [2015-01-31 21:45:41,7462] - 10 12 | [2015-01-31 21:45:41,7463] - 1 13 | [2015-01-31 21:45:41,7463] - Other 14 | 15 | 16 | [2015-01-31 21:51:55,8560] - Firefox 35.0 17 | [2015-01-31 21:51:55,8561] - 35.0 18 | [2015-01-31 21:51:55,8561] - Firefox 19 | [2015-01-31 21:51:55,8562] - 35 20 | [2015-01-31 21:51:55,8562] - 0 21 | [2015-01-31 21:51:55,8565] - null 22 | [2015-01-31 21:51:55,8566] - Mac OS X 10.10 23 | [2015-01-31 21:51:55,8566] - 10.10 24 | [2015-01-31 21:51:55,8566] - Mac OS X 25 | [2015-01-31 21:51:55,8567] - 10 26 | [2015-01-31 21:51:55,8567] - 10 27 | [2015-01-31 21:51:55,8568] - null 28 | [2015-01-31 21:51:55,8568] - Other 29 | 30 | 31 | [2015-01-31 21:52:05,9200] - Chrome 40.0.2214 32 | [2015-01-31 21:52:05,9202] - 40.0.2214 33 | [2015-01-31 21:52:05,9202] - Chrome 34 | [2015-01-31 21:52:05,9203] - 40 35 | [2015-01-31 21:52:05,9204] - 0 36 | [2015-01-31 21:52:05,9204] - 2214 37 | [2015-01-31 21:52:05,9205] - Mac OS X 10.10.1 38 | [2015-01-31 21:52:05,9207] - 10.10.1 39 | [2015-01-31 21:52:05,9208] - Mac OS X 40 | [2015-01-31 21:52:05,9209] - 10 41 | [2015-01-31 21:52:05,9209] - 10 42 | [2015-01-31 21:52:05,9210] - 1 43 | [2015-01-31 21:52:05,9211] - Other 44 | 45 | 46 | [2015-01-31 21:53:57,6542] - IE 11.0 47 | [2015-01-31 21:53:57,6544] - 11.0 48 | [2015-01-31 21:53:57,6544] - IE 49 | [2015-01-31 21:53:57,6547] - 11 50 | [2015-01-31 21:53:57,6547] - 0 51 | [2015-01-31 21:53:57,6547] - 11 52 | [2015-01-31 21:53:57,6547] - 0 53 | [2015-01-31 21:53:57,6552] - null 54 | [2015-01-31 21:53:57,6553] - Windows 7 55 | [2015-01-31 21:53:57,6553] - 56 | [2015-01-31 21:53:57,6555] - Windows 7 57 | [2015-01-31 21:53:57,6556] - null 58 | [2015-01-31 21:53:57,6557] - null 59 | [2015-01-31 21:53:57,6558] - null 60 | [2015-01-31 21:53:57,6559] - Other 61 | 62 | 63 | [2015-01-31 22:01:20,7303] - Chrome 38.0.2125 64 | [2015-01-31 22:01:20,7305] - 38.0.2125 65 | [2015-01-31 22:01:20,7306] - Chrome 66 | [2015-01-31 22:01:20,7307] - 38 67 | [2015-01-31 22:01:20,7307] - 0 68 | [2015-01-31 22:01:20,7310] - 2125 69 | [2015-01-31 22:01:20,7311] - Windows 7 70 | [2015-01-31 22:01:20,7311] - 71 | [2015-01-31 22:01:20,7312] - Windows 7 72 | [2015-01-31 22:01:20,7317] - null 73 | [2015-01-31 22:01:20,7319] - null 74 | [2015-01-31 22:01:20,7320] - null 75 | [2015-01-31 22:01:20,7321] - Other 76 | 77 | 78 | [2015-01-31 22:04:00,9868] - IE 8.0 79 | [2015-01-31 22:04:00,9869] - 8.0 80 | [2015-01-31 22:04:00,9869] - IE 81 | [2015-01-31 22:04:00,9870] - 8 82 | [2015-01-31 22:04:00,9869] - IE 83 | [2015-01-31 22:04:00,9870] - 8 84 | [2015-01-31 22:04:00,9870] - 0 85 | [2015-01-31 22:04:00,9872] - null 86 | [2015-01-31 22:04:00,9873] - Windows 7 87 | [2015-01-31 22:04:00,9874] - 88 | [2015-01-31 22:04:00,9875] - Windows 7 89 | [2015-01-31 22:04:00,9876] - null 90 | [2015-01-31 22:04:00,9877] - null 91 | [2015-01-31 22:04:00,9881] - null 92 | [2015-01-31 22:04:00,9882] - Other 93 | 94 | 95 | [2015-01-31 22:05:28,9923] - Opera 18.0.1284 96 | [2015-01-31 22:05:28,9923] - 18.0.1284 97 | [2015-01-31 22:05:28,9923] - Opera 98 | [2015-01-31 22:05:28,9924] - 18 99 | [2015-01-31 22:05:28,9924] - 0 100 | [2015-01-31 22:05:28,9924] - 1284 101 | [2015-01-31 22:05:28,9925] - Windows 7 102 | [2015-01-31 22:05:28,9926] - 103 | [2015-01-31 22:05:28,9926] - Windows 7 104 | [2015-01-31 22:05:28,9927] - null 105 | [2015-01-31 22:05:28,9927] - null 106 | [2015-01-31 22:05:28,9929] - null 107 | [2015-01-31 22:05:28,9929] - Other 108 | 109 | [2015-01-31 22:20:19,8488] - Opera 27.0.1689 110 | [2015-01-31 22:20:19,8489] - 27.0.1689 111 | [2015-01-31 22:20:19,8489] - Opera 112 | [2015-01-31 22:20:19,8489] - 27 113 | [2015-01-31 22:20:19,8489] - 0 114 | [2015-01-31 22:20:19,8489] - 1689 115 | [2015-01-31 22:20:19,8489] - Windows 7 116 | [2015-01-31 22:20:19,8490] - 117 | [2015-01-31 22:20:19,8490] - Windows 7 118 | [2015-01-31 22:20:19,8491] - null 119 | [2015-01-31 22:20:19,8491] - null 120 | [2015-01-31 22:20:19,8492] - null 121 | [2015-01-31 22:20:19,8492] - Other 122 | 123 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author Binu P. Ramakrishnan 7 | // Created 01/05/2015 8 | // 9 | // csptester configuration file 10 | 11 | // website title 12 | exports.title='Content Security Policy Tester'; 13 | 14 | // listen port 15 | exports.port=3000; 16 | 17 | // TLS (SSL) settings 18 | // 0 => TLS disabled (no TLS), 19 | // 1 => TLS enabled, 20 | // 2 => Listen on both TLS and non-TLS ports 21 | exports.tls=0; 22 | exports.tlsPort=4443; 23 | exports.tlsKey='/path/to/tls/private/key'; 24 | exports.tlsCert='/path/to/tls/public/cert'; 25 | 26 | // how long to cache user input and violation reports? 27 | // 240 sec (or 4 minutes) 28 | exports.ephemeralCache=240; 29 | 30 | // shareable link expiry time - 48 hours in milliseconds 31 | exports.longLivedCache=172800000; 32 | 33 | // key/record id str len 34 | exports.keyLen=16; 35 | 36 | // redis port 37 | exports.redisPort=6379; 38 | 39 | // redis hostname 40 | exports.redisHost='127.0.0.1'; 41 | 42 | -------------------------------------------------------------------------------- /csp-validator/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### What is csp-validator? 3 | 4 | `csp-validator.js` is a phantomjs based headless script to test CSP policy for the given URL. You may use this script during the web application build process (integration testing phase) to validate CSP policy to make sure your web page complies with the defined policy. 5 | 6 | Using the script as part of the the build process helps the team to detect inclusion of non-whitelisted resources before the application deploys to production. For example, adding a third-party Javascript tag or adding a HTTP resource to an HTTPS page. 7 | 8 | NOTE: `csp-validator.js` is an independent tool with no dependency on `csptester`. 9 | ### Usage 10 | 11 | Prerequisite: phantomjs 12 | 13 | ``` 14 | % bin/phantomjs csp-validator.js 15 | 16 | Usage: csp-validator.js [--quiet] 17 | Returns: 18 | 0 => SUCCESS - No violations 19 | 1 => FAIL - System/parse/input error 20 | 2 => CSP-VIOLATION - Violation detected 21 | 22 | ``` 23 | 24 | Want to do a quick try? 25 | 26 | 1. Go to http://csptester.io/csptest.html 27 | 2. Opt 'Render on `top.window`' and click `Submit` 28 | 3. Click `View Violations`. This will open a new window/tab. Go back to previous tab, copy the URL and use it here 29 | 30 | **Example** 31 | ``` 32 | % bin/phantomjs csp-validator.js http://74.6.34.39/test/w1uCH63aAg6Gv3IE 33 | http://74.6.34.39/report/w1uCH63aAg6Gv3IE 34 | Request (#2): {"csp-report":{"document-uri":"http://74.6.34.39/test/w1uCH63aAg6Gv3IE","referrer":"","violated-directive":"default-src none","original-policy":"default-src none; report-uri /report/w1uCH63aAg6Gv3IE;","blocked-uri":"http://yui.yahooapis.com"}} 35 | http://74.6.34.39/report/w1uCH63aAg6Gv3IE 36 | Request (#3): {"csp-report":{"document-uri":"http://74.6.34.39/test/w1uCH63aAg6Gv3IE","referrer":"","violated-directive":"default-src none","original-policy":"default-src none; report-uri /report/w1uCH63aAg6Gv3IE;","blocked-uri":"https://ajax.googleapis.com"}} 37 | http://74.6.34.39/report/w1uCH63aAg6Gv3IE 38 | Request (#4): {"csp-report":{"document-uri":"http://74.6.34.39/test/w1uCH63aAg6Gv3IE","referrer":"","violated-directive":"default-src none","original-policy":"default-src none; report-uri /report/w1uCH63aAg6Gv3IE;","blocked-uri":"http://l.yimg.com"}} 39 | 40 | Status: success 41 | Loaded: http://74.6.34.39/test/w1uCH63aAg6Gv3IE 42 | Number of violations: 3 43 | 44 | % echo $? 45 | 2 46 | 47 | ``` 48 | -------------------------------------------------------------------------------- /csp-validator/csp-validator.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author: Binu P. Ramakrishnan 7 | // Created: 03/06/2015 8 | // 9 | // A phantomjs headless script to test CSP policy of the given URL 10 | // use as part of CICD pipeline 11 | // 12 | // Usage: % phantonjs csp-validator.js 13 | // 14 | 15 | var system = require('system'); 16 | var args = system.args; 17 | 18 | var homePage; 19 | var quiet=false; 20 | var violationCount=0; 21 | 22 | if (args.length < 2) { 23 | console.log('\nUsage: ' + args[0] + ' [--quiet] '); 24 | console.log('Returns:'); 25 | console.log(' 0 => SUCCESS - No violations'); 26 | console.log(' 1 => FAIL - System/parse/input error'); 27 | console.log(' 2 => CSP-VIOLATION - Violation detected\n'); 28 | phantom.exit(1); 29 | } else { 30 | homePage = args[args.length-1]; 31 | if ((args.length === 3) && (args[1] == '--quiet')) { 32 | quiet=true; 33 | } 34 | } 35 | 36 | var page = require("webpage").create(); 37 | 38 | /*page.customHeaders = { 39 | "Cookie": "auth cookies" 40 | }; 41 | */ 42 | 43 | page.open(homePage); 44 | 45 | page.onLoadFinished = function(status) { 46 | if (status !== 'success') { 47 | console.log('URL load failed; exiting...'); 48 | phantom.exit(1); 49 | } 50 | 51 | var url = page.url; 52 | if (quiet === false) { 53 | console.log('Status: ' + status); 54 | console.log('Loaded: ' + url); 55 | } 56 | 57 | console.log('Number of violations: ' + violationCount); 58 | if (violationCount > 0) { 59 | phantom.exit(2); 60 | } else { 61 | phantom.exit(0); 62 | } 63 | }; 64 | 65 | // filter csp reports 66 | page.onResourceRequested = function(requestData, networkRequest) { 67 | console.log(requestData.url); 68 | //console.log('Request (#' + requestData + ': ' + JSON.stringify(requestData)); 69 | if (requestData.postData) { 70 | try{ 71 | if (JSON.parse(requestData.postData)['csp-report']) { 72 | if (quiet == false) { 73 | console.log('Request (#' + requestData.id + '): ' + requestData.postData); 74 | } 75 | 76 | violationCount++; 77 | } 78 | 79 | }catch(e){ 80 | //alert(e); //error in the above parsing; skip and continue 81 | 82 | } 83 | } 84 | }; 85 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author Binu P. Ramakrishnan 7 | // Created 01/05/2015 8 | 9 | 10 | var express = require('express'); 11 | var path = require('path'); 12 | var favicon = require('serve-favicon'); 13 | var logger = require('morgan'); 14 | var cookieParser = require('cookie-parser'); 15 | var bodyParser = require('express-busboy'); 16 | //var bodyParser = require('body-parser'); 17 | 18 | var routes = require('./routes/index'); 19 | var app = express(); 20 | 21 | // A workaround to process CSP report from chrome. 22 | // Chrome uses separate content-type for sending CSP 23 | // reports which is not working well with express-busboy 24 | // The workaround is to intercept the request and 25 | // replace the content-type with app/json and pass it 26 | // to express-busboy. 27 | // Note the order is important. ie this function should 28 | // be placed before busboy bodyParser extend. 29 | app.post('/report/:id', function(req, res, next) { 30 | req.headers['content-type'] = 'application/json'; 31 | next(); 32 | }); 33 | 34 | //bodyParser.extend(app); 35 | bodyParser.extend(app, { 36 | limits: { 37 | fieldSize: 10 * 1024 * 1024 38 | } 39 | }); 40 | 41 | // view engine setup 42 | app.set('views', path.join(__dirname, 'views')); 43 | app.set('view engine', 'ejs'); 44 | 45 | app.use(favicon(__dirname + '/public/favicon.ico')); 46 | app.use(logger('dev')); 47 | app.use(cookieParser()); 48 | //app.use(express.compress()); 49 | app.use(express.static(path.join(__dirname, 'public'))); 50 | app.use('/resources', express.static(path.join(__dirname, 'webkit-tests/resources'))); 51 | 52 | app.use('/', routes); 53 | 54 | // catch 404 and forward to error handler 55 | app.use(function(req, res, next) { 56 | var err = new Error('Not Found'); 57 | err.status = 404; 58 | next(err); 59 | }); 60 | 61 | // error handlers 62 | 63 | // development error handler 64 | // will print stacktrace 65 | if (app.get('env') === 'development') { 66 | app.use(function(err, req, res, next) { 67 | res.status(err.status || 500); 68 | res.render('error', { 69 | message: "DEV " + err.message, 70 | error: err 71 | }); 72 | }); 73 | } 74 | 75 | // production error handler 76 | // no stacktraces leaked to user 77 | app.use(function(err, req, res, next) { 78 | res.status(err.status || 500); 79 | res.render('error', { 80 | message: err.message, 81 | error: {} 82 | }); 83 | }); 84 | 85 | 86 | module.exports = app; 87 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csptester", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.5", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 11 | "requires": { 12 | "mime-types": "~2.1.18", 13 | "negotiator": "0.6.1" 14 | }, 15 | "dependencies": { 16 | "mime-db": { 17 | "version": "1.36.0", 18 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", 19 | "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" 20 | }, 21 | "mime-types": { 22 | "version": "2.1.20", 23 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", 24 | "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", 25 | "requires": { 26 | "mime-db": "~1.36.0" 27 | } 28 | } 29 | } 30 | }, 31 | "array-flatten": { 32 | "version": "1.1.1", 33 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 34 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 35 | }, 36 | "array-uniq": { 37 | "version": "1.0.2", 38 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", 39 | "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" 40 | }, 41 | "basic-auth": { 42 | "version": "1.0.0", 43 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz", 44 | "integrity": "sha1-ERstn/jk5tE2uMhOpeCWy4c1Fjc=" 45 | }, 46 | "body": { 47 | "version": "4.5.0", 48 | "resolved": "https://registry.npmjs.org/body/-/body-4.5.0.tgz", 49 | "integrity": "sha1-a8P0BAC1vJCbD08X8lyfxsdKmlg=", 50 | "requires": { 51 | "error": "~2.0.4", 52 | "raw-body": "~1.1.0", 53 | "safe-json-parse": "~1.0.1" 54 | }, 55 | "dependencies": { 56 | "raw-body": { 57 | "version": "1.1.7", 58 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", 59 | "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", 60 | "requires": { 61 | "bytes": "1", 62 | "string_decoder": "0.10" 63 | } 64 | } 65 | } 66 | }, 67 | "body-parser": { 68 | "version": "1.8.4", 69 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.8.4.tgz", 70 | "integrity": "sha1-1JfgS8E7P5qL2McLsM3Bby4CiJg=", 71 | "requires": { 72 | "bytes": "1.0.0", 73 | "depd": "0.4.5", 74 | "iconv-lite": "0.4.4", 75 | "media-typer": "0.3.0", 76 | "on-finished": "2.1.0", 77 | "qs": "2.2.4", 78 | "raw-body": "1.3.0", 79 | "type-is": "~1.5.1" 80 | } 81 | }, 82 | "busboy": { 83 | "version": "0.2.14", 84 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", 85 | "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", 86 | "requires": { 87 | "dicer": "0.2.5", 88 | "readable-stream": "1.1.x" 89 | } 90 | }, 91 | "bytes": { 92 | "version": "1.0.0", 93 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", 94 | "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" 95 | }, 96 | "connect-busboy": { 97 | "version": "0.0.2", 98 | "resolved": "https://registry.npmjs.org/connect-busboy/-/connect-busboy-0.0.2.tgz", 99 | "integrity": "sha1-rFyclmchcYheV2xmsr/ZXTuxEJc=", 100 | "requires": { 101 | "busboy": "*" 102 | } 103 | }, 104 | "content-disposition": { 105 | "version": "0.5.2", 106 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 107 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 108 | }, 109 | "content-type": { 110 | "version": "1.0.4", 111 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 112 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 113 | }, 114 | "cookie": { 115 | "version": "0.1.3", 116 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz", 117 | "integrity": "sha1-5zSlwUF/zkctWu+Cw4HKu2TRpDU=" 118 | }, 119 | "cookie-parser": { 120 | "version": "1.3.5", 121 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz", 122 | "integrity": "sha1-nXVVcPtdF4kHcSJ6AjFNm+fPg1Y=", 123 | "requires": { 124 | "cookie": "0.1.3", 125 | "cookie-signature": "1.0.6" 126 | } 127 | }, 128 | "cookie-signature": { 129 | "version": "1.0.6", 130 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 131 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 132 | }, 133 | "core-util-is": { 134 | "version": "1.0.2", 135 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 136 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 137 | }, 138 | "debug": { 139 | "version": "2.6.9", 140 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 141 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 142 | "requires": { 143 | "ms": "2.0.0" 144 | } 145 | }, 146 | "depd": { 147 | "version": "0.4.5", 148 | "resolved": "https://registry.npmjs.org/depd/-/depd-0.4.5.tgz", 149 | "integrity": "sha1-GmZLUziLSmVz6K5ntfdnxpPKl/E=" 150 | }, 151 | "destroy": { 152 | "version": "1.0.4", 153 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 154 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 155 | }, 156 | "dicer": { 157 | "version": "0.2.5", 158 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", 159 | "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", 160 | "requires": { 161 | "readable-stream": "1.1.x", 162 | "streamsearch": "0.1.2" 163 | } 164 | }, 165 | "ee-first": { 166 | "version": "1.0.5", 167 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.5.tgz", 168 | "integrity": "sha1-jJshKJjYzZ8alDZlDOe+ICyen/A=" 169 | }, 170 | "ejs": { 171 | "version": "2.6.1", 172 | "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", 173 | "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" 174 | }, 175 | "encodeurl": { 176 | "version": "1.0.2", 177 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 178 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 179 | }, 180 | "error": { 181 | "version": "2.0.4", 182 | "resolved": "https://registry.npmjs.org/error/-/error-2.0.4.tgz", 183 | "integrity": "sha1-tq2QiFsFZzgyBNhd564bzFlGRUg=", 184 | "requires": { 185 | "xtend": "~2.1.1" 186 | } 187 | }, 188 | "escape-html": { 189 | "version": "1.0.3", 190 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 191 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 192 | }, 193 | "etag": { 194 | "version": "1.8.1", 195 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 196 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 197 | }, 198 | "express": { 199 | "version": "4.16.3", 200 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", 201 | "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", 202 | "requires": { 203 | "accepts": "~1.3.5", 204 | "array-flatten": "1.1.1", 205 | "body-parser": "1.18.2", 206 | "content-disposition": "0.5.2", 207 | "content-type": "~1.0.4", 208 | "cookie": "0.3.1", 209 | "cookie-signature": "1.0.6", 210 | "debug": "2.6.9", 211 | "depd": "~1.1.2", 212 | "encodeurl": "~1.0.2", 213 | "escape-html": "~1.0.3", 214 | "etag": "~1.8.1", 215 | "finalhandler": "1.1.1", 216 | "fresh": "0.5.2", 217 | "merge-descriptors": "1.0.1", 218 | "methods": "~1.1.2", 219 | "on-finished": "~2.3.0", 220 | "parseurl": "~1.3.2", 221 | "path-to-regexp": "0.1.7", 222 | "proxy-addr": "~2.0.3", 223 | "qs": "6.5.1", 224 | "range-parser": "~1.2.0", 225 | "safe-buffer": "5.1.1", 226 | "send": "0.16.2", 227 | "serve-static": "1.13.2", 228 | "setprototypeof": "1.1.0", 229 | "statuses": "~1.4.0", 230 | "type-is": "~1.6.16", 231 | "utils-merge": "1.0.1", 232 | "vary": "~1.1.2" 233 | }, 234 | "dependencies": { 235 | "body-parser": { 236 | "version": "1.18.2", 237 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 238 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 239 | "requires": { 240 | "bytes": "3.0.0", 241 | "content-type": "~1.0.4", 242 | "debug": "2.6.9", 243 | "depd": "~1.1.1", 244 | "http-errors": "~1.6.2", 245 | "iconv-lite": "0.4.19", 246 | "on-finished": "~2.3.0", 247 | "qs": "6.5.1", 248 | "raw-body": "2.3.2", 249 | "type-is": "~1.6.15" 250 | } 251 | }, 252 | "bytes": { 253 | "version": "3.0.0", 254 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 255 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 256 | }, 257 | "cookie": { 258 | "version": "0.3.1", 259 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 260 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 261 | }, 262 | "depd": { 263 | "version": "1.1.2", 264 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 265 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 266 | }, 267 | "ee-first": { 268 | "version": "1.1.1", 269 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 270 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 271 | }, 272 | "iconv-lite": { 273 | "version": "0.4.19", 274 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 275 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 276 | }, 277 | "mime-db": { 278 | "version": "1.36.0", 279 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", 280 | "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" 281 | }, 282 | "mime-types": { 283 | "version": "2.1.20", 284 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", 285 | "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", 286 | "requires": { 287 | "mime-db": "~1.36.0" 288 | } 289 | }, 290 | "on-finished": { 291 | "version": "2.3.0", 292 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 293 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 294 | "requires": { 295 | "ee-first": "1.1.1" 296 | } 297 | }, 298 | "qs": { 299 | "version": "6.5.1", 300 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 301 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 302 | }, 303 | "raw-body": { 304 | "version": "2.3.2", 305 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 306 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 307 | "requires": { 308 | "bytes": "3.0.0", 309 | "http-errors": "1.6.2", 310 | "iconv-lite": "0.4.19", 311 | "unpipe": "1.0.0" 312 | }, 313 | "dependencies": { 314 | "depd": { 315 | "version": "1.1.1", 316 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 317 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 318 | }, 319 | "http-errors": { 320 | "version": "1.6.2", 321 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 322 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 323 | "requires": { 324 | "depd": "1.1.1", 325 | "inherits": "2.0.3", 326 | "setprototypeof": "1.0.3", 327 | "statuses": ">= 1.3.1 < 2" 328 | } 329 | }, 330 | "setprototypeof": { 331 | "version": "1.0.3", 332 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 333 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 334 | } 335 | } 336 | }, 337 | "type-is": { 338 | "version": "1.6.16", 339 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 340 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 341 | "requires": { 342 | "media-typer": "0.3.0", 343 | "mime-types": "~2.1.18" 344 | } 345 | } 346 | } 347 | }, 348 | "express-busboy": { 349 | "version": "2.1.0", 350 | "resolved": "https://registry.npmjs.org/express-busboy/-/express-busboy-2.1.0.tgz", 351 | "integrity": "sha1-RSn58D7cxTLMozr6S5qXq5i/Xhk=", 352 | "requires": { 353 | "body": "~4.5.0", 354 | "connect-busboy": "~0.0.1", 355 | "mkdirp": "~0.5.0", 356 | "qs": "^2.3.2", 357 | "uuid": "~1.4.1" 358 | }, 359 | "dependencies": { 360 | "qs": { 361 | "version": "2.4.2", 362 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz", 363 | "integrity": "sha1-9854jld33wtQENp/fE5zujJHD1o=" 364 | } 365 | } 366 | }, 367 | "finalhandler": { 368 | "version": "1.1.1", 369 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 370 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 371 | "requires": { 372 | "debug": "2.6.9", 373 | "encodeurl": "~1.0.2", 374 | "escape-html": "~1.0.3", 375 | "on-finished": "~2.3.0", 376 | "parseurl": "~1.3.2", 377 | "statuses": "~1.4.0", 378 | "unpipe": "~1.0.0" 379 | }, 380 | "dependencies": { 381 | "ee-first": { 382 | "version": "1.1.1", 383 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 384 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 385 | }, 386 | "on-finished": { 387 | "version": "2.3.0", 388 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 389 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 390 | "requires": { 391 | "ee-first": "1.1.1" 392 | } 393 | } 394 | } 395 | }, 396 | "forwarded": { 397 | "version": "0.1.2", 398 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 399 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 400 | }, 401 | "fresh": { 402 | "version": "0.5.2", 403 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 404 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 405 | }, 406 | "http-errors": { 407 | "version": "1.6.3", 408 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 409 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 410 | "requires": { 411 | "depd": "~1.1.2", 412 | "inherits": "2.0.3", 413 | "setprototypeof": "1.1.0", 414 | "statuses": ">= 1.4.0 < 2" 415 | }, 416 | "dependencies": { 417 | "depd": { 418 | "version": "1.1.2", 419 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 420 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 421 | } 422 | } 423 | }, 424 | "iconv-lite": { 425 | "version": "0.4.4", 426 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.4.tgz", 427 | "integrity": "sha1-6V8uQdsHNfwhZS94J6XuMuY8g6g=" 428 | }, 429 | "inherits": { 430 | "version": "2.0.3", 431 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 432 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 433 | }, 434 | "ipaddr.js": { 435 | "version": "1.8.0", 436 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 437 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" 438 | }, 439 | "isarray": { 440 | "version": "0.0.1", 441 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 442 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 443 | }, 444 | "media-typer": { 445 | "version": "0.3.0", 446 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 447 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 448 | }, 449 | "merge-descriptors": { 450 | "version": "1.0.1", 451 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 452 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 453 | }, 454 | "methods": { 455 | "version": "1.1.2", 456 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 457 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 458 | }, 459 | "mime": { 460 | "version": "1.4.1", 461 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 462 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 463 | }, 464 | "mime-db": { 465 | "version": "1.12.0", 466 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", 467 | "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=" 468 | }, 469 | "mime-types": { 470 | "version": "2.0.14", 471 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", 472 | "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", 473 | "requires": { 474 | "mime-db": "~1.12.0" 475 | } 476 | }, 477 | "minimist": { 478 | "version": "0.0.8", 479 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 480 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 481 | }, 482 | "mkdirp": { 483 | "version": "0.5.1", 484 | "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 485 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 486 | "requires": { 487 | "minimist": "0.0.8" 488 | } 489 | }, 490 | "morgan": { 491 | "version": "1.3.2", 492 | "resolved": "http://registry.npmjs.org/morgan/-/morgan-1.3.2.tgz", 493 | "integrity": "sha1-rEGqFSIe5OXyrIQ4lraRgTmhjv0=", 494 | "requires": { 495 | "basic-auth": "1.0.0", 496 | "depd": "0.4.5", 497 | "on-finished": "2.1.0" 498 | } 499 | }, 500 | "ms": { 501 | "version": "2.0.0", 502 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 503 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 504 | }, 505 | "negotiator": { 506 | "version": "0.6.1", 507 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 508 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 509 | }, 510 | "object-keys": { 511 | "version": "0.4.0", 512 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", 513 | "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" 514 | }, 515 | "on-finished": { 516 | "version": "2.1.0", 517 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.1.0.tgz", 518 | "integrity": "sha1-DFOfCSkej/rd4MiiWFD7LO3HAi0=", 519 | "requires": { 520 | "ee-first": "1.0.5" 521 | } 522 | }, 523 | "parseurl": { 524 | "version": "1.3.2", 525 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 526 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 527 | }, 528 | "path-to-regexp": { 529 | "version": "0.1.7", 530 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 531 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 532 | }, 533 | "proxy-addr": { 534 | "version": "2.0.4", 535 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 536 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 537 | "requires": { 538 | "forwarded": "~0.1.2", 539 | "ipaddr.js": "1.8.0" 540 | } 541 | }, 542 | "qs": { 543 | "version": "2.2.4", 544 | "resolved": "https://registry.npmjs.org/qs/-/qs-2.2.4.tgz", 545 | "integrity": "sha1-Lp+800tUDjQhySTs0B6QqpdTGcg=" 546 | }, 547 | "randomstring": { 548 | "version": "1.1.5", 549 | "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.1.5.tgz", 550 | "integrity": "sha1-bfBij3XL1ZMpMNn+OrTpVqGFGMM=", 551 | "requires": { 552 | "array-uniq": "1.0.2" 553 | } 554 | }, 555 | "range-parser": { 556 | "version": "1.2.0", 557 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 558 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 559 | }, 560 | "raw-body": { 561 | "version": "1.3.0", 562 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.0.tgz", 563 | "integrity": "sha1-l4IwoValVI9C7vFN4i0PT2EAg9E=", 564 | "requires": { 565 | "bytes": "1", 566 | "iconv-lite": "0.4.4" 567 | } 568 | }, 569 | "readable-stream": { 570 | "version": "1.1.14", 571 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 572 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 573 | "requires": { 574 | "core-util-is": "~1.0.0", 575 | "inherits": "~2.0.1", 576 | "isarray": "0.0.1", 577 | "string_decoder": "~0.10.x" 578 | } 579 | }, 580 | "redis": { 581 | "version": "0.12.1", 582 | "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz", 583 | "integrity": "sha1-ZN92rQ/IrOuuvSoGReikj6xJGF4=" 584 | }, 585 | "safe-buffer": { 586 | "version": "5.1.1", 587 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 588 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 589 | }, 590 | "safe-json-parse": { 591 | "version": "1.0.1", 592 | "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", 593 | "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=" 594 | }, 595 | "send": { 596 | "version": "0.16.2", 597 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 598 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 599 | "requires": { 600 | "debug": "2.6.9", 601 | "depd": "~1.1.2", 602 | "destroy": "~1.0.4", 603 | "encodeurl": "~1.0.2", 604 | "escape-html": "~1.0.3", 605 | "etag": "~1.8.1", 606 | "fresh": "0.5.2", 607 | "http-errors": "~1.6.2", 608 | "mime": "1.4.1", 609 | "ms": "2.0.0", 610 | "on-finished": "~2.3.0", 611 | "range-parser": "~1.2.0", 612 | "statuses": "~1.4.0" 613 | }, 614 | "dependencies": { 615 | "depd": { 616 | "version": "1.1.2", 617 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 618 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 619 | }, 620 | "ee-first": { 621 | "version": "1.1.1", 622 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 623 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 624 | }, 625 | "on-finished": { 626 | "version": "2.3.0", 627 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 628 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 629 | "requires": { 630 | "ee-first": "1.1.1" 631 | } 632 | } 633 | } 634 | }, 635 | "serve-favicon": { 636 | "version": "2.5.0", 637 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", 638 | "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", 639 | "requires": { 640 | "etag": "~1.8.1", 641 | "fresh": "0.5.2", 642 | "ms": "2.1.1", 643 | "parseurl": "~1.3.2", 644 | "safe-buffer": "5.1.1" 645 | }, 646 | "dependencies": { 647 | "ms": { 648 | "version": "2.1.1", 649 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 650 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 651 | } 652 | } 653 | }, 654 | "serve-static": { 655 | "version": "1.13.2", 656 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 657 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 658 | "requires": { 659 | "encodeurl": "~1.0.2", 660 | "escape-html": "~1.0.3", 661 | "parseurl": "~1.3.2", 662 | "send": "0.16.2" 663 | } 664 | }, 665 | "setprototypeof": { 666 | "version": "1.1.0", 667 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 668 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 669 | }, 670 | "statuses": { 671 | "version": "1.4.0", 672 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 673 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 674 | }, 675 | "streamsearch": { 676 | "version": "0.1.2", 677 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 678 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 679 | }, 680 | "string_decoder": { 681 | "version": "0.10.31", 682 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 683 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 684 | }, 685 | "type-is": { 686 | "version": "1.5.7", 687 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.5.7.tgz", 688 | "integrity": "sha1-uTaKWTzG730GReeLL0xky+zQXpA=", 689 | "requires": { 690 | "media-typer": "0.3.0", 691 | "mime-types": "~2.0.9" 692 | } 693 | }, 694 | "ua-parser": { 695 | "version": "0.3.5", 696 | "resolved": "https://registry.npmjs.org/ua-parser/-/ua-parser-0.3.5.tgz", 697 | "integrity": "sha1-L/T5yebi1k1xFGHxe+ssnGl/Lxo=", 698 | "requires": { 699 | "yamlparser": ">=0.0.2" 700 | } 701 | }, 702 | "unpipe": { 703 | "version": "1.0.0", 704 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 705 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 706 | }, 707 | "utils-merge": { 708 | "version": "1.0.1", 709 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 710 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 711 | }, 712 | "uuid": { 713 | "version": "1.4.2", 714 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-1.4.2.tgz", 715 | "integrity": "sha1-RTAZ9oaWam34PNxSROfJkOzDMvw=" 716 | }, 717 | "vary": { 718 | "version": "1.1.2", 719 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 720 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 721 | }, 722 | "xtend": { 723 | "version": "2.1.2", 724 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", 725 | "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", 726 | "requires": { 727 | "object-keys": "~0.4.0" 728 | } 729 | }, 730 | "yamlparser": { 731 | "version": "0.0.2", 732 | "resolved": "https://registry.npmjs.org/yamlparser/-/yamlparser-0.0.2.tgz", 733 | "integrity": "sha1-Mjk+avxwyMoGa2ZQrGc4tIFnjrw=" 734 | } 735 | } 736 | } 737 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csptester", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.8.1", 10 | "cookie-parser": "~1.3.3", 11 | "debug": "^2.0.0", 12 | "ejs": "^2.6.1", 13 | "express": "^4.9.8", 14 | "express-busboy": "~2.1.0", 15 | "morgan": "~1.3.0", 16 | "randomstring": "^1.0.3", 17 | "redis": "~0.12.1", 18 | "serve-favicon": "^2.5.0", 19 | "ua-parser": "~0.3.5" 20 | }, 21 | "description": "A quick and easy way to test CSP behaviour across all modern browsers", 22 | "main": "index.js", 23 | "keywords": [ 24 | "csp" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "http://github.com/yahoo/csptester.git" 29 | }, 30 | "licenses": [ 31 | { 32 | "type": "BSD", 33 | "url": "https://raw.github.com/yahoo/csptester/master/LICENSE.md" 34 | } 35 | ], 36 | "author": "Binu P Ramakrishnan " 37 | } 38 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YahooArchive/csptester/08d342d9596bde67dea23c9e610577349eec87cd/public/favicon.ico -------------------------------------------------------------------------------- /public/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YahooArchive/csptester/08d342d9596bde67dea23c9e610577349eec87cd/public/images/spinner.gif -------------------------------------------------------------------------------- /public/javascripts/test-share-script.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author Binu P. Ramakrishnan 7 | // Created 01/05/2015 8 | // 9 | 10 | window.addEventListener('load', converToLocaleDate, false); 11 | function converToLocaleDate(){ 12 | if (document.getElementById("expirytime") != undefined) { 13 | var ts = document.getElementById("expirytime").textContent; 14 | d = new Date(parseInt(ts)); 15 | document.getElementById("expirytime").textContent = d.toLocaleString(); 16 | } 17 | 18 | if (document.getElementById("share-url") != undefined) { 19 | // i dont like this, but this should work for now 20 | document.getElementById("share-url").value = (document.URL).split("&")[0]; 21 | document.getElementById("share-url").select(); 22 | } 23 | 24 | } 25 | 26 | if (document.getElementById("share-link") != undefined) { 27 | document.getElementById("share-link").addEventListener("click", shareLink); 28 | } 29 | 30 | function shareLink(e) { 31 | e.preventDefault(); 32 | var share_uri = document.getElementById("share-uri").textContent; 33 | document.location.assign(share_uri); 34 | } 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /public/javascripts/test-window.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author Binu P. Ramakrishnan 7 | // Created 01/05/2015 8 | // 9 | // test_window.ejs 10 | 11 | document.getElementById("report-link").addEventListener("click", reportRedirect); 12 | 13 | function reportRedirect(e) { 14 | e.preventDefault(); 15 | var test_uri = document.getElementById("test-uri").textContent; 16 | var report_uri = document.getElementById("report-uri").textContent; 17 | 18 | var myPopup = window.open(report_uri, "_blank"); 19 | window.location.replace(test_uri); 20 | return false; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /public/javascripts/testscript.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2015, Yahoo Inc. 3 | // Copyrights licensed under the New BSD License. See the 4 | // accompanying LICENSE.txt file for terms. 5 | // 6 | // Author Binu P. Ramakrishnan 7 | // Created 01/05/2015 8 | // 9 | 10 | function getCSPViolationReport() { 11 | var xmlhttp; 12 | if (window.XMLHttpRequest) { 13 | // code for IE7+, Firefox, Chrome, Opera, Safari 14 | xmlhttp = new XMLHttpRequest(); 15 | } else { 16 | // code for IE6, IE5 17 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 18 | } 19 | 20 | xmlhttp.onreadystatechange=function() { 21 | if (xmlhttp.readyState === 4) { 22 | 23 | if (xmlhttp.status === 200) { 24 | 25 | if (xmlhttp.responseText) { 26 | document.getElementById("cspreportdiv").innerHTML = xmlhttp.responseText; 27 | document.getElementById("noviolationmsg").style.display = 'none'; 28 | } else { 29 | document.getElementById("noviolationmsg").innerHTML = "
"; 30 | document.getElementById("noviolationmsg").style.display = 'block'; 31 | } 32 | 33 | document.getElementById("loading").style.display = 'none'; 34 | } 35 | 36 | if (times++ === maxtimes) { 37 | clearInterval(nIntervId); 38 | if (!xmlhttp.responseText) { 39 | document.getElementById("noviolationmsg").innerHTML = "
No violation reported
"; 40 | } 41 | } 42 | } 43 | }; 44 | 45 | var testsrc = "/report/" + document.getElementById("testid").textContent; 46 | xmlhttp.open("GET", testsrc, true); 47 | xmlhttp.send(); 48 | } 49 | 50 | var times = 0; 51 | var maxtimes = 10; 52 | var nIntervId = setInterval(getCSPViolationReport, 2000); 53 | 54 | // jquery is used only for resize functionality 55 | $(function() { 56 | $( "#topdiv" ).resizable({ axis: "y" }); 57 | $( "#bottomdiv" ).resizable({ axis: "y" }); 58 | $( "#noviolationmsg" ).hide(); 59 | }); 60 | 61 | 62 | -------------------------------------------------------------------------------- /public/stylesheets/jquery/1.11.2/themes/smoothness/jquery-ui.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.11.2 - 2014-10-16 2 | * http://jqueryui.com 3 | * Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css 4 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 5 | * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ 6 | 7 | /* Layout helpers 8 | ----------------------------------*/ 9 | .ui-helper-hidden { 10 | display: none; 11 | } 12 | .ui-helper-hidden-accessible { 13 | border: 0; 14 | clip: rect(0 0 0 0); 15 | height: 1px; 16 | margin: -1px; 17 | overflow: hidden; 18 | padding: 0; 19 | position: absolute; 20 | width: 1px; 21 | } 22 | .ui-helper-reset { 23 | margin: 0; 24 | padding: 0; 25 | border: 0; 26 | outline: 0; 27 | line-height: 1.3; 28 | text-decoration: none; 29 | font-size: 100%; 30 | list-style: none; 31 | } 32 | .ui-helper-clearfix:before, 33 | .ui-helper-clearfix:after { 34 | content: ""; 35 | display: table; 36 | border-collapse: collapse; 37 | } 38 | .ui-helper-clearfix:after { 39 | clear: both; 40 | } 41 | .ui-helper-clearfix { 42 | min-height: 0; /* support: IE7 */ 43 | } 44 | .ui-helper-zfix { 45 | width: 100%; 46 | height: 100%; 47 | top: 0; 48 | left: 0; 49 | position: absolute; 50 | opacity: 0; 51 | filter:Alpha(Opacity=0); /* support: IE8 */ 52 | } 53 | 54 | .ui-front { 55 | z-index: 100; 56 | } 57 | 58 | 59 | /* Interaction Cues 60 | ----------------------------------*/ 61 | .ui-state-disabled { 62 | cursor: default !important; 63 | } 64 | 65 | 66 | /* Icons 67 | ----------------------------------*/ 68 | 69 | /* states and images */ 70 | .ui-icon { 71 | display: block; 72 | text-indent: -99999px; 73 | overflow: hidden; 74 | background-repeat: no-repeat; 75 | } 76 | 77 | 78 | /* Misc visuals 79 | ----------------------------------*/ 80 | 81 | /* Overlays */ 82 | .ui-widget-overlay { 83 | position: fixed; 84 | top: 0; 85 | left: 0; 86 | width: 100%; 87 | height: 100%; 88 | } 89 | .ui-accordion .ui-accordion-header { 90 | display: block; 91 | cursor: pointer; 92 | position: relative; 93 | margin: 2px 0 0 0; 94 | padding: .5em .5em .5em .7em; 95 | min-height: 0; /* support: IE7 */ 96 | font-size: 100%; 97 | } 98 | .ui-accordion .ui-accordion-icons { 99 | padding-left: 2.2em; 100 | } 101 | .ui-accordion .ui-accordion-icons .ui-accordion-icons { 102 | padding-left: 2.2em; 103 | } 104 | .ui-accordion .ui-accordion-header .ui-accordion-header-icon { 105 | position: absolute; 106 | left: .5em; 107 | top: 50%; 108 | margin-top: -8px; 109 | } 110 | .ui-accordion .ui-accordion-content { 111 | padding: 1em 2.2em; 112 | border-top: 0; 113 | overflow: auto; 114 | } 115 | .ui-autocomplete { 116 | position: absolute; 117 | top: 0; 118 | left: 0; 119 | cursor: default; 120 | } 121 | .ui-button { 122 | display: inline-block; 123 | position: relative; 124 | padding: 0; 125 | line-height: normal; 126 | margin-right: .1em; 127 | cursor: pointer; 128 | vertical-align: middle; 129 | text-align: center; 130 | overflow: visible; /* removes extra width in IE */ 131 | } 132 | .ui-button, 133 | .ui-button:link, 134 | .ui-button:visited, 135 | .ui-button:hover, 136 | .ui-button:active { 137 | text-decoration: none; 138 | } 139 | /* to make room for the icon, a width needs to be set here */ 140 | .ui-button-icon-only { 141 | width: 2.2em; 142 | } 143 | /* button elements seem to need a little more width */ 144 | button.ui-button-icon-only { 145 | width: 2.4em; 146 | } 147 | .ui-button-icons-only { 148 | width: 3.4em; 149 | } 150 | button.ui-button-icons-only { 151 | width: 3.7em; 152 | } 153 | 154 | /* button text element */ 155 | .ui-button .ui-button-text { 156 | display: block; 157 | line-height: normal; 158 | } 159 | .ui-button-text-only .ui-button-text { 160 | padding: .4em 1em; 161 | } 162 | .ui-button-icon-only .ui-button-text, 163 | .ui-button-icons-only .ui-button-text { 164 | padding: .4em; 165 | text-indent: -9999999px; 166 | } 167 | .ui-button-text-icon-primary .ui-button-text, 168 | .ui-button-text-icons .ui-button-text { 169 | padding: .4em 1em .4em 2.1em; 170 | } 171 | .ui-button-text-icon-secondary .ui-button-text, 172 | .ui-button-text-icons .ui-button-text { 173 | padding: .4em 2.1em .4em 1em; 174 | } 175 | .ui-button-text-icons .ui-button-text { 176 | padding-left: 2.1em; 177 | padding-right: 2.1em; 178 | } 179 | /* no icon support for input elements, provide padding by default */ 180 | input.ui-button { 181 | padding: .4em 1em; 182 | } 183 | 184 | /* button icon element(s) */ 185 | .ui-button-icon-only .ui-icon, 186 | .ui-button-text-icon-primary .ui-icon, 187 | .ui-button-text-icon-secondary .ui-icon, 188 | .ui-button-text-icons .ui-icon, 189 | .ui-button-icons-only .ui-icon { 190 | position: absolute; 191 | top: 50%; 192 | margin-top: -8px; 193 | } 194 | .ui-button-icon-only .ui-icon { 195 | left: 50%; 196 | margin-left: -8px; 197 | } 198 | .ui-button-text-icon-primary .ui-button-icon-primary, 199 | .ui-button-text-icons .ui-button-icon-primary, 200 | .ui-button-icons-only .ui-button-icon-primary { 201 | left: .5em; 202 | } 203 | .ui-button-text-icon-secondary .ui-button-icon-secondary, 204 | .ui-button-text-icons .ui-button-icon-secondary, 205 | .ui-button-icons-only .ui-button-icon-secondary { 206 | right: .5em; 207 | } 208 | 209 | /* button sets */ 210 | .ui-buttonset { 211 | margin-right: 7px; 212 | } 213 | .ui-buttonset .ui-button { 214 | margin-left: 0; 215 | margin-right: -.3em; 216 | } 217 | 218 | /* workarounds */ 219 | /* reset extra padding in Firefox, see h5bp.com/l */ 220 | input.ui-button::-moz-focus-inner, 221 | button.ui-button::-moz-focus-inner { 222 | border: 0; 223 | padding: 0; 224 | } 225 | .ui-datepicker { 226 | width: 17em; 227 | padding: .2em .2em 0; 228 | display: none; 229 | } 230 | .ui-datepicker .ui-datepicker-header { 231 | position: relative; 232 | padding: .2em 0; 233 | } 234 | .ui-datepicker .ui-datepicker-prev, 235 | .ui-datepicker .ui-datepicker-next { 236 | position: absolute; 237 | top: 2px; 238 | width: 1.8em; 239 | height: 1.8em; 240 | } 241 | .ui-datepicker .ui-datepicker-prev-hover, 242 | .ui-datepicker .ui-datepicker-next-hover { 243 | top: 1px; 244 | } 245 | .ui-datepicker .ui-datepicker-prev { 246 | left: 2px; 247 | } 248 | .ui-datepicker .ui-datepicker-next { 249 | right: 2px; 250 | } 251 | .ui-datepicker .ui-datepicker-prev-hover { 252 | left: 1px; 253 | } 254 | .ui-datepicker .ui-datepicker-next-hover { 255 | right: 1px; 256 | } 257 | .ui-datepicker .ui-datepicker-prev span, 258 | .ui-datepicker .ui-datepicker-next span { 259 | display: block; 260 | position: absolute; 261 | left: 50%; 262 | margin-left: -8px; 263 | top: 50%; 264 | margin-top: -8px; 265 | } 266 | .ui-datepicker .ui-datepicker-title { 267 | margin: 0 2.3em; 268 | line-height: 1.8em; 269 | text-align: center; 270 | } 271 | .ui-datepicker .ui-datepicker-title select { 272 | font-size: 1em; 273 | margin: 1px 0; 274 | } 275 | .ui-datepicker select.ui-datepicker-month, 276 | .ui-datepicker select.ui-datepicker-year { 277 | width: 45%; 278 | } 279 | .ui-datepicker table { 280 | width: 100%; 281 | font-size: .9em; 282 | border-collapse: collapse; 283 | margin: 0 0 .4em; 284 | } 285 | .ui-datepicker th { 286 | padding: .7em .3em; 287 | text-align: center; 288 | font-weight: bold; 289 | border: 0; 290 | } 291 | .ui-datepicker td { 292 | border: 0; 293 | padding: 1px; 294 | } 295 | .ui-datepicker td span, 296 | .ui-datepicker td a { 297 | display: block; 298 | padding: .2em; 299 | text-align: right; 300 | text-decoration: none; 301 | } 302 | .ui-datepicker .ui-datepicker-buttonpane { 303 | background-image: none; 304 | margin: .7em 0 0 0; 305 | padding: 0 .2em; 306 | border-left: 0; 307 | border-right: 0; 308 | border-bottom: 0; 309 | } 310 | .ui-datepicker .ui-datepicker-buttonpane button { 311 | float: right; 312 | margin: .5em .2em .4em; 313 | cursor: pointer; 314 | padding: .2em .6em .3em .6em; 315 | width: auto; 316 | overflow: visible; 317 | } 318 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { 319 | float: left; 320 | } 321 | 322 | /* with multiple calendars */ 323 | .ui-datepicker.ui-datepicker-multi { 324 | width: auto; 325 | } 326 | .ui-datepicker-multi .ui-datepicker-group { 327 | float: left; 328 | } 329 | .ui-datepicker-multi .ui-datepicker-group table { 330 | width: 95%; 331 | margin: 0 auto .4em; 332 | } 333 | .ui-datepicker-multi-2 .ui-datepicker-group { 334 | width: 50%; 335 | } 336 | .ui-datepicker-multi-3 .ui-datepicker-group { 337 | width: 33.3%; 338 | } 339 | .ui-datepicker-multi-4 .ui-datepicker-group { 340 | width: 25%; 341 | } 342 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, 343 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { 344 | border-left-width: 0; 345 | } 346 | .ui-datepicker-multi .ui-datepicker-buttonpane { 347 | clear: left; 348 | } 349 | .ui-datepicker-row-break { 350 | clear: both; 351 | width: 100%; 352 | font-size: 0; 353 | } 354 | 355 | /* RTL support */ 356 | .ui-datepicker-rtl { 357 | direction: rtl; 358 | } 359 | .ui-datepicker-rtl .ui-datepicker-prev { 360 | right: 2px; 361 | left: auto; 362 | } 363 | .ui-datepicker-rtl .ui-datepicker-next { 364 | left: 2px; 365 | right: auto; 366 | } 367 | .ui-datepicker-rtl .ui-datepicker-prev:hover { 368 | right: 1px; 369 | left: auto; 370 | } 371 | .ui-datepicker-rtl .ui-datepicker-next:hover { 372 | left: 1px; 373 | right: auto; 374 | } 375 | .ui-datepicker-rtl .ui-datepicker-buttonpane { 376 | clear: right; 377 | } 378 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { 379 | float: left; 380 | } 381 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, 382 | .ui-datepicker-rtl .ui-datepicker-group { 383 | float: right; 384 | } 385 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, 386 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { 387 | border-right-width: 0; 388 | border-left-width: 1px; 389 | } 390 | .ui-dialog { 391 | overflow: hidden; 392 | position: absolute; 393 | top: 0; 394 | left: 0; 395 | padding: .2em; 396 | outline: 0; 397 | } 398 | .ui-dialog .ui-dialog-titlebar { 399 | padding: .4em 1em; 400 | position: relative; 401 | } 402 | .ui-dialog .ui-dialog-title { 403 | float: left; 404 | margin: .1em 0; 405 | white-space: nowrap; 406 | width: 90%; 407 | overflow: hidden; 408 | text-overflow: ellipsis; 409 | } 410 | .ui-dialog .ui-dialog-titlebar-close { 411 | position: absolute; 412 | right: .3em; 413 | top: 50%; 414 | width: 20px; 415 | margin: -10px 0 0 0; 416 | padding: 1px; 417 | height: 20px; 418 | } 419 | .ui-dialog .ui-dialog-content { 420 | position: relative; 421 | border: 0; 422 | padding: .5em 1em; 423 | background: none; 424 | overflow: auto; 425 | } 426 | .ui-dialog .ui-dialog-buttonpane { 427 | text-align: left; 428 | border-width: 1px 0 0 0; 429 | background-image: none; 430 | margin-top: .5em; 431 | padding: .3em 1em .5em .4em; 432 | } 433 | .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { 434 | float: right; 435 | } 436 | .ui-dialog .ui-dialog-buttonpane button { 437 | margin: .5em .4em .5em 0; 438 | cursor: pointer; 439 | } 440 | .ui-dialog .ui-resizable-se { 441 | width: 12px; 442 | height: 12px; 443 | right: -5px; 444 | bottom: -5px; 445 | background-position: 16px 16px; 446 | } 447 | .ui-draggable .ui-dialog-titlebar { 448 | cursor: move; 449 | } 450 | .ui-draggable-handle { 451 | -ms-touch-action: none; 452 | touch-action: none; 453 | } 454 | .ui-menu { 455 | list-style: none; 456 | padding: 0; 457 | margin: 0; 458 | display: block; 459 | outline: none; 460 | } 461 | .ui-menu .ui-menu { 462 | position: absolute; 463 | } 464 | .ui-menu .ui-menu-item { 465 | position: relative; 466 | margin: 0; 467 | padding: 3px 1em 3px .4em; 468 | cursor: pointer; 469 | min-height: 0; /* support: IE7 */ 470 | /* support: IE10, see #8844 */ 471 | list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); 472 | } 473 | .ui-menu .ui-menu-divider { 474 | margin: 5px 0; 475 | height: 0; 476 | font-size: 0; 477 | line-height: 0; 478 | border-width: 1px 0 0 0; 479 | } 480 | .ui-menu .ui-state-focus, 481 | .ui-menu .ui-state-active { 482 | margin: -1px; 483 | } 484 | 485 | /* icon support */ 486 | .ui-menu-icons { 487 | position: relative; 488 | } 489 | .ui-menu-icons .ui-menu-item { 490 | padding-left: 2em; 491 | } 492 | 493 | /* left-aligned */ 494 | .ui-menu .ui-icon { 495 | position: absolute; 496 | top: 0; 497 | bottom: 0; 498 | left: .2em; 499 | margin: auto 0; 500 | } 501 | 502 | /* right-aligned */ 503 | .ui-menu .ui-menu-icon { 504 | left: auto; 505 | right: 0; 506 | } 507 | .ui-progressbar { 508 | height: 2em; 509 | text-align: left; 510 | overflow: hidden; 511 | } 512 | .ui-progressbar .ui-progressbar-value { 513 | margin: -1px; 514 | height: 100%; 515 | } 516 | .ui-progressbar .ui-progressbar-overlay { 517 | background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw=="); 518 | height: 100%; 519 | filter: alpha(opacity=25); /* support: IE8 */ 520 | opacity: 0.25; 521 | } 522 | .ui-progressbar-indeterminate .ui-progressbar-value { 523 | background-image: none; 524 | } 525 | .ui-resizable { 526 | position: relative; 527 | } 528 | .ui-resizable-handle { 529 | position: absolute; 530 | font-size: 0.1px; 531 | display: block; 532 | -ms-touch-action: none; 533 | touch-action: none; 534 | } 535 | .ui-resizable-disabled .ui-resizable-handle, 536 | .ui-resizable-autohide .ui-resizable-handle { 537 | display: none; 538 | } 539 | .ui-resizable-n { 540 | cursor: n-resize; 541 | height: 7px; 542 | width: 100%; 543 | top: -5px; 544 | left: 0; 545 | } 546 | .ui-resizable-s { 547 | cursor: s-resize; 548 | height: 7px; 549 | width: 100%; 550 | bottom: -5px; 551 | left: 0; 552 | } 553 | .ui-resizable-e { 554 | cursor: e-resize; 555 | width: 7px; 556 | right: -5px; 557 | top: 0; 558 | height: 100%; 559 | } 560 | .ui-resizable-w { 561 | cursor: w-resize; 562 | width: 7px; 563 | left: -5px; 564 | top: 0; 565 | height: 100%; 566 | } 567 | .ui-resizable-se { 568 | cursor: se-resize; 569 | width: 12px; 570 | height: 12px; 571 | right: 1px; 572 | bottom: 1px; 573 | } 574 | .ui-resizable-sw { 575 | cursor: sw-resize; 576 | width: 9px; 577 | height: 9px; 578 | left: -5px; 579 | bottom: -5px; 580 | } 581 | .ui-resizable-nw { 582 | cursor: nw-resize; 583 | width: 9px; 584 | height: 9px; 585 | left: -5px; 586 | top: -5px; 587 | } 588 | .ui-resizable-ne { 589 | cursor: ne-resize; 590 | width: 9px; 591 | height: 9px; 592 | right: -5px; 593 | top: -5px; 594 | } 595 | .ui-selectable { 596 | -ms-touch-action: none; 597 | touch-action: none; 598 | } 599 | .ui-selectable-helper { 600 | position: absolute; 601 | z-index: 100; 602 | border: 1px dotted black; 603 | } 604 | .ui-selectmenu-menu { 605 | padding: 0; 606 | margin: 0; 607 | position: absolute; 608 | top: 0; 609 | left: 0; 610 | display: none; 611 | } 612 | .ui-selectmenu-menu .ui-menu { 613 | overflow: auto; 614 | /* Support: IE7 */ 615 | overflow-x: hidden; 616 | padding-bottom: 1px; 617 | } 618 | .ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { 619 | font-size: 1em; 620 | font-weight: bold; 621 | line-height: 1.5; 622 | padding: 2px 0.4em; 623 | margin: 0.5em 0 0 0; 624 | height: auto; 625 | border: 0; 626 | } 627 | .ui-selectmenu-open { 628 | display: block; 629 | } 630 | .ui-selectmenu-button { 631 | display: inline-block; 632 | overflow: hidden; 633 | position: relative; 634 | text-decoration: none; 635 | cursor: pointer; 636 | } 637 | .ui-selectmenu-button span.ui-icon { 638 | right: 0.5em; 639 | left: auto; 640 | margin-top: -8px; 641 | position: absolute; 642 | top: 50%; 643 | } 644 | .ui-selectmenu-button span.ui-selectmenu-text { 645 | text-align: left; 646 | padding: 0.4em 2.1em 0.4em 1em; 647 | display: block; 648 | line-height: 1.4; 649 | overflow: hidden; 650 | text-overflow: ellipsis; 651 | white-space: nowrap; 652 | } 653 | .ui-slider { 654 | position: relative; 655 | text-align: left; 656 | } 657 | .ui-slider .ui-slider-handle { 658 | position: absolute; 659 | z-index: 2; 660 | width: 1.2em; 661 | height: 1.2em; 662 | cursor: default; 663 | -ms-touch-action: none; 664 | touch-action: none; 665 | } 666 | .ui-slider .ui-slider-range { 667 | position: absolute; 668 | z-index: 1; 669 | font-size: .7em; 670 | display: block; 671 | border: 0; 672 | background-position: 0 0; 673 | } 674 | 675 | /* support: IE8 - See #6727 */ 676 | .ui-slider.ui-state-disabled .ui-slider-handle, 677 | .ui-slider.ui-state-disabled .ui-slider-range { 678 | filter: inherit; 679 | } 680 | 681 | .ui-slider-horizontal { 682 | height: .8em; 683 | } 684 | .ui-slider-horizontal .ui-slider-handle { 685 | top: -.3em; 686 | margin-left: -.6em; 687 | } 688 | .ui-slider-horizontal .ui-slider-range { 689 | top: 0; 690 | height: 100%; 691 | } 692 | .ui-slider-horizontal .ui-slider-range-min { 693 | left: 0; 694 | } 695 | .ui-slider-horizontal .ui-slider-range-max { 696 | right: 0; 697 | } 698 | 699 | .ui-slider-vertical { 700 | width: .8em; 701 | height: 100px; 702 | } 703 | .ui-slider-vertical .ui-slider-handle { 704 | left: -.3em; 705 | margin-left: 0; 706 | margin-bottom: -.6em; 707 | } 708 | .ui-slider-vertical .ui-slider-range { 709 | left: 0; 710 | width: 100%; 711 | } 712 | .ui-slider-vertical .ui-slider-range-min { 713 | bottom: 0; 714 | } 715 | .ui-slider-vertical .ui-slider-range-max { 716 | top: 0; 717 | } 718 | .ui-sortable-handle { 719 | -ms-touch-action: none; 720 | touch-action: none; 721 | } 722 | .ui-spinner { 723 | position: relative; 724 | display: inline-block; 725 | overflow: hidden; 726 | padding: 0; 727 | vertical-align: middle; 728 | } 729 | .ui-spinner-input { 730 | border: none; 731 | background: none; 732 | color: inherit; 733 | padding: 0; 734 | margin: .2em 0; 735 | vertical-align: middle; 736 | margin-left: .4em; 737 | margin-right: 22px; 738 | } 739 | .ui-spinner-button { 740 | width: 16px; 741 | height: 50%; 742 | font-size: .5em; 743 | padding: 0; 744 | margin: 0; 745 | text-align: center; 746 | position: absolute; 747 | cursor: default; 748 | display: block; 749 | overflow: hidden; 750 | right: 0; 751 | } 752 | /* more specificity required here to override default borders */ 753 | .ui-spinner a.ui-spinner-button { 754 | border-top: none; 755 | border-bottom: none; 756 | border-right: none; 757 | } 758 | /* vertically center icon */ 759 | .ui-spinner .ui-icon { 760 | position: absolute; 761 | margin-top: -8px; 762 | top: 50%; 763 | left: 0; 764 | } 765 | .ui-spinner-up { 766 | top: 0; 767 | } 768 | .ui-spinner-down { 769 | bottom: 0; 770 | } 771 | 772 | /* TR overrides */ 773 | .ui-spinner .ui-icon-triangle-1-s { 774 | /* need to fix icons sprite */ 775 | background-position: -65px -16px; 776 | } 777 | .ui-tabs { 778 | position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ 779 | padding: .2em; 780 | } 781 | .ui-tabs .ui-tabs-nav { 782 | margin: 0; 783 | padding: .2em .2em 0; 784 | } 785 | .ui-tabs .ui-tabs-nav li { 786 | list-style: none; 787 | float: left; 788 | position: relative; 789 | top: 0; 790 | margin: 1px .2em 0 0; 791 | border-bottom-width: 0; 792 | padding: 0; 793 | white-space: nowrap; 794 | } 795 | .ui-tabs .ui-tabs-nav .ui-tabs-anchor { 796 | float: left; 797 | padding: .5em 1em; 798 | text-decoration: none; 799 | } 800 | .ui-tabs .ui-tabs-nav li.ui-tabs-active { 801 | margin-bottom: -1px; 802 | padding-bottom: 1px; 803 | } 804 | .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, 805 | .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, 806 | .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { 807 | cursor: text; 808 | } 809 | .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { 810 | cursor: pointer; 811 | } 812 | .ui-tabs .ui-tabs-panel { 813 | display: block; 814 | border-width: 0; 815 | padding: 1em 1.4em; 816 | background: none; 817 | } 818 | .ui-tooltip { 819 | padding: 8px; 820 | position: absolute; 821 | z-index: 9999; 822 | max-width: 300px; 823 | -webkit-box-shadow: 0 0 5px #aaa; 824 | box-shadow: 0 0 5px #aaa; 825 | } 826 | body .ui-tooltip { 827 | border-width: 2px; 828 | } 829 | 830 | .ui-state-error a, 831 | .ui-widget-content .ui-state-error a, 832 | .ui-widget-header .ui-state-error a { 833 | color: #cd0a0a; 834 | } 835 | .ui-state-error-text, 836 | .ui-widget-content .ui-state-error-text, 837 | .ui-widget-header .ui-state-error-text { 838 | color: #cd0a0a; 839 | } 840 | .ui-priority-primary, 841 | .ui-widget-content .ui-priority-primary, 842 | .ui-widget-header .ui-priority-primary { 843 | font-weight: bold; 844 | } 845 | .ui-priority-secondary, 846 | .ui-widget-content .ui-priority-secondary, 847 | .ui-widget-header .ui-priority-secondary { 848 | opacity: .7; 849 | filter:Alpha(Opacity=70); /* support: IE8 */ 850 | font-weight: normal; 851 | } 852 | .ui-state-disabled, 853 | .ui-widget-content .ui-state-disabled, 854 | .ui-widget-header .ui-state-disabled { 855 | opacity: .35; 856 | filter:Alpha(Opacity=35); /* support: IE8 */ 857 | background-image: none; 858 | } 859 | .ui-state-disabled .ui-icon { 860 | filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ 861 | } 862 | 863 | 864 | /* positioning */ 865 | .ui-icon-blank { background-position: 16px 16px; } 866 | .ui-icon-carat-1-n { background-position: 0 0; } 867 | .ui-icon-carat-1-ne { background-position: -16px 0; } 868 | .ui-icon-carat-1-e { background-position: -32px 0; } 869 | .ui-icon-carat-1-se { background-position: -48px 0; } 870 | .ui-icon-carat-1-s { background-position: -64px 0; } 871 | .ui-icon-carat-1-sw { background-position: -80px 0; } 872 | .ui-icon-carat-1-w { background-position: -96px 0; } 873 | .ui-icon-carat-1-nw { background-position: -112px 0; } 874 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 875 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 876 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 877 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 878 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 879 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 880 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 881 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 882 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 883 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 884 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 885 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 886 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 887 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 888 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 889 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 890 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 891 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 892 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 893 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 894 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 895 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 896 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 897 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 898 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 899 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 900 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 901 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 902 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 903 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 904 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 905 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 906 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 907 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 908 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 909 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 910 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 911 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 912 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 913 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 914 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 915 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 916 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 917 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 918 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 919 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 920 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 921 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 922 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 923 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 924 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 925 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 926 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 927 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 928 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 929 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 930 | .ui-icon-arrow-4 { background-position: 0 -80px; } 931 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 932 | .ui-icon-extlink { background-position: -32px -80px; } 933 | .ui-icon-newwin { background-position: -48px -80px; } 934 | .ui-icon-refresh { background-position: -64px -80px; } 935 | .ui-icon-shuffle { background-position: -80px -80px; } 936 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 937 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 938 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 939 | .ui-icon-folder-open { background-position: -16px -96px; } 940 | .ui-icon-document { background-position: -32px -96px; } 941 | .ui-icon-document-b { background-position: -48px -96px; } 942 | .ui-icon-note { background-position: -64px -96px; } 943 | .ui-icon-mail-closed { background-position: -80px -96px; } 944 | .ui-icon-mail-open { background-position: -96px -96px; } 945 | .ui-icon-suitcase { background-position: -112px -96px; } 946 | .ui-icon-comment { background-position: -128px -96px; } 947 | .ui-icon-person { background-position: -144px -96px; } 948 | .ui-icon-print { background-position: -160px -96px; } 949 | .ui-icon-trash { background-position: -176px -96px; } 950 | .ui-icon-locked { background-position: -192px -96px; } 951 | .ui-icon-unlocked { background-position: -208px -96px; } 952 | .ui-icon-bookmark { background-position: -224px -96px; } 953 | .ui-icon-tag { background-position: -240px -96px; } 954 | .ui-icon-home { background-position: 0 -112px; } 955 | .ui-icon-flag { background-position: -16px -112px; } 956 | .ui-icon-calendar { background-position: -32px -112px; } 957 | .ui-icon-cart { background-position: -48px -112px; } 958 | .ui-icon-pencil { background-position: -64px -112px; } 959 | .ui-icon-clock { background-position: -80px -112px; } 960 | .ui-icon-disk { background-position: -96px -112px; } 961 | .ui-icon-calculator { background-position: -112px -112px; } 962 | .ui-icon-zoomin { background-position: -128px -112px; } 963 | .ui-icon-zoomout { background-position: -144px -112px; } 964 | .ui-icon-search { background-position: -160px -112px; } 965 | .ui-icon-wrench { background-position: -176px -112px; } 966 | .ui-icon-gear { background-position: -192px -112px; } 967 | .ui-icon-heart { background-position: -208px -112px; } 968 | .ui-icon-star { background-position: -224px -112px; } 969 | .ui-icon-link { background-position: -240px -112px; } 970 | .ui-icon-cancel { background-position: 0 -128px; } 971 | .ui-icon-plus { background-position: -16px -128px; } 972 | .ui-icon-plusthick { background-position: -32px -128px; } 973 | .ui-icon-minus { background-position: -48px -128px; } 974 | .ui-icon-minusthick { background-position: -64px -128px; } 975 | .ui-icon-close { background-position: -80px -128px; } 976 | .ui-icon-closethick { background-position: -96px -128px; } 977 | .ui-icon-key { background-position: -112px -128px; } 978 | .ui-icon-lightbulb { background-position: -128px -128px; } 979 | .ui-icon-scissors { background-position: -144px -128px; } 980 | .ui-icon-clipboard { background-position: -160px -128px; } 981 | .ui-icon-copy { background-position: -176px -128px; } 982 | .ui-icon-contact { background-position: -192px -128px; } 983 | .ui-icon-image { background-position: -208px -128px; } 984 | .ui-icon-video { background-position: -224px -128px; } 985 | .ui-icon-script { background-position: -240px -128px; } 986 | .ui-icon-alert { background-position: 0 -144px; } 987 | .ui-icon-info { background-position: -16px -144px; } 988 | .ui-icon-notice { background-position: -32px -144px; } 989 | .ui-icon-help { background-position: -48px -144px; } 990 | .ui-icon-check { background-position: -64px -144px; } 991 | .ui-icon-bullet { background-position: -80px -144px; } 992 | .ui-icon-radio-on { background-position: -96px -144px; } 993 | .ui-icon-radio-off { background-position: -112px -144px; } 994 | .ui-icon-pin-w { background-position: -128px -144px; } 995 | .ui-icon-pin-s { background-position: -144px -144px; } 996 | .ui-icon-play { background-position: 0 -160px; } 997 | .ui-icon-pause { background-position: -16px -160px; } 998 | .ui-icon-seek-next { background-position: -32px -160px; } 999 | .ui-icon-seek-prev { background-position: -48px -160px; } 1000 | .ui-icon-seek-end { background-position: -64px -160px; } 1001 | .ui-icon-seek-start { background-position: -80px -160px; } 1002 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ 1003 | .ui-icon-seek-first { background-position: -80px -160px; } 1004 | .ui-icon-stop { background-position: -96px -160px; } 1005 | .ui-icon-eject { background-position: -112px -160px; } 1006 | .ui-icon-volume-off { background-position: -128px -160px; } 1007 | .ui-icon-volume-on { background-position: -144px -160px; } 1008 | .ui-icon-power { background-position: 0 -176px; } 1009 | .ui-icon-signal-diag { background-position: -16px -176px; } 1010 | .ui-icon-signal { background-position: -32px -176px; } 1011 | .ui-icon-battery-0 { background-position: -48px -176px; } 1012 | .ui-icon-battery-1 { background-position: -64px -176px; } 1013 | .ui-icon-battery-2 { background-position: -80px -176px; } 1014 | .ui-icon-battery-3 { background-position: -96px -176px; } 1015 | .ui-icon-circle-plus { background-position: 0 -192px; } 1016 | .ui-icon-circle-minus { background-position: -16px -192px; } 1017 | .ui-icon-circle-close { background-position: -32px -192px; } 1018 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 1019 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 1020 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 1021 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 1022 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 1023 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 1024 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 1025 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 1026 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 1027 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 1028 | .ui-icon-circle-check { background-position: -208px -192px; } 1029 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 1030 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 1031 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 1032 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 1033 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 1034 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 1035 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 1036 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 1037 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 1038 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 1039 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 1040 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 1041 | 1042 | 1043 | /* Misc visuals 1044 | ----------------------------------*/ 1045 | 1046 | /* Corner radius */ 1047 | .ui-corner-all, 1048 | .ui-corner-top, 1049 | .ui-corner-left, 1050 | .ui-corner-tl { 1051 | border-top-left-radius: 4px; 1052 | } 1053 | .ui-corner-all, 1054 | .ui-corner-top, 1055 | .ui-corner-right, 1056 | .ui-corner-tr { 1057 | border-top-right-radius: 4px; 1058 | } 1059 | .ui-corner-all, 1060 | .ui-corner-bottom, 1061 | .ui-corner-left, 1062 | .ui-corner-bl { 1063 | border-bottom-left-radius: 4px; 1064 | } 1065 | .ui-corner-all, 1066 | .ui-corner-bottom, 1067 | .ui-corner-right, 1068 | .ui-corner-br { 1069 | border-bottom-right-radius: 4px; 1070 | } 1071 | -------------------------------------------------------------------------------- /public/stylesheets/pure/0.5.0/pure-min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Pure v0.5.0 3 | Copyright 2014 Yahoo Inc. All rights reserved. 4 | Licensed under the BSD License. 5 | https://github.com/yui/pure/blob/master/LICENSE.md 6 | */ 7 | /*! 8 | normalize.css v1.1.3 | MIT License | git.io/normalize 9 | Copyright (c) Nicolas Gallagher and Jonathan Neal 10 | */ 11 | /*! normalize.css v1.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-flex;-webkit-flex-flow:row wrap;display:-ms-flexbox;-ms-flex-flow:row wrap}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class *="pure-u"]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%;*width:4.1357%}.pure-u-1-12,.pure-u-2-24{width:8.3333%;*width:8.3023%}.pure-u-1-8,.pure-u-3-24{width:12.5%;*width:12.469%}.pure-u-1-6,.pure-u-4-24{width:16.6667%;*width:16.6357%}.pure-u-1-5{width:20%;*width:19.969%}.pure-u-5-24{width:20.8333%;*width:20.8023%}.pure-u-1-4,.pure-u-6-24{width:25%;*width:24.969%}.pure-u-7-24{width:29.1667%;*width:29.1357%}.pure-u-1-3,.pure-u-8-24{width:33.3333%;*width:33.3023%}.pure-u-3-8,.pure-u-9-24{width:37.5%;*width:37.469%}.pure-u-2-5{width:40%;*width:39.969%}.pure-u-5-12,.pure-u-10-24{width:41.6667%;*width:41.6357%}.pure-u-11-24{width:45.8333%;*width:45.8023%}.pure-u-1-2,.pure-u-12-24{width:50%;*width:49.969%}.pure-u-13-24{width:54.1667%;*width:54.1357%}.pure-u-7-12,.pure-u-14-24{width:58.3333%;*width:58.3023%}.pure-u-3-5{width:60%;*width:59.969%}.pure-u-5-8,.pure-u-15-24{width:62.5%;*width:62.469%}.pure-u-2-3,.pure-u-16-24{width:66.6667%;*width:66.6357%}.pure-u-17-24{width:70.8333%;*width:70.8023%}.pure-u-3-4,.pure-u-18-24{width:75%;*width:74.969%}.pure-u-19-24{width:79.1667%;*width:79.1357%}.pure-u-4-5{width:80%;*width:79.969%}.pure-u-5-6,.pure-u-20-24{width:83.3333%;*width:83.3023%}.pure-u-7-8,.pure-u-21-24{width:87.5%;*width:87.469%}.pure-u-11-12,.pure-u-22-24{width:91.6667%;*width:91.6357%}.pure-u-23-24{width:95.8333%;*width:95.8023%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}.pure-button{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button{font-family:inherit;font-size:100%;*font-size:90%;*overflow:visible;padding:.5em 1em;color:#444;color:rgba(0,0,0,.8);*color:#444;border:1px solid #999;border:0 rgba(0,0,0,0);background-color:#E6E6E6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:hover,.pure-button:focus{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000', GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:-moz-linear-gradient(top,rgba(0,0,0,.05) 0,rgba(0,0,0,.1));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{border:0;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);filter:alpha(opacity=40);-khtml-opacity:.4;-moz-opacity:.4;opacity:.4;cursor:not-allowed;box-shadow:none}.pure-button-hidden{display:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;outline:thin dotted \9;border-color:#129FEA}.pure-form input:not([type]):focus{outline:0;outline:thin dotted \9;border-color:#129FEA}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:thin dotted #333;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border-color:#ee5f5b}.pure-form input:focus:invalid:focus,.pure-form textarea:focus:invalid:focus,.pure-form select:focus:invalid:focus{border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-aligned .pure-help-inline,.pure-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 10em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input{display:block;padding:10px;margin:0;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus{z-index:2}.pure-form .pure-group input:first-child{top:1px;border-radius:4px 4px 0 0}.pure-form .pure-group input:last-child{top:-2px;border-radius:0 0 4px 4px}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form .pure-help-inline,.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form .pure-help-inline,.pure-form-message-inline,.pure-form-message{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu ul{position:absolute;visibility:hidden}.pure-menu.pure-menu-open{visibility:visible;z-index:2;width:100%}.pure-menu ul{left:-10000px;list-style:none;margin:0;padding:0;top:-10000px;z-index:1}.pure-menu>ul{position:relative}.pure-menu-open>ul{left:0;top:0;visibility:visible}.pure-menu-open>ul:focus{outline:0}.pure-menu li{position:relative}.pure-menu a,.pure-menu .pure-menu-heading{display:block;color:inherit;line-height:1.5em;padding:5px 20px;text-decoration:none;white-space:nowrap}.pure-menu.pure-menu-horizontal>.pure-menu-heading{display:inline-block;*display:inline;zoom:1;margin:0;vertical-align:middle}.pure-menu.pure-menu-horizontal>ul{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.pure-menu li a{padding:5px 20px}.pure-menu-can-have-children>.pure-menu-label:after{content:'\25B8';float:right;font-family:'Lucida Grande','Lucida Sans Unicode','DejaVu Sans',sans-serif;margin-right:-20px;margin-top:-1px}.pure-menu-can-have-children>.pure-menu-label{padding-right:30px}.pure-menu-separator{background-color:#dfdfdf;display:block;height:1px;font-size:0;margin:7px 2px;overflow:hidden}.pure-menu-hidden{display:none}.pure-menu-fixed{position:fixed;top:0;left:0;width:100%}.pure-menu-horizontal li{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.pure-menu-horizontal li li{display:block}.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label:after{content:"\25BE"}.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label{padding-right:30px}.pure-menu-horizontal li.pure-menu-separator{height:50%;width:1px;margin:0 7px}.pure-menu-horizontal li li.pure-menu-separator{height:1px;width:auto;margin:7px 2px}.pure-menu.pure-menu-open,.pure-menu.pure-menu-horizontal li .pure-menu-children{background:#fff;border:1px solid #b7b7b7}.pure-menu.pure-menu-horizontal,.pure-menu.pure-menu-horizontal .pure-menu-heading{border:0}.pure-menu a{border:1px solid transparent;border-left:0;border-right:0}.pure-menu a,.pure-menu .pure-menu-can-have-children>li:after{color:#777}.pure-menu .pure-menu-can-have-children>li:hover:after{color:#fff}.pure-menu .pure-menu-open{background:#dedede}.pure-menu li a:hover,.pure-menu li a:focus{background:#eee}.pure-menu li.pure-menu-disabled a:hover,.pure-menu li.pure-menu-disabled a:focus{background:#fff;color:#bfbfbf}.pure-menu .pure-menu-disabled>a{background-image:none;border-color:transparent;cursor:default}.pure-menu .pure-menu-disabled>a,.pure-menu .pure-menu-can-have-children.pure-menu-disabled>a:after{color:#bfbfbf}.pure-menu .pure-menu-heading{color:#565d64;text-transform:uppercase;font-size:90%;margin-top:.5em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#dfdfdf}.pure-menu .pure-menu-selected a{color:#000}.pure-menu.pure-menu-open.pure-menu-fixed{border:0;border-bottom:1px solid #b7b7b7}.pure-paginator{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;list-style:none;margin:0;padding:0}.opera-only :-o-prefocus,.pure-paginator{word-spacing:-.43em}.pure-paginator li{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-paginator .pure-button{border-radius:0;padding:.8em 1.4em;vertical-align:top;height:1.1em}.pure-paginator .pure-button:focus,.pure-paginator .pure-button:active{outline-style:none}.pure-paginator .prev,.pure-paginator .next{color:#C0C1C3;text-shadow:0 -1px 0 rgba(0,0,0,.45)}.pure-paginator .prev{border-radius:2px 0 0 2px}.pure-paginator .next{border-radius:0 2px 2px 0}@media (max-width:480px){.pure-menu-horizontal{width:100%}.pure-menu-children li{display:block;border-bottom:1px solid #000}}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table td:first-child,.pure-table th:first-child{border-left-width:0}.pure-table thead{background:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child td,.pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0} 12 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0px; 3 | font-size: small; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | 10 | /* navbar CSS */ 11 | .pure-menu a { 12 | color: #FFFFFF; 13 | } 14 | 15 | .pure-menu li a:hover, .pure-menu li a:focus { 16 | background: #6f5499; 17 | } 18 | 19 | .pure-menu .pure-menu-open { 20 | background: #6f5499; 21 | } 22 | 23 | #pageheader { 24 | background-color: #6f5499; 25 | color: #FFFFFF; 26 | padding-right: 8px; 27 | padding-left: 10px; 28 | margin-bottom: 8px; 29 | } 30 | 31 | #title { 32 | font-size: large; 33 | margin-top: 6px; 34 | margin-bottom: 4px; 35 | } 36 | 37 | #desc { 38 | font-size: small; 39 | color: #cdbfe3; 40 | margin-bottom: 4px; 41 | } 42 | 43 | #navbar { 44 | text-align: right; 45 | } 46 | 47 | #webkit-csp-tests { 48 | color: #fff1aa; 49 | } 50 | 51 | /* navbar END */ 52 | 53 | #msgbox { 54 | border-style: solid; 55 | border-width: 1px; 56 | margin-right: 15%; 57 | margin-left: 15%; 58 | padding-top: 5px; 59 | padding-bottom: 5px; 60 | background-color: #FFFEEE; 61 | /*background-color: #F0EFDB;*/ 62 | } 63 | 64 | textarea { 65 | -webkit-box-sizing: border-box; 66 | -moz-box-sizing: border-box; 67 | box-sizing: border-box; 68 | 69 | width: 100%; 70 | } 71 | 72 | #htmlcode { 73 | height: 30em; 74 | font-family: Consolas; 75 | } 76 | 77 | #cspheader { 78 | font-family: Consolas; 79 | } 80 | 81 | html, body { 82 | height: 90%; 83 | } 84 | 85 | #container { 86 | padding: 10px; 87 | height: 100%; 88 | width: 100%; 89 | } 90 | 91 | #test-report-container { 92 | padding: 10px; 93 | height: 100%; 94 | width: 100%; 95 | /* ADD THE OVERFLOW */ 96 | overflow-x: auto; 97 | overflow-y: auto; 98 | } 99 | 100 | #topdiv { 101 | height: 60%; 102 | width: 100%; 103 | margin-bottom: 10px; 104 | } 105 | 106 | #bottomdiv { 107 | height: 40%; 108 | width: 100%; 109 | margin-top: 10px; 110 | /* margin-right: 10px; */ 111 | text-align: left; 112 | /* ADD THE OVERFLOW */ 113 | overflow-x: auto; 114 | overflow-y: auto; 115 | 116 | } 117 | 118 | #topframe { 119 | height: 100%; 120 | width:100%; 121 | } 122 | 123 | #bottomtable { 124 | width:100%; 125 | } 126 | 127 | .hiddenelement { 128 | display: none; 129 | } 130 | 131 | img#loading { 132 | display: block; 133 | margin-left: auto; 134 | margin-right: auto; 135 | } 136 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Yahoo Inc. 2 | // Copyrights licensed under the New BSD License. See the 3 | // accompanying LICENSE.txt file for terms. 4 | // 5 | // Author Binu P. Ramakrishnan 6 | // Created 01/05/2015 7 | 8 | var fs = require('fs'); 9 | var path = require('path'); 10 | var express = require('express'); 11 | var router = express.Router(); 12 | var randomstring = require("randomstring"); 13 | var redis = require('redis'); 14 | var hostname = require('os').hostname(); 15 | 16 | // config details; not the best, but works! 17 | var config = require('../config.js'); 18 | var title = config.title; 19 | var expiry = config.ephemeralCache; 20 | var linkexpiry_ms = config.longLivedCache; 21 | var keylen = config.keyLen; 22 | var cachestore = redis.createClient(config.redisPort, config.redisHost, {}); 23 | // apps CSP header 24 | var csp_hdr = "default-src 'self'; "; 25 | // webkit-tests path 26 | var webkit_tests = '../webkit-tests'; 27 | // webkit-tests2 path (CSP1.1 or level 2) 28 | var webkit_tests2 = '../webkit-tests/1.1'; 29 | // filter html files 30 | var pattern = /^[\w, -]{1,48}\.html$/; 31 | 32 | // 33 | /* GET home page. */ 34 | router.get('/', function(req, res) { 35 | 36 | /* // User Agent parser 37 | var r = require('ua-parser').parse(req.headers['user-agent']); 38 | console.log(r.ua.toString()); // -> "Safari 5.0.1" 39 | console.log(r.ua.toVersionString()); // -> "5.0.1" 40 | console.log(r.ua.family) // -> "Safari" 41 | console.log(r.ua.major); // -> "5" 42 | console.log(r.ua.minor); // -> "0" 43 | console.log(r.ua.patch); // -> "1" 44 | 45 | console.log(r.os.toString()); // -> "iOS 5.1" 46 | console.log(r.os.toVersionString()); // -> "5.1" 47 | console.log(r.os.family) // -> "iOS" 48 | console.log(r.os.major); // -> "5" 49 | console.log(r.os.minor); // -> "1" 50 | console.log(r.os.patch); // -> null 51 | 52 | console.log(r.device.family); // -> "iPhone" 53 | */ 54 | 55 | res.set('content-security-policy', csp_hdr); 56 | res.render('index', { title: title, userinput: undefined }); 57 | }); 58 | 59 | /* Healthcheck URL */ 60 | router.get('/status.html', function(req, res) { 61 | res.set('content-security-policy', csp_hdr); 62 | res.set('content-type', 'text/plain'); 63 | res.set('connection', 'close'); 64 | res.status(200).send('OK'); 65 | }); 66 | 67 | /* GET home page with preloaded inputs. */ 68 | router.get('/webkit-tests', function(req, res) { 69 | try { 70 | fs.readdir(path.join(__dirname, webkit_tests), function(err, files) { 71 | if (err) { 72 | console.log('Read failed: ' + err.message); 73 | res.set('content-security-policy', csp_hdr); 74 | res.render('index', { title: title, userinput: undefined }); 75 | return; 76 | } 77 | 78 | var tests = []; 79 | var i = 0; 80 | files.forEach(function(filename) { 81 | //console.log('file: ' + filename); 82 | if (pattern.test(filename)) { 83 | tests[i++] = filename; 84 | } 85 | 86 | }); 87 | 88 | res.set('content-security-policy', csp_hdr); 89 | res.render('webkit-tests', { title: title, tests: tests, hostname: hostname, 90 | hostport: req.socket.localPort, 91 | hostip: req.socket.localAddress, csp11: false }); 92 | 93 | }); 94 | } catch (err) { 95 | // handle the error safely 96 | console.log(err); 97 | res.status(400).send('Bad Request'); 98 | } 99 | }); 100 | 101 | /* GET preloaded CSP level 2 scripts (from Chrome) */ 102 | router.get('/webkit-tests2', function(req, res) { 103 | 104 | try { 105 | fs.readdir(path.join(__dirname, webkit_tests2), function(err, files) { 106 | if (err) { 107 | console.log('Read failed: ' + err.message); 108 | res.set('content-security-policy', csp_hdr); 109 | res.render('index', { title: title, userinput: undefined }); 110 | return; 111 | } 112 | 113 | var tests = []; 114 | var i = 0; 115 | files.forEach(function(filename) { 116 | //console.log('file: ' + filename); 117 | if (pattern.test(filename)) { 118 | tests[i++] = filename; 119 | } 120 | }); 121 | 122 | res.set('content-security-policy', csp_hdr); 123 | res.render('webkit-tests', { title: title, tests: tests, hostname: hostname, 124 | hostport: req.socket.localPort, 125 | hostip: req.socket.localAddress, csp11: true }); 126 | 127 | }); 128 | } catch (err) { 129 | // handle the error safely 130 | console.log(err); 131 | res.status(400).send('Bad Request'); 132 | } 133 | }); 134 | 135 | /* GET home page with preloaded inputs. */ 136 | router.get('/:id', function(req, res) { 137 | try { 138 | var key = req.params.id; 139 | res.set('content-security-policy', csp_hdr); 140 | 141 | if ((key != undefined) && (key)) { 142 | key = key.slice(0, keylen); 143 | cachestore.get(key, function (err, result) { 144 | 145 | if (err || !result) { 146 | // not cached; lets see if it is a file 147 | console.log(key + ' : key not found aaaa'); 148 | var filename = req.params.id; 149 | // a crude input filter 150 | if (pattern.test(filename)) { 151 | fs.readFile(path.join(__dirname, webkit_tests + '/' + filename), 'utf8', 152 | function (error, data) { 153 | if (error) { 154 | // lets check it in 1.1 dir 155 | fs.readFile(path.join(__dirname, webkit_tests2 + '/' + filename), 'utf8', 156 | function (error, data) { 157 | if (error) { 158 | res.render('index', { title: title, userinput: undefined }); 159 | return; 160 | } 161 | 162 | var input = { 'cspheader' : '', 'htmlcode' : data }; 163 | res.render('index', { title: title, userinput: input }); 164 | return; 165 | }); 166 | 167 | } else { 168 | var input = { 'cspheader' : '', 'htmlcode' : data }; 169 | res.render('index', { title: title, userinput: input }); 170 | return; 171 | } 172 | }); 173 | 174 | } else { 175 | res.status(400).send('

Page not found. URL is expired

Home'); 176 | return; 177 | } 178 | 179 | } else { 180 | var j = JSON.parse(result); 181 | res.render('index', { title: title, userinput: j }); 182 | return; 183 | } 184 | }); 185 | 186 | } 187 | } catch (err) { 188 | // handle the error safely 189 | console.log(err); 190 | res.status(400).send('Bad Request'); 191 | } 192 | 193 | }); 194 | 195 | /* GET WebKit csp test page. */ 196 | router.get('/webkit-test/:id', function(req, res) { 197 | try { 198 | 199 | var filename = req.params.id; 200 | // a crude input filter 201 | if (pattern.test(filename)) { 202 | fs.readFile(path.join(__dirname, webkit_tests + '/' + filename), 'utf8', 203 | function (error, data) { 204 | if (error) { 205 | res.status(400).send('Bad Request'); 206 | return; 207 | } 208 | 209 | var input = { 'cspheader' : '', 'htmlcode' : data }; 210 | var key = randomstring.generate(keylen); 211 | cachestore.setex(key, expiry, JSON.stringify(input), redis.print); 212 | 213 | var csp_hdr2 = csp_hdr + ' frame-src http://' + req.socket.localAddress + ':' + req.socket.localPort + ';'; 214 | res.set('content-security-policy', csp_hdr2); 215 | res.render('test', { title: title, 216 | testid: key, 217 | hostport: req.socket.localPort, 218 | hostip: req.socket.localAddress }); 219 | 220 | }); 221 | } 222 | 223 | } catch (err) { 224 | // handle the error safely 225 | console.log(err); 226 | res.status(400).send('Bad Request'); 227 | } 228 | }); 229 | 230 | /* GET WebKit csp1.1 test page. */ 231 | router.get('/webkit-test2/:id', function(req, res) { 232 | try { 233 | 234 | var filename = req.params.id; 235 | // a crude input filter 236 | if (pattern.test(filename)) { 237 | fs.readFile(path.join(__dirname, webkit_tests2 + '/' + filename), 'utf8', 238 | function (error, data) { 239 | if (error) { 240 | res.status(400).send('Bad Request'); 241 | return; 242 | } 243 | 244 | var input = { 'cspheader' : '', 'htmlcode' : data }; 245 | var key = randomstring.generate(keylen); 246 | cachestore.setex(key, expiry, JSON.stringify(input), redis.print); 247 | 248 | var csp_hdr2 = csp_hdr + ' frame-src http://' + req.socket.localAddress + ':' + req.socket.localPort + ';'; 249 | res.set('content-security-policy', csp_hdr2); 250 | res.render('test', { title: title, 251 | testid: key, 252 | hostport: req.socket.localPort, 253 | hostip: req.socket.localAddress }); 254 | 255 | }); 256 | } 257 | 258 | } catch (err) { 259 | // handle the error safely 260 | console.log(err); 261 | res.status(400).send('Bad Request'); 262 | } 263 | }); 264 | 265 | /* GET test page. */ 266 | router.post('/test', function(req, res) { 267 | try { 268 | 269 | var key = randomstring.generate(keylen); 270 | cachestore.setex(key, expiry, JSON.stringify(req.body), redis.print); 271 | 272 | if (req.body.windowtop) { 273 | res.set('content-security-policy', csp_hdr); 274 | res.render('test-window', { title: title, 275 | testid: key, 276 | hostname: hostname, 277 | hostport: req.socket.localPort, 278 | hostip: req.socket.localAddress, 279 | sharelink: false, 280 | showlink: false, 281 | linkexpiry: 0 }); 282 | } else { 283 | var csp_hdr2 = csp_hdr + ' frame-src http://' + req.socket.localAddress + ':' + req.socket.localPort + ';'; 284 | res.set('content-security-policy', csp_hdr2); 285 | res.render('test', { title: title, 286 | testid: key, 287 | hostport: req.socket.localPort, 288 | hostip: req.socket.localAddress }); 289 | } 290 | 291 | } catch (err) { 292 | // handle the error safely 293 | console.log(err); 294 | res.status(400).send('Bad Request'); 295 | } 296 | }); 297 | 298 | /* GET test-share page. */ 299 | router.get('/test-share/:id', function(req, res) { 300 | try { 301 | 302 | var key = req.params.id; 303 | var ts = req.query.ts; 304 | var current = new Date().getTime(); 305 | if ((ts === undefined) || (!ts) || isNaN(ts) || (ts < current)) { 306 | ts = current; // sorry i cant help :( 307 | } 308 | 309 | // checking the existence is good enough 310 | var showlink = true; 311 | if (req.query.sl === undefined) { 312 | showlink = false; 313 | } 314 | 315 | cachestore.exists(key, function (err, result) { 316 | if (err || !result) { 317 | console.log(key + ' : key not found'); 318 | res.status(400).send('

Page not found. URL is expired

Home'); 319 | return; 320 | } else { 321 | // extend the expiry 322 | cachestore.expire(key, linkexpiry_ms); 323 | var lets = parseInt(ts); 324 | lets += parseInt(linkexpiry_ms); 325 | var sessionkey = key + '-' + randomstring.generate(7); 326 | res.set('content-security-policy', csp_hdr); 327 | res.render('test-window', { title: title, 328 | testid: sessionkey, 329 | hostname: hostname, 330 | hostport: req.socket.localPort, 331 | hostip: req.socket.localAddress, 332 | sharelink: true, 333 | showlink: showlink, 334 | linkexpiry: lets }); 335 | } 336 | }); 337 | 338 | } catch (err) { 339 | // handle the error safely 340 | console.log(err); 341 | res.status(400).send('Bad Request'); 342 | } 343 | }); 344 | 345 | /* GET test/id page. */ 346 | router.get('/test/:id', function(req, res) { 347 | try { 348 | 349 | // Yes, this is not a strong security assertion. Ideally tests should be 350 | // handled in a separate vhost. Also the recommendation is to host this 351 | // app in a separate domain 352 | if (req.hostname != req.socket.localAddress) { 353 | res.status(400).send('

Page not found

Home'); 354 | return; 355 | } 356 | 357 | var sessionkey = req.params.id; 358 | var reporturi = '; report-uri /report/' + sessionkey; 359 | var key = sessionkey.slice(0, keylen); 360 | 361 | cachestore.get(key, function (err, result) { 362 | if (err || !result) { 363 | console.log(key + ' : key not found'); 364 | res.status(400).send('

Page not found. URL is expired

Home'); 365 | return; 366 | } else { 367 | var j = JSON.parse(result); 368 | 369 | // cspheader can be empty 370 | if (j.cspheader) { 371 | if (j.hasOwnProperty('reportonly')) { 372 | res.set('content-security-policy-report-only', (j.cspheader).concat(reporturi)); 373 | res.set('X-Content-Security-Policy-Report-Only', (j.cspheader).concat(reporturi)); 374 | res.set('X-WebKit-CSP-Report-Only', (j.cspheader).concat(reporturi)); 375 | } else { 376 | res.set('content-security-policy', (j.cspheader).concat(reporturi)); 377 | res.set('X-Content-Security-Policy', (j.cspheader).concat(reporturi)); 378 | res.set('X-WebKit-CSP', (j.cspheader).concat(reporturi)); 379 | } 380 | } 381 | 382 | // to deal with CSP meta tag in the HTML file 383 | // eg: 384 | var code = j.htmlcode.replace(/\$CSP_REPORT_URI/g, '/report/' + sessionkey); 385 | res.send(code); 386 | //res.send(j.htmlcode); 387 | } 388 | }); 389 | 390 | } catch (err) { 391 | // handle the error safely 392 | console.log(err); 393 | res.status(400).send('Bad Request'); 394 | } 395 | }); 396 | 397 | /* POST report/id page. */ 398 | router.post('/report/:id', function(req, res) { 399 | try { 400 | 401 | var id = ('report_').concat(req.params.id); 402 | cachestore.rpush(id, JSON.stringify(req.body), redis.print); 403 | cachestore.expire(id, expiry); 404 | res.status(204).end(); 405 | 406 | } catch (err) { 407 | // handle the error safely 408 | console.log(err); 409 | res.status(400).send('Bad Request'); 410 | } 411 | }); 412 | 413 | /* GET report/id page. */ 414 | router.get('/report/:id', function(req, res) { 415 | try { 416 | var id = ('report_').concat(req.params.id); 417 | 418 | cachestore.lrange(id, 0, -1, function(err, records){ 419 | var len = records === null ? 0 : records.length; 420 | console.log('REDIS RECORDS LEN: ' + len); 421 | if (len > 0) { 422 | /*for (var i=0; i ' + report['csp-report']['document-uri']); 425 | console.log('|---->> ' + report['csp-report']['referrer']); 426 | console.log('|---->> ' + report['csp-report']['violated-directive']); 427 | console.log('|---->> ' + report['csp-report']['blocked-uri']); 428 | } 429 | 430 | cachestore.ttl(id, function(err, ttl){ 431 | console.log('TTL: ' + ttl); 432 | }); 433 | */ 434 | 435 | res.set('content-security-policy', csp_hdr); 436 | res.render('cspreport', { records: records }); 437 | } else { 438 | res.status(200); 439 | res.end(); 440 | } 441 | }); 442 | 443 | } catch (err) { 444 | // handle the error safely 445 | console.log(err); 446 | res.status(400).send('Bad Request'); 447 | } 448 | 449 | }); 450 | 451 | /* GET report2/id page. */ 452 | router.get('/report2/:id', function(req, res) { 453 | try { 454 | res.set('content-security-policy', csp_hdr); 455 | res.render('test-report', { title: title, testid: req.params.id }); 456 | } catch (err) { 457 | // handle the error safely 458 | console.log(err); 459 | res.status(400).send('Bad Request'); 460 | } 461 | 462 | }); 463 | 464 | /*-----------------------------------------*/ 465 | /* CSP 1.1 testing - A dummy form endpoint */ 466 | /*-----------------------------------------*/ 467 | router.get('/test/csp11/form-target', function(req, res) { 468 | try { 469 | res.set('content-security-policy', csp_hdr); 470 | res.status(200).send('Form submit OK'); 471 | } catch (err) { 472 | // handle the error safely 473 | console.log(err); 474 | res.status(400).send('Bad Request'); 475 | } 476 | 477 | }); 478 | 479 | router.post('/test/csp11/form-target', function(req, res) { 480 | try { 481 | res.set('content-security-policy', csp_hdr); 482 | res.status(200).send('Form submit OK'); 483 | } catch (err) { 484 | // handle the error safely 485 | console.log(err); 486 | res.status(400).send('Bad Request'); 487 | } 488 | 489 | }); 490 | 491 | router.get('/test/csp11/redirect', function(req, res) { 492 | try { 493 | res.set('content-security-policy', csp_hdr); 494 | res.redirect(302, 'http://example.com'); 495 | } catch (err) { 496 | // handle the error safely 497 | console.log(err); 498 | res.status(400).send('Bad Request'); 499 | } 500 | 501 | }); 502 | 503 | router.post('/test/csp11/redirect', function(req, res) { 504 | try { 505 | res.set('content-security-policy', csp_hdr); 506 | res.redirect(302, 'http://example.com'); 507 | } catch (err) { 508 | // handle the error safely 509 | console.log(err); 510 | res.status(400).send('Bad Request'); 511 | } 512 | 513 | }); 514 | 515 | router.get('/test/csp11/mock-plugin', function(req, res) { 516 | try { 517 | res.set('Content-Type', 'application/x-webkit-test-netscape'); 518 | res.status(200).send('This is a mock plugin. It does pretty much nothing.'); 519 | } catch (err) { 520 | // handle the error safely 521 | console.log(err); 522 | res.status(400).send('Bad Request'); 523 | } 524 | 525 | }); 526 | /*-----------------------------------------*/ 527 | /* CSP 1.1 testing - END */ 528 | /*-----------------------------------------*/ 529 | 530 | module.exports = router; 531 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | DEBUG=csptester ./bin/www 2 | 3 | -------------------------------------------------------------------------------- /views/cspreport.ejs: -------------------------------------------------------------------------------- 1 | <% for(var i=0; i < records.length; i++) { %> 2 | <% var report = JSON.parse(records[i]); var j = i+1;%> 3 | <% if (i%2 === 0) { %> 4 | 5 | <% } else { %> 6 | 7 | <% } %> 8 | 9 | <%= j %> 10 | <%= report['csp-report']['document-uri'] %> 11 | <%= report['csp-report']['referrer'] %> 12 | <%= report['csp-report']['violated-directive'] %> 13 | <%= report['csp-report']['blocked-uri'] %> 14 | 15 | <% } %> 16 | 17 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 | <% if (error.hasOwnProperty('status')) { %> 3 |

<%= error.status %>

4 | <% } %> 5 | <% if (error.hasOwnProperty('stack')) { %> 6 |
<%= error.stack %>
7 | <% } %> 8 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | <% include partials/template/head.ejs %> 4 | 5 | 6 | <% include partials/template/header.ejs %> 7 |
8 |
9 |
10 | 11 | 12 | <% if ((userinput != undefined) && (userinput.cspheader)) { %> 13 | 14 | <% } else { %> 15 | 16 | <% } %> 17 | 18 | 19 | 26 | 27 |
28 | 29 | <% if ((userinput != undefined) && (userinput.htmlcode)) { %> 30 | 31 | <% } else { %> 32 | 33 | <% } %> 34 | 35 | 42 | 43 |
44 |
45 | 46 |
47 |
48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /views/partials/template/footer.ejs: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /views/partials/template/head.ejs: -------------------------------------------------------------------------------- 1 | <%= title %> 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /views/partials/template/header.ejs: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /views/test-report.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <% include partials/template/head.ejs %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <% include partials/template/header.ejs %> 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
document-urireferrerviolated-directiveblocked-uri
28 |
29 | 30 |
31 |
32 | 33 |
<%= testid %>
34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /views/test-window.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 |
17 |
18 |
19 | <% if (sharelink === true) { %> 20 | <% if (showlink === true) { %> 21 |
22 | 23 |
24 |
25 | <% } else { %> 26 | View test code

27 | <% } %> 28 | This shareable link expires on: <%= linkexpiry %>
29 | <% } else { %> 30 |
31 | 32 |
33 | <% var ts = new Date().getTime(); %> 34 |
/test-share/<%= testid %>?ts=<%= ts %>&sl=1
35 | <% } %> 36 |
37 |
http://<%= hostip %>:<%= hostport %>/report2/<%= testid %>
38 |
http://<%= hostip %>:<%= hostport %>/test/<%= testid %>
39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /views/test.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <% include partials/template/head.ejs %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <% include partials/template/header.ejs %> 13 | 14 |
15 |
16 | 17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
document-urireferrerviolated-directiveblocked-uri
33 |
34 | 35 |
36 |
37 |
38 | 39 |
<%= testid %>
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /views/webkit-tests.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <% include partials/template/head.ejs %> 5 | 6 | 7 | 8 | <% include partials/template/header.ejs %> 9 | 10 |

This is a curated subset of WebKit CSP tests provided for testing various CSP features. You may find the complete set of tests in WebKit and Chrome repositories

11 |
12 | <% if (csp11 === true) { %> 13 |

CSP 1.0 Tests

14 | <% } else { %> 15 |

CSP 1.1 (Level 2) Tests

16 | <% } %> 17 | 18 | 19 | <% for(var i=0; i < tests.length; i++) { %> 20 | 21 | 22 | 23 | 24 | <% if (csp11 === true) { %> 25 | 26 | <% } else { %> 27 | 28 | <% } %> 29 | 30 | 31 | <% } %> 32 | 33 |
<%= i+1 %><%= tests[i] %>ViewRunRun
34 |

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /webkit-tests/1.1/base-uri-allow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/1.1/base-uri-deny.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |

Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.

20 | 21 | 22 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |

Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.

20 | 21 | 22 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-default-ignored.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |

Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.

20 | 21 | 22 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-get-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |

Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.

20 | 21 | 22 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-get-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | 17 |
18 | 19 |

Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.

20 | 21 | 22 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-javascript-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 |
16 | 17 | 18 |
19 | 20 |

Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a JavaScript alert.

21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /webkit-tests/1.1/form-action-src-redirect-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 |
16 | 17 | 18 |
19 | 20 |

Tests that blocking form redirect works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed.

21 | 22 | 23 | -------------------------------------------------------------------------------- /webkit-tests/1.1/frame-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/1.1/frame-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/1.1/frame-redirect-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/1.1/meta-outside-head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 |

This test checks that Content Security Policy delivered via a meta element is not enforced if the element is outside the document's head.

11 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /webkit-tests/1.1/plugintypes-notype-url.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Given a `plugin-types` directive, plugins have to declare a type explicitly. 8 | No declared type, no load. This test passes if there's a console message 9 | above. 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/1.1/plugintypes-nourl-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | This test passes if there isn't a console message saying the plugin was blocked. 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scripthash-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 13 | 16 | 19 | 20 | 21 |

22 | This tests the effect of a valid script-hash value. It passes if no 23 | console warning is visible, and the alert() is executed. 24 |

25 | 26 | 27 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scripthash-basic-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 13 | 15 | 16 | 17 | 18 | 19 |

20 | This tests the effect of a valid script-hash value, with one valid 21 | script and several invalid ones. It passes if one alert is executed 22 | and four console warings are visible. 23 |

24 | 25 | 26 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scripthash-ignore-unsafeinline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 13 | 14 | 15 |

16 | This tests that a valid hash value disables inline JavaScript, even if 'unsafe-inline' is present. 17 |

18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scripthash-unicode-normalization.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 15 | 19 | 23 | 24 | 25 |

26 | This tests Unicode normalization. While appearing the same, the 27 | strings in the scripts are different Unicode points, but through 28 | normalization, should be the same when the hash is taken. 29 |

30 | 31 | 32 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scriptnonce-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 12 | 15 | 16 | 17 |

18 | This tests the effect of a valid script-nonce value. It passes if 19 | no console warning is visible and the alerts are executed. 20 |

21 | 22 | 23 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scriptnonce-and-scripthash.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 13 | 16 | 19 | 22 | 23 | 24 |

25 | This tests the combined use of script hash and script nonce. It 26 | passes if two console warnings are visible and the three alerts show 27 | PASS. 28 |

29 | 30 | 31 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scriptnonce-basic-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 13 | 16 | 19 | 22 | 23 | 24 |

25 | This tests the effect of a valid script-nonce value. It passes if 26 | three console warnings are visible, and the two PASS alerts are 27 | executed. 28 |

29 | 30 | 31 | -------------------------------------------------------------------------------- /webkit-tests/1.1/scriptnonce-ignore-unsafeinline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 12 | 15 | 18 | 19 | 20 |

21 | This tests that a valid nonce disables inline JavaScript, even if 'unsafe-inline' is present. 22 |

23 | 24 | 25 | -------------------------------------------------------------------------------- /webkit-tests/1.1/stylehash-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

This tests the result of a valid style hash. It passes if this text is green, and a "PASS" alert for p1 is fired.

8 |

This tests the result of a valid style hash. It passes if this text is green, and a "PASS" alert for p2 is fired.

9 |

This tests the result of a valid style hash. It passes if this text is green, and a "PASS" alert for p3 is fired.

10 |

This tests the result of a valid style hash. It passes if this text is green, and a "PASS" alert for p4 is fired.

11 | 12 | 13 | 14 | 15 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /webkit-tests/1.1/stylehash-basic-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 | This tests the effect of a valid style-hash value, with one valid 13 | style and several invalid ones. It passes if the valid style is applied 14 | and three console warnings are visible. 15 |

16 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /webkit-tests/1.1/stylenonce-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 16 | 21 | 22 | 23 |

This text should be green.

24 |

This text should also be green.

25 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /webkit-tests/1.1/stylenonce-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 |

This text should be black.

13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /webkit-tests/blob-urls-match-self.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

8 | blob: URLs are same-origin with the page in which they were created, 9 | and should therefore match the 'self' source in CSP directives. 10 |

11 | 12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /webkit-tests/combine-multiple-policies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | This test checks that we enforce all the supplied policies. This test passes 10 | if it doesn't alert fail and if the style doesn't apply. 11 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /webkit-tests/csptest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CSP Tester 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Hello, world!

14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /webkit-tests/default-src-inline-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/duplicate-directive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 |

11 | This tests the effect of duplicated directives. It passes if a 12 | console warning is visible, and the alert() is executed. 13 |

14 | 15 | 16 | -------------------------------------------------------------------------------- /webkit-tests/eval-allowed-in-report-only-mode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/eval-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /webkit-tests/eval-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /webkit-tests/eval-scripts-setInterval-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 8 | 
21 | 
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /webkit-tests/eval-scripts-setInterval-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 8 | 
21 | 
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /webkit-tests/eval-scripts-setTimeout-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 8 | 
20 | 
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /webkit-tests/eval-scripts-setTimeout-blocked.html: -------------------------------------------------------------------------------- 1 | CTYPE html> 2 | 3 | 4 | 5 | 6 | 7 |
 8 | 
20 | 
21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /webkit-tests/function-constructor-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/function-constructor-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/image-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webkit-tests/image-full-host-wildcard-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /webkit-tests/image-host-wildcard-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /webkit-tests/img-blocked-no-gc-crash.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 28 | 29 | 30 |

31 | This test ensures that blocking an image via CSP doesn't crash if GC 32 | executes before the error event fires. 33 |

34 | 35 | 36 | -------------------------------------------------------------------------------- /webkit-tests/injected-inline-script-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webkit-tests/injected-inline-script-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webkit-tests/injected-inline-style-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | FAIL 1/2 10 |
11 |
12 | FAIL 2/2 13 |
14 | 15 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /webkit-tests/injected-inline-style-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | PASS 1/2 10 |
11 |
12 | PASS 2/2 13 |
14 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/inline-script-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/inline-script-blocked-goofy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | This test passes if it doesn't alert fail. 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/inline-style-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /webkit-tests/inline-style-attribute-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/inline-style-attribute-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/inline-style-attribute-on-html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Even though this page has a CSP policy the blocks inline style, the style 8 | attribute on the HTML element still takes effect because it preceeds the meta 9 | element.

10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /webkit-tests/inline-style-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /webkit-tests/media-src-track-block.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /webkit-tests/no-policy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

7 | Loads an external script. Since no content security policy is present, the script should get executed. 8 |

9 |
10 | FAIL 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /webkit-tests/policy-does-not-affect-child.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /webkit-tests/report-and-enforce.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | This image should be blocked, but should not show up in the violation report. 8 | 9 | 10 | -------------------------------------------------------------------------------- /webkit-tests/report-blocked-data-uri.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webkit-tests/report-only-report-uri-missing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

This test passes if a console message is present, warning about the missing 'report-uri' directive.

8 | 9 | 10 | -------------------------------------------------------------------------------- /webkit-tests/report-only.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /webkit-tests/report-uri.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /webkit-tests/resources/abe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YahooArchive/csptester/08d342d9596bde67dea23c9e610577349eec87cd/webkit-tests/resources/abe.png -------------------------------------------------------------------------------- /webkit-tests/resources/alert-fail.js: -------------------------------------------------------------------------------- 1 | alert('FAIL'); 2 | -------------------------------------------------------------------------------- /webkit-tests/resources/alert-pass.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /webkit-tests/resources/blue.css: -------------------------------------------------------------------------------- 1 | .target { 2 | background-color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /webkit-tests/resources/document-write-alert-fail.js: -------------------------------------------------------------------------------- 1 | document.write(""); 2 | -------------------------------------------------------------------------------- /webkit-tests/resources/dump-as-text.js: -------------------------------------------------------------------------------- 1 | if (window.testRunner) 2 | testRunner.dumpAsText(); 3 | -------------------------------------------------------------------------------- /webkit-tests/resources/get.txt: -------------------------------------------------------------------------------- 1 | PASS 2 | -------------------------------------------------------------------------------- /webkit-tests/resources/go-to-echo-report.js: -------------------------------------------------------------------------------- 1 | 2 | window.onload = function () { 3 | window.location = "/resources/script.js"; 4 | //window.location = "/resources/echo-report.php"; 5 | } 6 | -------------------------------------------------------------------------------- /webkit-tests/resources/inject-script.js: -------------------------------------------------------------------------------- 1 | document.write(""); 2 | 3 | var s = document.createElement('script'); 4 | s.innerText = "alert('Pass 2 of 2');"; 5 | document.body.appendChild(s); 6 | -------------------------------------------------------------------------------- /webkit-tests/resources/inject-style.js: -------------------------------------------------------------------------------- 1 | document.write(""); 2 | 3 | var s = document.createElement('style'); 4 | s.innerText = "#test2 { display: none; }"; 5 | document.body.appendChild(s); 6 | -------------------------------------------------------------------------------- /webkit-tests/resources/multiple-iframe-test.js: -------------------------------------------------------------------------------- 1 | if (window.testRunner) { 2 | testRunner.waitUntilDone(); 3 | testRunner.dumpAsText(); 4 | testRunner.dumpChildFramesAsText(); 5 | } 6 | 7 | function testPreescapedPolicy() { 8 | testImpl(false, true); 9 | } 10 | 11 | function testExperimentalPolicy() { 12 | testImpl(true, false); 13 | } 14 | 15 | function test() { 16 | testImpl(false, false); 17 | } 18 | 19 | function testImpl(experimental, preescapedPolicy) { 20 | if (tests.length === 0) 21 | return finishTesting(); 22 | 23 | var baseURL = "/security/contentSecurityPolicy/"; 24 | var current = tests.shift(); 25 | var iframe = document.createElement("iframe"); 26 | 27 | var policy = current[1]; 28 | if (!preescapedPolicy) 29 | policy = encodeURIComponent(policy); 30 | 31 | var scriptURLIsAbsolute = current[2][0] == '/'; 32 | var scriptToLoad = scriptURLIsAbsolute ? encodeURIComponent(current[2]) : (baseURL + encodeURIComponent(current[2])); 33 | if (current[2].match(/^data:/) || current[2].match(/^https?:/)) 34 | scriptToLoad = encodeURIComponent(current[2]); 35 | 36 | iframe.src = baseURL + "resources/echo-script-src.pl?" + 37 | "experimental=" + (experimental ? "true" : "false") + 38 | "&should_run=" + encodeURIComponent(current[0]) + 39 | "&csp=" + policy + "&q=" + scriptToLoad; 40 | if (current[3]) 41 | iframe.src += "&nonce=" + encodeURIComponent(current[3]); 42 | 43 | iframe.onload = function() { testImpl(experimental, preescapedPolicy); }; 44 | document.body.appendChild(iframe); 45 | } 46 | 47 | function finishTesting() { 48 | if (window.testRunner) { 49 | setTimeout("testRunner.notifyDone()", 0); 50 | } 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /webkit-tests/resources/script.js: -------------------------------------------------------------------------------- 1 | var result = document.getElementById("result"); 2 | result.firstChild.nodeValue = result.attributes.getNamedItem("text").value; 3 | -------------------------------------------------------------------------------- /webkit-tests/resources/track.vtt: -------------------------------------------------------------------------------- 1 | Subtitles! 2 | -------------------------------------------------------------------------------- /webkit-tests/resources/worker-eval.js: -------------------------------------------------------------------------------- 1 | var id = 0; 2 | try { 3 | id = eval("1 + 2 + 3"); 4 | } 5 | catch (e) { 6 | } 7 | postMessage(id === 0 ? "eval blocked" : "eval allowed"); 8 | -------------------------------------------------------------------------------- /webkit-tests/resources/worker-function-function.js: -------------------------------------------------------------------------------- 1 | var fn = function() { 2 | postMessage('Function() function blocked'); 3 | } 4 | try { 5 | fn = new Function("", "postMessage('Function() function allowed');"); 6 | } 7 | catch(e) { 8 | } 9 | fn(); 10 | -------------------------------------------------------------------------------- /webkit-tests/resources/worker-make-xhr.js: -------------------------------------------------------------------------------- 1 | try { 2 | var xhr = new XMLHttpRequest; 3 | xhr.open("GET", "/resources/get.txt", true); 4 | postMessage("xhr allowed"); 5 | } catch(e) { 6 | postMessage("xhr blocked"); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /webkit-tests/resources/worker-set-timeout.js: -------------------------------------------------------------------------------- 1 | var id = 0; 2 | try { 3 | id = setTimeout("postMessage('handler invoked')", 100); 4 | } catch(e) { 5 | } 6 | postMessage(id === 0 ? "setTimeout blocked" : "setTimeout allowed"); 7 | -------------------------------------------------------------------------------- /webkit-tests/sandbox-allow-scripts-subframe.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | This test passes if it does alert pass. 7 | 8 | -------------------------------------------------------------------------------- /webkit-tests/sandbox-allow-scripts.html: -------------------------------------------------------------------------------- 1 | 2 | This test passes if it does alert pass. 3 | 6 | -------------------------------------------------------------------------------- /webkit-tests/sandbox-empty-subframe.html: -------------------------------------------------------------------------------- 1 | 2 | This test passes if it doesn't alert fail. 3 | 4 | -------------------------------------------------------------------------------- /webkit-tests/sandbox-empty.html: -------------------------------------------------------------------------------- 1 | 2 | This test passes if it doesn't alert fail. 3 | 6 | -------------------------------------------------------------------------------- /webkit-tests/script-src-overrides-default-src.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webkit-tests/source-list-parsing-02.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 |

16 | These scripts should execute even though there are parse errors in the policy. 17 |

18 | -------------------------------------------------------------------------------- /webkit-tests/source-list-parsing-03.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 |

16 | None of these scripts should execute even though there are parse errors in the policy. 17 |

18 | 19 | -------------------------------------------------------------------------------- /webkit-tests/source-list-parsing-04.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 |

16 | None of these scripts should execute even though there are parse errors in the policy. 17 |

18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/source-list-parsing-deprecated.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |

15 | Test that directives that predate the CSP 1.0 standard generate proper 16 | warnings to set developer expectations correctly. 17 |

18 | 19 | -------------------------------------------------------------------------------- /webkit-tests/source-list-parsing-no-semicolon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 |

If a web author forgets a semicolon, we should do our best to warn them 14 | that the policy they've defined is probably not what they intended.

15 | -------------------------------------------------------------------------------- /webkit-tests/srcdoc-doesnt-bypass-script-src.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | This test passes if it doesn't alert fail. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /webkit-tests/style-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /webkit-tests/style-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /webkit-tests/worker-connect-src-allowed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/worker-connect-src-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/worker-eval-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /webkit-tests/worker-function-function-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /webkit-tests/worker-script-src.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /webkit-tests/worker-set-timeout-blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | --------------------------------------------------------------------------------