├── .editorconfig ├── .gitignore ├── .jscsrc ├── .jshintrc ├── LICENSE ├── LICENSE2 ├── README.md ├── bower.json ├── component.json ├── package-lock.json ├── package.json ├── spark-md5.js ├── spark-md5.min.js └── test ├── css ├── bootstrap-1.4.min.css └── qunit-1.16.0.css ├── file_reader.html ├── file_reader_binary.html ├── index.html ├── index.min.html ├── js └── qunit-1.16.0.js ├── readme_example.html └── specs.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [package.json] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.* -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywordsOnNewLine": [ 3 | "else", 4 | "catch" 5 | ], 6 | "disallowMixedSpacesAndTabs": true, 7 | "disallowSpacesInCallExpression": true, 8 | "disallowSpacesInFunctionDeclaration": { 9 | "beforeOpeningRoundBrace": true 10 | }, 11 | "disallowTrailingComma": true, 12 | "disallowTrailingWhitespace": true, 13 | "excludeFiles": [ 14 | "bower_components/**", 15 | "node_modules/**" 16 | ], 17 | "fileExtensions": [ 18 | ".js", 19 | "jscs" 20 | ], 21 | "requireCommaBeforeLineBreak": true, 22 | "requireCurlyBraces": [ 23 | "if", 24 | "else", 25 | "for", 26 | "while", 27 | "do", 28 | "try", 29 | "catch" 30 | ], 31 | "requireMultipleVarDecl": "onevar", 32 | "requireSpaceAfterBinaryOperators": true, 33 | "requireSpaceAfterKeywords": [ 34 | "if", 35 | "else", 36 | "for", 37 | "while", 38 | "do", 39 | "switch", 40 | "return", 41 | "try", 42 | "catch", 43 | "function" 44 | ], 45 | "requireSpaceBeforeBinaryOperators": [ 46 | "=", 47 | "+=", 48 | "-=", 49 | "*=", 50 | "/=", 51 | "%=", 52 | "<<=", 53 | ">>=", 54 | ">>>=", 55 | "&=", 56 | "|=", 57 | "^=", 58 | "+=", 59 | "+", 60 | "-", 61 | "*", 62 | "/", 63 | "%", 64 | "<<", 65 | ">>", 66 | ">>>", 67 | "&", 68 | "|", 69 | "^", 70 | "&&", 71 | "||", 72 | "===", 73 | "==", 74 | ">=", 75 | "<=", 76 | "<", 77 | ">", 78 | "!=", 79 | "!==" 80 | ], 81 | "requireSpaceBeforeBlockStatements": true, 82 | "requireSpaceBeforeKeywords": [ 83 | "else" 84 | ], 85 | "requireSpaceBeforeObjectValues": true, 86 | "requireSpacesInConditionalExpression": true, 87 | "requireSpacesInFunctionExpression": { 88 | "beforeOpeningCurlyBrace": true, 89 | "beforeOpeningRoundBrace": true 90 | }, 91 | "requireSpacesInsideObjectBrackets": "allButNested", 92 | "validateIndentation": 4, 93 | "validateParameterSeparator": ", ", 94 | "validateQuoteMarks": "'" 95 | } 96 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "console", 4 | "define", 5 | "self", 6 | "unescape", 7 | "module", 8 | "File", 9 | "SparkMD5" 10 | ], 11 | 12 | "browser": true, 13 | "devel": true, 14 | 15 | "bitwise": false, 16 | "curly": true, 17 | "eqeqeq": false, 18 | "forin": false, 19 | "immed": true, 20 | "latedef": false, 21 | "newcap": true, 22 | "noarg": true, 23 | "noempty": false, 24 | "nonew": true, 25 | "plusplus": false, 26 | "regexp": true, 27 | "undef": true, 28 | "unused": true, 29 | "quotmark": "single", 30 | "strict": false, 31 | "trailing": true, 32 | 33 | "asi": false, 34 | "boss": false, 35 | "debug": false, 36 | "eqnull": true, 37 | "es5": true, 38 | "esnext": false, 39 | "evil": false, 40 | "expr": true, 41 | "funcscope": false, 42 | "globalstrict": false, 43 | "iterator": false, 44 | "lastsemic": false, 45 | "laxbreak": false, 46 | "laxcomma": false, 47 | "loopfunc": true, 48 | "multistr": true, 49 | "onecase": true, 50 | "regexdash": false, 51 | "scripturl": false, 52 | "smarttabs": false, 53 | "shadow": false, 54 | "sub": false, 55 | "supernew": false, 56 | "validthis": false, 57 | 58 | "nomen": false, 59 | "onevar": false, 60 | "white": true 61 | } 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2015 André Cruz 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /LICENSE2: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 André Cruz 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SparkMD5 2 | 3 | SparkMD5 is a fast md5 implementation of the MD5 algorithm. 4 | This script is based in the JKM md5 library which is the [fastest](http://jsperf.com/md5-shootout/7) algorithm around. This is most suitable for browser usage, because `nodejs` version might be faster. 5 | 6 | NOTE: Please disable Firebug while performing the test! 7 | Firebug consumes a lot of memory and CPU and slows the test by a great margin. 8 | 9 | 10 | **[Demo](http://9px.ir/demo/incremental-md5.html)** 11 | 12 | ## Install 13 | 14 | ```sh 15 | npm install --save spark-md5 16 | ``` 17 | 18 | ## Improvements over the JKM md5 library 19 | 20 | * Strings are converted to utf8, like most server side algorithms 21 | * Fix computation for large amounts of data (overflow) 22 | * Incremental md5 (see below) 23 | * Support for array buffers (typed arrays) 24 | * Functionality wrapped in a closure, to avoid global assignments 25 | * Object oriented library 26 | * CommonJS (it can be used in node) and AMD integration 27 | * Code passed through JSHint and JSCS 28 | 29 | 30 | Incremental md5 performs a lot better for hashing large amounts of data, such as 31 | files. One could read files in chunks, using the FileReader & Blob's, and append 32 | each chunk for md5 hashing while keeping memory usage low. See example below. 33 | 34 | 35 | ## Usage 36 | 37 | ### Normal usage 38 | 39 | ```js 40 | var hexHash = SparkMD5.hash('Hi there'); // hex hash 41 | var rawHash = SparkMD5.hash('Hi there', true); // OR raw hash (binary string) 42 | ``` 43 | 44 | ### Incremental usage 45 | 46 | ```js 47 | var spark = new SparkMD5(); 48 | spark.append('Hi'); 49 | spark.append(' there'); 50 | var hexHash = spark.end(); // hex hash 51 | var rawHash = spark.end(true); // OR raw hash (binary string) 52 | ``` 53 | 54 | ### Hash a file incrementally 55 | 56 | NOTE: If you test the code bellow using the file:// protocol in chrome you must start the browser with -allow-file-access-from-files argument. 57 | Please see: http://code.google.com/p/chromium/issues/detail?id=60889 58 | 59 | ```js 60 | document.getElementById('file').addEventListener('change', function () { 61 | var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, 62 | file = this.files[0], 63 | chunkSize = 2097152, // Read in chunks of 2MB 64 | chunks = Math.ceil(file.size / chunkSize), 65 | currentChunk = 0, 66 | spark = new SparkMD5.ArrayBuffer(), 67 | fileReader = new FileReader(); 68 | 69 | fileReader.onload = function (e) { 70 | console.log('read chunk nr', currentChunk + 1, 'of', chunks); 71 | spark.append(e.target.result); // Append array buffer 72 | currentChunk++; 73 | 74 | if (currentChunk < chunks) { 75 | loadNext(); 76 | } else { 77 | console.log('finished loading'); 78 | console.info('computed hash', spark.end()); // Compute hash 79 | } 80 | }; 81 | 82 | fileReader.onerror = function () { 83 | console.warn('oops, something went wrong.'); 84 | }; 85 | 86 | function loadNext() { 87 | var start = currentChunk * chunkSize, 88 | end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; 89 | 90 | fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); 91 | } 92 | 93 | loadNext(); 94 | }); 95 | ``` 96 | 97 | You can see some more examples in the test folder. 98 | 99 | ## Documentation 100 | 101 | 102 | ### SparkMD5 class 103 | 104 | #### SparkMD5#append(str) 105 | 106 | Appends a string, encoding it to UTF8 if necessary. 107 | 108 | #### SparkMD5#appendBinary(str) 109 | 110 | Appends a binary string (e.g.: string returned from the deprecated [readAsBinaryString](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString)). 111 | 112 | #### SparkMD5#end(raw) 113 | 114 | Finishes the computation of the md5, returning the hex result. 115 | If `raw` is true, the result as a binary string will be returned instead. 116 | 117 | #### SparkMD5#reset() 118 | 119 | Resets the internal state of the computation. 120 | 121 | #### SparkMD5#getState() 122 | 123 | Returns an object representing the internal computation state. 124 | You can pass this state to setState(). This feature is useful to resume an incremental md5. 125 | 126 | #### SparkMD5#setState(state) 127 | 128 | Sets the internal computation state. See: getState(). 129 | 130 | #### SparkMD5#destroy() 131 | 132 | Releases memory used by the incremental buffer and other additional resources. 133 | 134 | #### SparkMD5.hash(str, raw) 135 | 136 | Hashes a string directly, returning the hex result. 137 | If `raw` is true, the result as a binary string will be returned instead. 138 | Note that this function is `static`. 139 | 140 | #### SparkMD5.hashBinary(str, raw) 141 | 142 | Hashes a binary string directly (e.g.: string returned from the deprecated [readAsBinaryString](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString)), returning the hex result. 143 | If `raw` is true, the result as a binary string will be returned instead. 144 | Note that this function is `static`. 145 | 146 | 147 | ### SparkMD5.ArrayBuffer class 148 | 149 | #### SparkMD5.ArrayBuffer#append(arr) 150 | 151 | Appends an array buffer. 152 | 153 | #### SparkMD5.ArrayBuffer#end(raw) 154 | 155 | Finishes the computation of the md5, returning the hex result. 156 | If `raw` is true, the result as a binary string will be returned instead. 157 | 158 | #### SparkMD5.ArrayBuffer#reset() 159 | 160 | Resets the internal state of the computation. 161 | 162 | #### SparkMD5.ArrayBuffer#destroy() 163 | 164 | Releases memory used by the incremental buffer and other additional resources. 165 | 166 | #### SparkMD5.ArrayBuffer#getState() 167 | 168 | Returns an object representing the internal computation state. 169 | You can pass this state to setState(). This feature is useful to resume an incremental md5. 170 | 171 | #### SparkMD5.ArrayBuffer#setState(state) 172 | 173 | Sets the internal computation state. See: getState(). 174 | 175 | #### SparkMD5.ArrayBuffer.hash(arr, raw) 176 | 177 | Hashes an array buffer directly, returning the hex result. 178 | If `raw` is true, the result as a binary string will be returned instead. 179 | Note that this function is `static`. 180 | 181 | 182 | ## License 183 | 184 | The project is double licensed, being [WTF2](./LICENSE) the master license and [MIT](./LICENSE2) the alternative license. 185 | The reason to have two licenses is that some entities refuse to use the master license (WTF2) due to 186 | bad language. If that's also your case, you can choose the alternative license. 187 | 188 | 189 | ## Credits 190 | 191 | [Joseph Myers](http://www.myersdaily.org/joseph/javascript/md5-text.html) 192 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SparkMD5", 3 | "version": "3.0.0", 4 | "homepage": "https://github.com/satazor/js-spark-md5", 5 | "authors": [ 6 | "André Cruz " 7 | ], 8 | "description": "Lightning fast normal and incremental md5 for javascript", 9 | "main": "spark-md5.js", 10 | "keywords": [ 11 | "md5", 12 | "spark", 13 | "incremental", 14 | "fast" 15 | ], 16 | "license": "http://www.wtfpl.net/", 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "md5", 3 | "repo": "satazor/js-spark-md5", 4 | "description": "Lightning fast normal and incremental md5 for javascript", 5 | "version": "2.0.0", 6 | "keywords": [ 7 | "md5", 8 | "fast", 9 | "spark", 10 | "incremental" 11 | ], 12 | "dependencies": {}, 13 | "development": {}, 14 | "license": "WTFPL", 15 | "main": "spark-md5.js", 16 | "scripts": [ 17 | "spark-md5.js" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spark-md5", 3 | "version": "3.0.2", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "spark-md5", 9 | "version": "3.0.2", 10 | "license": "(WTFPL OR MIT)", 11 | "devDependencies": { 12 | "uglify-js": "^3.0.0" 13 | } 14 | }, 15 | "node_modules/uglify-js": { 16 | "version": "3.14.1", 17 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.1.tgz", 18 | "integrity": "sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==", 19 | "dev": true, 20 | "bin": { 21 | "uglifyjs": "bin/uglifyjs" 22 | }, 23 | "engines": { 24 | "node": ">=0.8.0" 25 | } 26 | } 27 | }, 28 | "dependencies": { 29 | "uglify-js": { 30 | "version": "3.14.1", 31 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.1.tgz", 32 | "integrity": "sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==", 33 | "dev": true 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spark-md5", 3 | "version": "3.0.2", 4 | "description": "Lightning fast normal and incremental md5 for javascript", 5 | "main": "spark-md5.js", 6 | "files": [ 7 | "spark-md5.js", 8 | "spark-md5.min.js" 9 | ], 10 | "directories": { 11 | "test": "test" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git@github.com:satazor/js-spark-md5.git" 16 | }, 17 | "keywords": [ 18 | "md5", 19 | "fast", 20 | "spark", 21 | "incremental" 22 | ], 23 | "author": "André Cruz ", 24 | "license": "(WTFPL OR MIT)", 25 | "bugs": { 26 | "url": "https://github.com/satazor/js-spark-md5/issues" 27 | }, 28 | "scripts": { 29 | "min": "uglifyjs spark-md5.js > spark-md5.min.js", 30 | "test": "open test/index.html" 31 | }, 32 | "devDependencies": { 33 | "uglify-js": "^3.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /spark-md5.js: -------------------------------------------------------------------------------- 1 | (function (factory) { 2 | if (typeof exports === 'object') { 3 | // Node/CommonJS 4 | module.exports = factory(); 5 | } else if (typeof define === 'function' && define.amd) { 6 | // AMD 7 | define(factory); 8 | } else { 9 | // Browser globals (with support for web workers) 10 | var glob; 11 | 12 | try { 13 | glob = window; 14 | } catch (e) { 15 | glob = self; 16 | } 17 | 18 | glob.SparkMD5 = factory(); 19 | } 20 | }(function (undefined) { 21 | 22 | 'use strict'; 23 | 24 | /* 25 | * Fastest md5 implementation around (JKM md5). 26 | * Credits: Joseph Myers 27 | * 28 | * @see http://www.myersdaily.org/joseph/javascript/md5-text.html 29 | * @see http://jsperf.com/md5-shootout/7 30 | */ 31 | 32 | /* this function is much faster, 33 | so if possible we use it. Some IEs 34 | are the only ones I know of that 35 | need the idiotic second function, 36 | generated by an if clause. */ 37 | var add32 = function (a, b) { 38 | return (a + b) & 0xFFFFFFFF; 39 | }, 40 | hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; 41 | 42 | 43 | function cmn(q, a, b, x, s, t) { 44 | a = add32(add32(a, q), add32(x, t)); 45 | return add32((a << s) | (a >>> (32 - s)), b); 46 | } 47 | 48 | function md5cycle(x, k) { 49 | var a = x[0], 50 | b = x[1], 51 | c = x[2], 52 | d = x[3]; 53 | 54 | a += (b & c | ~b & d) + k[0] - 680876936 | 0; 55 | a = (a << 7 | a >>> 25) + b | 0; 56 | d += (a & b | ~a & c) + k[1] - 389564586 | 0; 57 | d = (d << 12 | d >>> 20) + a | 0; 58 | c += (d & a | ~d & b) + k[2] + 606105819 | 0; 59 | c = (c << 17 | c >>> 15) + d | 0; 60 | b += (c & d | ~c & a) + k[3] - 1044525330 | 0; 61 | b = (b << 22 | b >>> 10) + c | 0; 62 | a += (b & c | ~b & d) + k[4] - 176418897 | 0; 63 | a = (a << 7 | a >>> 25) + b | 0; 64 | d += (a & b | ~a & c) + k[5] + 1200080426 | 0; 65 | d = (d << 12 | d >>> 20) + a | 0; 66 | c += (d & a | ~d & b) + k[6] - 1473231341 | 0; 67 | c = (c << 17 | c >>> 15) + d | 0; 68 | b += (c & d | ~c & a) + k[7] - 45705983 | 0; 69 | b = (b << 22 | b >>> 10) + c | 0; 70 | a += (b & c | ~b & d) + k[8] + 1770035416 | 0; 71 | a = (a << 7 | a >>> 25) + b | 0; 72 | d += (a & b | ~a & c) + k[9] - 1958414417 | 0; 73 | d = (d << 12 | d >>> 20) + a | 0; 74 | c += (d & a | ~d & b) + k[10] - 42063 | 0; 75 | c = (c << 17 | c >>> 15) + d | 0; 76 | b += (c & d | ~c & a) + k[11] - 1990404162 | 0; 77 | b = (b << 22 | b >>> 10) + c | 0; 78 | a += (b & c | ~b & d) + k[12] + 1804603682 | 0; 79 | a = (a << 7 | a >>> 25) + b | 0; 80 | d += (a & b | ~a & c) + k[13] - 40341101 | 0; 81 | d = (d << 12 | d >>> 20) + a | 0; 82 | c += (d & a | ~d & b) + k[14] - 1502002290 | 0; 83 | c = (c << 17 | c >>> 15) + d | 0; 84 | b += (c & d | ~c & a) + k[15] + 1236535329 | 0; 85 | b = (b << 22 | b >>> 10) + c | 0; 86 | 87 | a += (b & d | c & ~d) + k[1] - 165796510 | 0; 88 | a = (a << 5 | a >>> 27) + b | 0; 89 | d += (a & c | b & ~c) + k[6] - 1069501632 | 0; 90 | d = (d << 9 | d >>> 23) + a | 0; 91 | c += (d & b | a & ~b) + k[11] + 643717713 | 0; 92 | c = (c << 14 | c >>> 18) + d | 0; 93 | b += (c & a | d & ~a) + k[0] - 373897302 | 0; 94 | b = (b << 20 | b >>> 12) + c | 0; 95 | a += (b & d | c & ~d) + k[5] - 701558691 | 0; 96 | a = (a << 5 | a >>> 27) + b | 0; 97 | d += (a & c | b & ~c) + k[10] + 38016083 | 0; 98 | d = (d << 9 | d >>> 23) + a | 0; 99 | c += (d & b | a & ~b) + k[15] - 660478335 | 0; 100 | c = (c << 14 | c >>> 18) + d | 0; 101 | b += (c & a | d & ~a) + k[4] - 405537848 | 0; 102 | b = (b << 20 | b >>> 12) + c | 0; 103 | a += (b & d | c & ~d) + k[9] + 568446438 | 0; 104 | a = (a << 5 | a >>> 27) + b | 0; 105 | d += (a & c | b & ~c) + k[14] - 1019803690 | 0; 106 | d = (d << 9 | d >>> 23) + a | 0; 107 | c += (d & b | a & ~b) + k[3] - 187363961 | 0; 108 | c = (c << 14 | c >>> 18) + d | 0; 109 | b += (c & a | d & ~a) + k[8] + 1163531501 | 0; 110 | b = (b << 20 | b >>> 12) + c | 0; 111 | a += (b & d | c & ~d) + k[13] - 1444681467 | 0; 112 | a = (a << 5 | a >>> 27) + b | 0; 113 | d += (a & c | b & ~c) + k[2] - 51403784 | 0; 114 | d = (d << 9 | d >>> 23) + a | 0; 115 | c += (d & b | a & ~b) + k[7] + 1735328473 | 0; 116 | c = (c << 14 | c >>> 18) + d | 0; 117 | b += (c & a | d & ~a) + k[12] - 1926607734 | 0; 118 | b = (b << 20 | b >>> 12) + c | 0; 119 | 120 | a += (b ^ c ^ d) + k[5] - 378558 | 0; 121 | a = (a << 4 | a >>> 28) + b | 0; 122 | d += (a ^ b ^ c) + k[8] - 2022574463 | 0; 123 | d = (d << 11 | d >>> 21) + a | 0; 124 | c += (d ^ a ^ b) + k[11] + 1839030562 | 0; 125 | c = (c << 16 | c >>> 16) + d | 0; 126 | b += (c ^ d ^ a) + k[14] - 35309556 | 0; 127 | b = (b << 23 | b >>> 9) + c | 0; 128 | a += (b ^ c ^ d) + k[1] - 1530992060 | 0; 129 | a = (a << 4 | a >>> 28) + b | 0; 130 | d += (a ^ b ^ c) + k[4] + 1272893353 | 0; 131 | d = (d << 11 | d >>> 21) + a | 0; 132 | c += (d ^ a ^ b) + k[7] - 155497632 | 0; 133 | c = (c << 16 | c >>> 16) + d | 0; 134 | b += (c ^ d ^ a) + k[10] - 1094730640 | 0; 135 | b = (b << 23 | b >>> 9) + c | 0; 136 | a += (b ^ c ^ d) + k[13] + 681279174 | 0; 137 | a = (a << 4 | a >>> 28) + b | 0; 138 | d += (a ^ b ^ c) + k[0] - 358537222 | 0; 139 | d = (d << 11 | d >>> 21) + a | 0; 140 | c += (d ^ a ^ b) + k[3] - 722521979 | 0; 141 | c = (c << 16 | c >>> 16) + d | 0; 142 | b += (c ^ d ^ a) + k[6] + 76029189 | 0; 143 | b = (b << 23 | b >>> 9) + c | 0; 144 | a += (b ^ c ^ d) + k[9] - 640364487 | 0; 145 | a = (a << 4 | a >>> 28) + b | 0; 146 | d += (a ^ b ^ c) + k[12] - 421815835 | 0; 147 | d = (d << 11 | d >>> 21) + a | 0; 148 | c += (d ^ a ^ b) + k[15] + 530742520 | 0; 149 | c = (c << 16 | c >>> 16) + d | 0; 150 | b += (c ^ d ^ a) + k[2] - 995338651 | 0; 151 | b = (b << 23 | b >>> 9) + c | 0; 152 | 153 | a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; 154 | a = (a << 6 | a >>> 26) + b | 0; 155 | d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; 156 | d = (d << 10 | d >>> 22) + a | 0; 157 | c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; 158 | c = (c << 15 | c >>> 17) + d | 0; 159 | b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; 160 | b = (b << 21 |b >>> 11) + c | 0; 161 | a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; 162 | a = (a << 6 | a >>> 26) + b | 0; 163 | d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; 164 | d = (d << 10 | d >>> 22) + a | 0; 165 | c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; 166 | c = (c << 15 | c >>> 17) + d | 0; 167 | b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; 168 | b = (b << 21 |b >>> 11) + c | 0; 169 | a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; 170 | a = (a << 6 | a >>> 26) + b | 0; 171 | d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; 172 | d = (d << 10 | d >>> 22) + a | 0; 173 | c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; 174 | c = (c << 15 | c >>> 17) + d | 0; 175 | b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; 176 | b = (b << 21 |b >>> 11) + c | 0; 177 | a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; 178 | a = (a << 6 | a >>> 26) + b | 0; 179 | d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; 180 | d = (d << 10 | d >>> 22) + a | 0; 181 | c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; 182 | c = (c << 15 | c >>> 17) + d | 0; 183 | b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; 184 | b = (b << 21 | b >>> 11) + c | 0; 185 | 186 | x[0] = a + x[0] | 0; 187 | x[1] = b + x[1] | 0; 188 | x[2] = c + x[2] | 0; 189 | x[3] = d + x[3] | 0; 190 | } 191 | 192 | function md5blk(s) { 193 | var md5blks = [], 194 | i; /* Andy King said do it this way. */ 195 | 196 | for (i = 0; i < 64; i += 4) { 197 | md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24); 198 | } 199 | return md5blks; 200 | } 201 | 202 | function md5blk_array(a) { 203 | var md5blks = [], 204 | i; /* Andy King said do it this way. */ 205 | 206 | for (i = 0; i < 64; i += 4) { 207 | md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24); 208 | } 209 | return md5blks; 210 | } 211 | 212 | function md51(s) { 213 | var n = s.length, 214 | state = [1732584193, -271733879, -1732584194, 271733878], 215 | i, 216 | length, 217 | tail, 218 | tmp, 219 | lo, 220 | hi; 221 | 222 | for (i = 64; i <= n; i += 64) { 223 | md5cycle(state, md5blk(s.substring(i - 64, i))); 224 | } 225 | s = s.substring(i - 64); 226 | length = s.length; 227 | tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 228 | for (i = 0; i < length; i += 1) { 229 | tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3); 230 | } 231 | tail[i >> 2] |= 0x80 << ((i % 4) << 3); 232 | if (i > 55) { 233 | md5cycle(state, tail); 234 | for (i = 0; i < 16; i += 1) { 235 | tail[i] = 0; 236 | } 237 | } 238 | 239 | // Beware that the final length might not fit in 32 bits so we take care of that 240 | tmp = n * 8; 241 | tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); 242 | lo = parseInt(tmp[2], 16); 243 | hi = parseInt(tmp[1], 16) || 0; 244 | 245 | tail[14] = lo; 246 | tail[15] = hi; 247 | 248 | md5cycle(state, tail); 249 | return state; 250 | } 251 | 252 | function md51_array(a) { 253 | var n = a.length, 254 | state = [1732584193, -271733879, -1732584194, 271733878], 255 | i, 256 | length, 257 | tail, 258 | tmp, 259 | lo, 260 | hi; 261 | 262 | for (i = 64; i <= n; i += 64) { 263 | md5cycle(state, md5blk_array(a.subarray(i - 64, i))); 264 | } 265 | 266 | // Not sure if it is a bug, however IE10 will always produce a sub array of length 1 267 | // containing the last element of the parent array if the sub array specified starts 268 | // beyond the length of the parent array - weird. 269 | // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue 270 | a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0); 271 | 272 | length = a.length; 273 | tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 274 | for (i = 0; i < length; i += 1) { 275 | tail[i >> 2] |= a[i] << ((i % 4) << 3); 276 | } 277 | 278 | tail[i >> 2] |= 0x80 << ((i % 4) << 3); 279 | if (i > 55) { 280 | md5cycle(state, tail); 281 | for (i = 0; i < 16; i += 1) { 282 | tail[i] = 0; 283 | } 284 | } 285 | 286 | // Beware that the final length might not fit in 32 bits so we take care of that 287 | tmp = n * 8; 288 | tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); 289 | lo = parseInt(tmp[2], 16); 290 | hi = parseInt(tmp[1], 16) || 0; 291 | 292 | tail[14] = lo; 293 | tail[15] = hi; 294 | 295 | md5cycle(state, tail); 296 | 297 | return state; 298 | } 299 | 300 | function rhex(n) { 301 | var s = '', 302 | j; 303 | for (j = 0; j < 4; j += 1) { 304 | s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; 305 | } 306 | return s; 307 | } 308 | 309 | function hex(x) { 310 | var i; 311 | for (i = 0; i < x.length; i += 1) { 312 | x[i] = rhex(x[i]); 313 | } 314 | return x.join(''); 315 | } 316 | 317 | // In some cases the fast add32 function cannot be used.. 318 | if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') { 319 | add32 = function (x, y) { 320 | var lsw = (x & 0xFFFF) + (y & 0xFFFF), 321 | msw = (x >> 16) + (y >> 16) + (lsw >> 16); 322 | return (msw << 16) | (lsw & 0xFFFF); 323 | }; 324 | } 325 | 326 | // --------------------------------------------------- 327 | 328 | /** 329 | * ArrayBuffer slice polyfill. 330 | * 331 | * @see https://github.com/ttaubert/node-arraybuffer-slice 332 | */ 333 | 334 | if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) { 335 | (function () { 336 | function clamp(val, length) { 337 | val = (val | 0) || 0; 338 | 339 | if (val < 0) { 340 | return Math.max(val + length, 0); 341 | } 342 | 343 | return Math.min(val, length); 344 | } 345 | 346 | ArrayBuffer.prototype.slice = function (from, to) { 347 | var length = this.byteLength, 348 | begin = clamp(from, length), 349 | end = length, 350 | num, 351 | target, 352 | targetArray, 353 | sourceArray; 354 | 355 | if (to !== undefined) { 356 | end = clamp(to, length); 357 | } 358 | 359 | if (begin > end) { 360 | return new ArrayBuffer(0); 361 | } 362 | 363 | num = end - begin; 364 | target = new ArrayBuffer(num); 365 | targetArray = new Uint8Array(target); 366 | 367 | sourceArray = new Uint8Array(this, begin, num); 368 | targetArray.set(sourceArray); 369 | 370 | return target; 371 | }; 372 | })(); 373 | } 374 | 375 | // --------------------------------------------------- 376 | 377 | /** 378 | * Helpers. 379 | */ 380 | 381 | function toUtf8(str) { 382 | if (/[\u0080-\uFFFF]/.test(str)) { 383 | str = unescape(encodeURIComponent(str)); 384 | } 385 | 386 | return str; 387 | } 388 | 389 | function utf8Str2ArrayBuffer(str, returnUInt8Array) { 390 | var length = str.length, 391 | buff = new ArrayBuffer(length), 392 | arr = new Uint8Array(buff), 393 | i; 394 | 395 | for (i = 0; i < length; i += 1) { 396 | arr[i] = str.charCodeAt(i); 397 | } 398 | 399 | return returnUInt8Array ? arr : buff; 400 | } 401 | 402 | function arrayBuffer2Utf8Str(buff) { 403 | return String.fromCharCode.apply(null, new Uint8Array(buff)); 404 | } 405 | 406 | function concatenateArrayBuffers(first, second, returnUInt8Array) { 407 | var result = new Uint8Array(first.byteLength + second.byteLength); 408 | 409 | result.set(new Uint8Array(first)); 410 | result.set(new Uint8Array(second), first.byteLength); 411 | 412 | return returnUInt8Array ? result : result.buffer; 413 | } 414 | 415 | function hexToBinaryString(hex) { 416 | var bytes = [], 417 | length = hex.length, 418 | x; 419 | 420 | for (x = 0; x < length - 1; x += 2) { 421 | bytes.push(parseInt(hex.substr(x, 2), 16)); 422 | } 423 | 424 | return String.fromCharCode.apply(String, bytes); 425 | } 426 | 427 | // --------------------------------------------------- 428 | 429 | /** 430 | * SparkMD5 OOP implementation. 431 | * 432 | * Use this class to perform an incremental md5, otherwise use the 433 | * static methods instead. 434 | */ 435 | 436 | function SparkMD5() { 437 | // call reset to init the instance 438 | this.reset(); 439 | } 440 | 441 | /** 442 | * Appends a string. 443 | * A conversion will be applied if an utf8 string is detected. 444 | * 445 | * @param {String} str The string to be appended 446 | * 447 | * @return {SparkMD5} The instance itself 448 | */ 449 | SparkMD5.prototype.append = function (str) { 450 | // Converts the string to utf8 bytes if necessary 451 | // Then append as binary 452 | this.appendBinary(toUtf8(str)); 453 | 454 | return this; 455 | }; 456 | 457 | /** 458 | * Appends a binary string. 459 | * 460 | * @param {String} contents The binary string to be appended 461 | * 462 | * @return {SparkMD5} The instance itself 463 | */ 464 | SparkMD5.prototype.appendBinary = function (contents) { 465 | this._buff += contents; 466 | this._length += contents.length; 467 | 468 | var length = this._buff.length, 469 | i; 470 | 471 | for (i = 64; i <= length; i += 64) { 472 | md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i))); 473 | } 474 | 475 | this._buff = this._buff.substring(i - 64); 476 | 477 | return this; 478 | }; 479 | 480 | /** 481 | * Finishes the incremental computation, reseting the internal state and 482 | * returning the result. 483 | * 484 | * @param {Boolean} raw True to get the raw string, false to get the hex string 485 | * 486 | * @return {String} The result 487 | */ 488 | SparkMD5.prototype.end = function (raw) { 489 | var buff = this._buff, 490 | length = buff.length, 491 | i, 492 | tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 493 | ret; 494 | 495 | for (i = 0; i < length; i += 1) { 496 | tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3); 497 | } 498 | 499 | this._finish(tail, length); 500 | ret = hex(this._hash); 501 | 502 | if (raw) { 503 | ret = hexToBinaryString(ret); 504 | } 505 | 506 | this.reset(); 507 | 508 | return ret; 509 | }; 510 | 511 | /** 512 | * Resets the internal state of the computation. 513 | * 514 | * @return {SparkMD5} The instance itself 515 | */ 516 | SparkMD5.prototype.reset = function () { 517 | this._buff = ''; 518 | this._length = 0; 519 | this._hash = [1732584193, -271733879, -1732584194, 271733878]; 520 | 521 | return this; 522 | }; 523 | 524 | /** 525 | * Gets the internal state of the computation. 526 | * 527 | * @return {Object} The state 528 | */ 529 | SparkMD5.prototype.getState = function () { 530 | return { 531 | buff: this._buff, 532 | length: this._length, 533 | hash: this._hash.slice() 534 | }; 535 | }; 536 | 537 | /** 538 | * Gets the internal state of the computation. 539 | * 540 | * @param {Object} state The state 541 | * 542 | * @return {SparkMD5} The instance itself 543 | */ 544 | SparkMD5.prototype.setState = function (state) { 545 | this._buff = state.buff; 546 | this._length = state.length; 547 | this._hash = state.hash; 548 | 549 | return this; 550 | }; 551 | 552 | /** 553 | * Releases memory used by the incremental buffer and other additional 554 | * resources. If you plan to use the instance again, use reset instead. 555 | */ 556 | SparkMD5.prototype.destroy = function () { 557 | delete this._hash; 558 | delete this._buff; 559 | delete this._length; 560 | }; 561 | 562 | /** 563 | * Finish the final calculation based on the tail. 564 | * 565 | * @param {Array} tail The tail (will be modified) 566 | * @param {Number} length The length of the remaining buffer 567 | */ 568 | SparkMD5.prototype._finish = function (tail, length) { 569 | var i = length, 570 | tmp, 571 | lo, 572 | hi; 573 | 574 | tail[i >> 2] |= 0x80 << ((i % 4) << 3); 575 | if (i > 55) { 576 | md5cycle(this._hash, tail); 577 | for (i = 0; i < 16; i += 1) { 578 | tail[i] = 0; 579 | } 580 | } 581 | 582 | // Do the final computation based on the tail and length 583 | // Beware that the final length may not fit in 32 bits so we take care of that 584 | tmp = this._length * 8; 585 | tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/); 586 | lo = parseInt(tmp[2], 16); 587 | hi = parseInt(tmp[1], 16) || 0; 588 | 589 | tail[14] = lo; 590 | tail[15] = hi; 591 | md5cycle(this._hash, tail); 592 | }; 593 | 594 | /** 595 | * Performs the md5 hash on a string. 596 | * A conversion will be applied if utf8 string is detected. 597 | * 598 | * @param {String} str The string 599 | * @param {Boolean} [raw] True to get the raw string, false to get the hex string 600 | * 601 | * @return {String} The result 602 | */ 603 | SparkMD5.hash = function (str, raw) { 604 | // Converts the string to utf8 bytes if necessary 605 | // Then compute it using the binary function 606 | return SparkMD5.hashBinary(toUtf8(str), raw); 607 | }; 608 | 609 | /** 610 | * Performs the md5 hash on a binary string. 611 | * 612 | * @param {String} content The binary string 613 | * @param {Boolean} [raw] True to get the raw string, false to get the hex string 614 | * 615 | * @return {String} The result 616 | */ 617 | SparkMD5.hashBinary = function (content, raw) { 618 | var hash = md51(content), 619 | ret = hex(hash); 620 | 621 | return raw ? hexToBinaryString(ret) : ret; 622 | }; 623 | 624 | // --------------------------------------------------- 625 | 626 | /** 627 | * SparkMD5 OOP implementation for array buffers. 628 | * 629 | * Use this class to perform an incremental md5 ONLY for array buffers. 630 | */ 631 | SparkMD5.ArrayBuffer = function () { 632 | // call reset to init the instance 633 | this.reset(); 634 | }; 635 | 636 | /** 637 | * Appends an array buffer. 638 | * 639 | * @param {ArrayBuffer} arr The array to be appended 640 | * 641 | * @return {SparkMD5.ArrayBuffer} The instance itself 642 | */ 643 | SparkMD5.ArrayBuffer.prototype.append = function (arr) { 644 | var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), 645 | length = buff.length, 646 | i; 647 | 648 | this._length += arr.byteLength; 649 | 650 | for (i = 64; i <= length; i += 64) { 651 | md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i))); 652 | } 653 | 654 | this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0); 655 | 656 | return this; 657 | }; 658 | 659 | /** 660 | * Finishes the incremental computation, reseting the internal state and 661 | * returning the result. 662 | * 663 | * @param {Boolean} raw True to get the raw string, false to get the hex string 664 | * 665 | * @return {String} The result 666 | */ 667 | SparkMD5.ArrayBuffer.prototype.end = function (raw) { 668 | var buff = this._buff, 669 | length = buff.length, 670 | tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 671 | i, 672 | ret; 673 | 674 | for (i = 0; i < length; i += 1) { 675 | tail[i >> 2] |= buff[i] << ((i % 4) << 3); 676 | } 677 | 678 | this._finish(tail, length); 679 | ret = hex(this._hash); 680 | 681 | if (raw) { 682 | ret = hexToBinaryString(ret); 683 | } 684 | 685 | this.reset(); 686 | 687 | return ret; 688 | }; 689 | 690 | /** 691 | * Resets the internal state of the computation. 692 | * 693 | * @return {SparkMD5.ArrayBuffer} The instance itself 694 | */ 695 | SparkMD5.ArrayBuffer.prototype.reset = function () { 696 | this._buff = new Uint8Array(0); 697 | this._length = 0; 698 | this._hash = [1732584193, -271733879, -1732584194, 271733878]; 699 | 700 | return this; 701 | }; 702 | 703 | /** 704 | * Gets the internal state of the computation. 705 | * 706 | * @return {Object} The state 707 | */ 708 | SparkMD5.ArrayBuffer.prototype.getState = function () { 709 | var state = SparkMD5.prototype.getState.call(this); 710 | 711 | // Convert buffer to a string 712 | state.buff = arrayBuffer2Utf8Str(state.buff); 713 | 714 | return state; 715 | }; 716 | 717 | /** 718 | * Gets the internal state of the computation. 719 | * 720 | * @param {Object} state The state 721 | * 722 | * @return {SparkMD5.ArrayBuffer} The instance itself 723 | */ 724 | SparkMD5.ArrayBuffer.prototype.setState = function (state) { 725 | // Convert string to buffer 726 | state.buff = utf8Str2ArrayBuffer(state.buff, true); 727 | 728 | return SparkMD5.prototype.setState.call(this, state); 729 | }; 730 | 731 | SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy; 732 | 733 | SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish; 734 | 735 | /** 736 | * Performs the md5 hash on an array buffer. 737 | * 738 | * @param {ArrayBuffer} arr The array buffer 739 | * @param {Boolean} [raw] True to get the raw string, false to get the hex one 740 | * 741 | * @return {String} The result 742 | */ 743 | SparkMD5.ArrayBuffer.hash = function (arr, raw) { 744 | var hash = md51_array(new Uint8Array(arr)), 745 | ret = hex(hash); 746 | 747 | return raw ? hexToBinaryString(ret) : ret; 748 | }; 749 | 750 | return SparkMD5; 751 | })); 752 | -------------------------------------------------------------------------------- /spark-md5.min.js: -------------------------------------------------------------------------------- 1 | (function(factory){if(typeof exports==="object"){module.exports=factory()}else if(typeof define==="function"&&define.amd){define(factory)}else{var glob;try{glob=window}catch(e){glob=self}glob.SparkMD5=factory()}})(function(undefined){"use strict";var add32=function(a,b){return a+b&4294967295},hex_chr=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];function cmn(q,a,b,x,s,t){a=add32(add32(a,q),add32(x,t));return add32(a<>>32-s,b)}function md5cycle(x,k){var a=x[0],b=x[1],c=x[2],d=x[3];a+=(b&c|~b&d)+k[0]-680876936|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[1]-389564586|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[2]+606105819|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[3]-1044525330|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[4]-176418897|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[5]+1200080426|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[6]-1473231341|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[7]-45705983|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[8]+1770035416|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[9]-1958414417|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[10]-42063|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[11]-1990404162|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[12]+1804603682|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[13]-40341101|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[14]-1502002290|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[15]+1236535329|0;b=(b<<22|b>>>10)+c|0;a+=(b&d|c&~d)+k[1]-165796510|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[6]-1069501632|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[11]+643717713|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[0]-373897302|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[5]-701558691|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[10]+38016083|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[15]-660478335|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[4]-405537848|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[9]+568446438|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[14]-1019803690|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[3]-187363961|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[8]+1163531501|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[13]-1444681467|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[2]-51403784|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[7]+1735328473|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[12]-1926607734|0;b=(b<<20|b>>>12)+c|0;a+=(b^c^d)+k[5]-378558|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[8]-2022574463|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[11]+1839030562|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[14]-35309556|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[1]-1530992060|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[4]+1272893353|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[7]-155497632|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[10]-1094730640|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[13]+681279174|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[0]-358537222|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[3]-722521979|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[6]+76029189|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[9]-640364487|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[12]-421815835|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[15]+530742520|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[2]-995338651|0;b=(b<<23|b>>>9)+c|0;a+=(c^(b|~d))+k[0]-198630844|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[7]+1126891415|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[14]-1416354905|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[5]-57434055|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[12]+1700485571|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[3]-1894986606|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[10]-1051523|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[1]-2054922799|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[8]+1873313359|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[15]-30611744|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[6]-1560198380|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[13]+1309151649|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[4]-145523070|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[11]-1120210379|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[2]+718787259|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[9]-343485551|0;b=(b<<21|b>>>11)+c|0;x[0]=a+x[0]|0;x[1]=b+x[1]|0;x[2]=c+x[2]|0;x[3]=d+x[3]|0}function md5blk(s){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=s.charCodeAt(i)+(s.charCodeAt(i+1)<<8)+(s.charCodeAt(i+2)<<16)+(s.charCodeAt(i+3)<<24)}return md5blks}function md5blk_array(a){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=a[i]+(a[i+1]<<8)+(a[i+2]<<16)+(a[i+3]<<24)}return md5blks}function md51(s){var n=s.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk(s.substring(i-64,i)))}s=s.substring(i-64);length=s.length;tail=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(i=0;i>2]|=s.charCodeAt(i)<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function md51_array(a){var n=a.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk_array(a.subarray(i-64,i)))}a=i-64>2]|=a[i]<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function rhex(n){var s="",j;for(j=0;j<4;j+=1){s+=hex_chr[n>>j*8+4&15]+hex_chr[n>>j*8&15]}return s}function hex(x){var i;for(i=0;i>16)+(y>>16)+(lsw>>16);return msw<<16|lsw&65535}}if(typeof ArrayBuffer!=="undefined"&&!ArrayBuffer.prototype.slice){(function(){function clamp(val,length){val=val|0||0;if(val<0){return Math.max(val+length,0)}return Math.min(val,length)}ArrayBuffer.prototype.slice=function(from,to){var length=this.byteLength,begin=clamp(from,length),end=length,num,target,targetArray,sourceArray;if(to!==undefined){end=clamp(to,length)}if(begin>end){return new ArrayBuffer(0)}num=end-begin;target=new ArrayBuffer(num);targetArray=new Uint8Array(target);sourceArray=new Uint8Array(this,begin,num);targetArray.set(sourceArray);return target}})()}function toUtf8(str){if(/[\u0080-\uFFFF]/.test(str)){str=unescape(encodeURIComponent(str))}return str}function utf8Str2ArrayBuffer(str,returnUInt8Array){var length=str.length,buff=new ArrayBuffer(length),arr=new Uint8Array(buff),i;for(i=0;i>2]|=buff.charCodeAt(i)<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.prototype.reset=function(){this._buff="";this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}};SparkMD5.prototype.setState=function(state){this._buff=state.buff;this._length=state.length;this._hash=state.hash;return this};SparkMD5.prototype.destroy=function(){delete this._hash;delete this._buff;delete this._length};SparkMD5.prototype._finish=function(tail,length){var i=length,tmp,lo,hi;tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(this._hash,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=this._length*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(this._hash,tail)};SparkMD5.hash=function(str,raw){return SparkMD5.hashBinary(toUtf8(str),raw)};SparkMD5.hashBinary=function(content,raw){var hash=md51(content),ret=hex(hash);return raw?hexToBinaryString(ret):ret};SparkMD5.ArrayBuffer=function(){this.reset()};SparkMD5.ArrayBuffer.prototype.append=function(arr){var buff=concatenateArrayBuffers(this._buff.buffer,arr,true),length=buff.length,i;this._length+=arr.byteLength;for(i=64;i<=length;i+=64){md5cycle(this._hash,md5blk_array(buff.subarray(i-64,i)))}this._buff=i-64>2]|=buff[i]<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.ArrayBuffer.prototype.reset=function(){this._buff=new Uint8Array(0);this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.ArrayBuffer.prototype.getState=function(){var state=SparkMD5.prototype.getState.call(this);state.buff=arrayBuffer2Utf8Str(state.buff);return state};SparkMD5.ArrayBuffer.prototype.setState=function(state){state.buff=utf8Str2ArrayBuffer(state.buff,true);return SparkMD5.prototype.setState.call(this,state)};SparkMD5.ArrayBuffer.prototype.destroy=SparkMD5.prototype.destroy;SparkMD5.ArrayBuffer.prototype._finish=SparkMD5.prototype._finish;SparkMD5.ArrayBuffer.hash=function(arr,raw){var hash=md51_array(new Uint8Array(arr)),ret=hex(hash);return raw?hexToBinaryString(ret):ret};return SparkMD5}); 2 | -------------------------------------------------------------------------------- /test/css/bootstrap-1.4.min.css: -------------------------------------------------------------------------------- 1 | html,body{margin:0;padding:0;} 2 | h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,cite,code,del,dfn,em,img,q,s,samp,small,strike,strong,sub,sup,tt,var,dd,dl,dt,li,ol,ul,fieldset,form,label,legend,button,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;} 3 | table{border-collapse:collapse;border-spacing:0;} 4 | ol,ul{list-style:none;} 5 | q:before,q:after,blockquote:before,blockquote:after{content:"";} 6 | html{overflow-y:scroll;font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} 7 | a:focus{outline:thin dotted;} 8 | a:hover,a:active{outline:0;} 9 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;} 10 | audio,canvas,video{display:inline-block;*display:inline;*zoom:1;} 11 | audio:not([controls]){display:none;} 12 | sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} 13 | sup{top:-0.5em;} 14 | sub{bottom:-0.25em;} 15 | img{border:0;-ms-interpolation-mode:bicubic;} 16 | button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;} 17 | button,input{line-height:normal;*overflow:visible;} 18 | button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} 19 | button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;} 20 | input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} 21 | input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} 22 | textarea{overflow:auto;vertical-align:top;} 23 | body{background-color:#ffffff;margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;color:#404040;} 24 | .container{width:940px;margin-left:auto;margin-right:auto;zoom:1;}.container:before,.container:after{display:table;content:"";zoom:1;} 25 | .container:after{clear:both;} 26 | .container-fluid{position:relative;min-width:940px;padding-left:20px;padding-right:20px;zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";zoom:1;} 27 | .container-fluid:after{clear:both;} 28 | .container-fluid>.sidebar{position:absolute;top:0;left:20px;width:220px;} 29 | .container-fluid>.content{margin-left:240px;} 30 | a{color:#0069d6;text-decoration:none;line-height:inherit;font-weight:inherit;}a:hover{color:#00438a;text-decoration:underline;} 31 | .pull-right{float:right;} 32 | .pull-left{float:left;} 33 | .hide{display:none;} 34 | .show{display:block;} 35 | .row{zoom:1;margin-left:-20px;}.row:before,.row:after{display:table;content:"";zoom:1;} 36 | .row:after{clear:both;} 37 | .row>[class*="span"]{display:inline;float:left;margin-left:20px;} 38 | .span1{width:40px;} 39 | .span2{width:100px;} 40 | .span3{width:160px;} 41 | .span4{width:220px;} 42 | .span5{width:280px;} 43 | .span6{width:340px;} 44 | .span7{width:400px;} 45 | .span8{width:460px;} 46 | .span9{width:520px;} 47 | .span10{width:580px;} 48 | .span11{width:640px;} 49 | .span12{width:700px;} 50 | .span13{width:760px;} 51 | .span14{width:820px;} 52 | .span15{width:880px;} 53 | .span16{width:940px;} 54 | .span17{width:1000px;} 55 | .span18{width:1060px;} 56 | .span19{width:1120px;} 57 | .span20{width:1180px;} 58 | .span21{width:1240px;} 59 | .span22{width:1300px;} 60 | .span23{width:1360px;} 61 | .span24{width:1420px;} 62 | .row >.offset1{margin-left:80px;} 63 | .row >.offset2{margin-left:140px;} 64 | .row >.offset3{margin-left:200px;} 65 | .row >.offset4{margin-left:260px;} 66 | .row >.offset5{margin-left:320px;} 67 | .row >.offset6{margin-left:380px;} 68 | .row >.offset7{margin-left:440px;} 69 | .row >.offset8{margin-left:500px;} 70 | .row >.offset9{margin-left:560px;} 71 | .row >.offset10{margin-left:620px;} 72 | .row >.offset11{margin-left:680px;} 73 | .row >.offset12{margin-left:740px;} 74 | .span-one-third{width:300px;} 75 | .span-two-thirds{width:620px;} 76 | .offset-one-third{margin-left:340px;} 77 | .offset-two-thirds{margin-left:660px;} 78 | p{font-size:13px;font-weight:normal;line-height:18px;margin-bottom:9px;}p small{font-size:11px;color:#bfbfbf;} 79 | h1,h2,h3,h4,h5,h6{font-weight:bold;color:#404040;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:#bfbfbf;} 80 | h1{margin-bottom:18px;font-size:30px;line-height:36px;}h1 small{font-size:18px;} 81 | h2{font-size:24px;line-height:36px;}h2 small{font-size:14px;} 82 | h3,h4,h5,h6{line-height:36px;} 83 | h3{font-size:18px;}h3 small{font-size:14px;} 84 | h4{font-size:16px;}h4 small{font-size:12px;} 85 | h5{font-size:14px;} 86 | h6{font-size:13px;color:#bfbfbf;text-transform:uppercase;} 87 | ul,ol{margin:0 0 18px 25px;} 88 | ul ul,ul ol,ol ol,ol ul{margin-bottom:0;} 89 | ul{list-style:disc;} 90 | ol{list-style:decimal;} 91 | li{line-height:18px;color:#808080;} 92 | ul.unstyled{list-style:none;margin-left:0;} 93 | dl{margin-bottom:18px;}dl dt,dl dd{line-height:18px;} 94 | dl dt{font-weight:bold;} 95 | dl dd{margin-left:9px;} 96 | hr{margin:20px 0 19px;border:0;border-bottom:1px solid #eee;} 97 | strong{font-style:inherit;font-weight:bold;} 98 | em{font-style:italic;font-weight:inherit;line-height:inherit;} 99 | .muted{color:#bfbfbf;} 100 | blockquote{margin-bottom:18px;border-left:5px solid #eee;padding-left:15px;}blockquote p{font-size:14px;font-weight:300;line-height:18px;margin-bottom:0;} 101 | blockquote small{display:block;font-size:12px;font-weight:300;line-height:18px;color:#bfbfbf;}blockquote small:before{content:'\2014 \00A0';} 102 | address{display:block;line-height:18px;margin-bottom:18px;} 103 | code,pre{padding:0 3px 2px;font-family:Monaco, Andale Mono, Courier New, monospace;font-size:12px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} 104 | code{background-color:#fee9cc;color:rgba(0, 0, 0, 0.75);padding:1px 3px;} 105 | pre{background-color:#f5f5f5;display:block;padding:8.5px;margin:0 0 18px;line-height:18px;font-size:12px;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;white-space:pre;white-space:pre-wrap;word-wrap:break-word;} 106 | form{margin-bottom:18px;} 107 | fieldset{margin-bottom:18px;padding-top:18px;}fieldset legend{display:block;padding-left:150px;font-size:19.5px;line-height:1;color:#404040;*padding:0 0 5px 145px;*line-height:1.5;} 108 | form .clearfix{margin-bottom:18px;zoom:1;}form .clearfix:before,form .clearfix:after{display:table;content:"";zoom:1;} 109 | form .clearfix:after{clear:both;} 110 | label,input,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:normal;} 111 | label{padding-top:6px;font-size:13px;line-height:18px;float:left;width:130px;text-align:right;color:#404040;} 112 | form .input{margin-left:150px;} 113 | input[type=checkbox],input[type=radio]{cursor:pointer;} 114 | input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;font-size:13px;line-height:18px;color:#808080;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} 115 | select{padding:initial;} 116 | input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:none;} 117 | input[type=file]{background-color:#ffffff;padding:initial;border:initial;line-height:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 118 | input[type=button],input[type=reset],input[type=submit]{width:auto;height:auto;} 119 | select,input[type=file]{height:27px;*height:auto;line-height:27px;*margin-top:4px;} 120 | select[multiple]{height:inherit;background-color:#ffffff;} 121 | textarea{height:auto;} 122 | .uneditable-input{background-color:#ffffff;display:block;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} 123 | :-moz-placeholder{color:#bfbfbf;} 124 | ::-webkit-input-placeholder{color:#bfbfbf;} 125 | input,textarea{-webkit-transform-style:preserve-3d;-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);} 126 | input:focus,textarea:focus{outline:0;border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);} 127 | input[type=file]:focus,input[type=checkbox]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:1px dotted #666;} 128 | form .clearfix.error>label,form .clearfix.error .help-block,form .clearfix.error .help-inline{color:#b94a48;} 129 | form .clearfix.error input,form .clearfix.error textarea{color:#b94a48;border-color:#ee5f5b;}form .clearfix.error input:focus,form .clearfix.error textarea:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;} 130 | form .clearfix.error .input-prepend .add-on,form .clearfix.error .input-append .add-on{color:#b94a48;background-color:#fce6e6;border-color:#b94a48;} 131 | form .clearfix.warning>label,form .clearfix.warning .help-block,form .clearfix.warning .help-inline{color:#c09853;} 132 | form .clearfix.warning input,form .clearfix.warning textarea{color:#c09853;border-color:#ccae64;}form .clearfix.warning input:focus,form .clearfix.warning textarea:focus{border-color:#be9a3f;-webkit-box-shadow:0 0 6px #e5d6b1;-moz-box-shadow:0 0 6px #e5d6b1;box-shadow:0 0 6px #e5d6b1;} 133 | form .clearfix.warning .input-prepend .add-on,form .clearfix.warning .input-append .add-on{color:#c09853;background-color:#d2b877;border-color:#c09853;} 134 | form .clearfix.success>label,form .clearfix.success .help-block,form .clearfix.success .help-inline{color:#468847;} 135 | form .clearfix.success input,form .clearfix.success textarea{color:#468847;border-color:#57a957;}form .clearfix.success input:focus,form .clearfix.success textarea:focus{border-color:#458845;-webkit-box-shadow:0 0 6px #9acc9a;-moz-box-shadow:0 0 6px #9acc9a;box-shadow:0 0 6px #9acc9a;} 136 | form .clearfix.success .input-prepend .add-on,form .clearfix.success .input-append .add-on{color:#468847;background-color:#bcddbc;border-color:#468847;} 137 | .input-mini,input.mini,textarea.mini,select.mini{width:60px;} 138 | .input-small,input.small,textarea.small,select.small{width:90px;} 139 | .input-medium,input.medium,textarea.medium,select.medium{width:150px;} 140 | .input-large,input.large,textarea.large,select.large{width:210px;} 141 | .input-xlarge,input.xlarge,textarea.xlarge,select.xlarge{width:270px;} 142 | .input-xxlarge,input.xxlarge,textarea.xxlarge,select.xxlarge{width:530px;} 143 | textarea.xxlarge{overflow-y:auto;} 144 | input.span1,textarea.span1{display:inline-block;float:none;width:30px;margin-left:0;} 145 | input.span2,textarea.span2{display:inline-block;float:none;width:90px;margin-left:0;} 146 | input.span3,textarea.span3{display:inline-block;float:none;width:150px;margin-left:0;} 147 | input.span4,textarea.span4{display:inline-block;float:none;width:210px;margin-left:0;} 148 | input.span5,textarea.span5{display:inline-block;float:none;width:270px;margin-left:0;} 149 | input.span6,textarea.span6{display:inline-block;float:none;width:330px;margin-left:0;} 150 | input.span7,textarea.span7{display:inline-block;float:none;width:390px;margin-left:0;} 151 | input.span8,textarea.span8{display:inline-block;float:none;width:450px;margin-left:0;} 152 | input.span9,textarea.span9{display:inline-block;float:none;width:510px;margin-left:0;} 153 | input.span10,textarea.span10{display:inline-block;float:none;width:570px;margin-left:0;} 154 | input.span11,textarea.span11{display:inline-block;float:none;width:630px;margin-left:0;} 155 | input.span12,textarea.span12{display:inline-block;float:none;width:690px;margin-left:0;} 156 | input.span13,textarea.span13{display:inline-block;float:none;width:750px;margin-left:0;} 157 | input.span14,textarea.span14{display:inline-block;float:none;width:810px;margin-left:0;} 158 | input.span15,textarea.span15{display:inline-block;float:none;width:870px;margin-left:0;} 159 | input.span16,textarea.span16{display:inline-block;float:none;width:930px;margin-left:0;} 160 | input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;} 161 | .actions{background:#f5f5f5;margin-top:18px;margin-bottom:18px;padding:17px 20px 18px 150px;border-top:1px solid #ddd;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;}.actions .secondary-action{float:right;}.actions .secondary-action a{line-height:30px;}.actions .secondary-action a:hover{text-decoration:underline;} 162 | .help-inline,.help-block{font-size:13px;line-height:18px;color:#bfbfbf;} 163 | .help-inline{padding-left:5px;*position:relative;*top:-5px;} 164 | .help-block{display:block;max-width:600px;} 165 | .inline-inputs{color:#808080;}.inline-inputs span{padding:0 2px 0 1px;} 166 | .input-prepend input,.input-append input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} 167 | .input-prepend .add-on,.input-append .add-on{position:relative;background:#f5f5f5;border:1px solid #ccc;z-index:2;float:left;display:block;width:auto;min-width:16px;height:18px;padding:4px 4px 4px 5px;margin-right:-1px;font-weight:normal;line-height:18px;color:#bfbfbf;text-align:center;text-shadow:0 1px 0 #ffffff;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} 168 | .input-prepend .active,.input-append .active{background:#a9dba9;border-color:#46a546;} 169 | .input-prepend .add-on{*margin-top:1px;} 170 | .input-append input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} 171 | .input-append .add-on{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;margin-right:0;margin-left:-1px;} 172 | .inputs-list{margin:0 0 5px;width:100%;}.inputs-list li{display:block;padding:0;width:100%;} 173 | .inputs-list label{display:block;float:none;width:auto;padding:0;margin-left:20px;line-height:18px;text-align:left;white-space:normal;}.inputs-list label strong{color:#808080;} 174 | .inputs-list label small{font-size:11px;font-weight:normal;} 175 | .inputs-list .inputs-list{margin-left:25px;margin-bottom:10px;padding-top:0;} 176 | .inputs-list:first-child{padding-top:6px;} 177 | .inputs-list li+li{padding-top:2px;} 178 | .inputs-list input[type=radio],.inputs-list input[type=checkbox]{margin-bottom:0;margin-left:-20px;float:left;} 179 | .form-stacked{padding-left:20px;}.form-stacked fieldset{padding-top:9px;} 180 | .form-stacked legend{padding-left:0;} 181 | .form-stacked label{display:block;float:none;width:auto;font-weight:bold;text-align:left;line-height:20px;padding-top:0;} 182 | .form-stacked .clearfix{margin-bottom:9px;}.form-stacked .clearfix div.input{margin-left:0;} 183 | .form-stacked .inputs-list{margin-bottom:0;}.form-stacked .inputs-list li{padding-top:0;}.form-stacked .inputs-list li label{font-weight:normal;padding-top:0;} 184 | .form-stacked div.clearfix.error{padding-top:10px;padding-bottom:10px;padding-left:10px;margin-top:0;margin-left:-10px;} 185 | .form-stacked .actions{margin-left:-20px;padding-left:20px;} 186 | table{width:100%;margin-bottom:18px;padding:0;font-size:13px;border-collapse:collapse;}table th,table td{padding:10px 10px 9px;line-height:18px;text-align:left;} 187 | table th{padding-top:9px;font-weight:bold;vertical-align:middle;} 188 | table td{vertical-align:top;border-top:1px solid #ddd;} 189 | table tbody th{border-top:1px solid #ddd;vertical-align:top;} 190 | .condensed-table th,.condensed-table td{padding:5px 5px 4px;} 191 | .bordered-table{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.bordered-table th+th,.bordered-table td+td,.bordered-table th+td{border-left:1px solid #ddd;} 192 | .bordered-table thead tr:first-child th:first-child,.bordered-table tbody tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;} 193 | .bordered-table thead tr:first-child th:last-child,.bordered-table tbody tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;} 194 | .bordered-table tbody tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;} 195 | .bordered-table tbody tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;} 196 | table .span1{width:20px;} 197 | table .span2{width:60px;} 198 | table .span3{width:100px;} 199 | table .span4{width:140px;} 200 | table .span5{width:180px;} 201 | table .span6{width:220px;} 202 | table .span7{width:260px;} 203 | table .span8{width:300px;} 204 | table .span9{width:340px;} 205 | table .span10{width:380px;} 206 | table .span11{width:420px;} 207 | table .span12{width:460px;} 208 | table .span13{width:500px;} 209 | table .span14{width:540px;} 210 | table .span15{width:580px;} 211 | table .span16{width:620px;} 212 | .zebra-striped tbody tr:nth-child(odd) td,.zebra-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;} 213 | .zebra-striped tbody tr:hover td,.zebra-striped tbody tr:hover th{background-color:#f5f5f5;} 214 | table .header{cursor:pointer;}table .header:after{content:"";float:right;margin-top:7px;border-width:0 4px 4px;border-style:solid;border-color:#000 transparent;visibility:hidden;} 215 | table .headerSortUp,table .headerSortDown{background-color:rgba(141, 192, 219, 0.25);text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);} 216 | table .header:hover:after{visibility:visible;} 217 | table .headerSortDown:after,table .headerSortDown:hover:after{visibility:visible;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;} 218 | table .headerSortUp:after{border-bottom:none;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000;visibility:visible;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:alpha(opacity=60);-khtml-opacity:0.6;-moz-opacity:0.6;opacity:0.6;} 219 | table .blue{color:#049cdb;border-bottom-color:#049cdb;} 220 | table .headerSortUp.blue,table .headerSortDown.blue{background-color:#ade6fe;} 221 | table .green{color:#46a546;border-bottom-color:#46a546;} 222 | table .headerSortUp.green,table .headerSortDown.green{background-color:#cdeacd;} 223 | table .red{color:#9d261d;border-bottom-color:#9d261d;} 224 | table .headerSortUp.red,table .headerSortDown.red{background-color:#f4c8c5;} 225 | table .yellow{color:#ffc40d;border-bottom-color:#ffc40d;} 226 | table .headerSortUp.yellow,table .headerSortDown.yellow{background-color:#fff6d9;} 227 | table .orange{color:#f89406;border-bottom-color:#f89406;} 228 | table .headerSortUp.orange,table .headerSortDown.orange{background-color:#fee9cc;} 229 | table .purple{color:#7a43b6;border-bottom-color:#7a43b6;} 230 | table .headerSortUp.purple,table .headerSortDown.purple{background-color:#e2d5f0;} 231 | .topbar{height:40px;position:fixed;top:0;left:0;right:0;z-index:10000;overflow:visible;}.topbar a{color:#bfbfbf;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);} 232 | .topbar h3 a:hover,.topbar .brand:hover,.topbar ul .active>a{background-color:#333;background-color:rgba(255, 255, 255, 0.05);color:#ffffff;text-decoration:none;} 233 | .topbar h3{position:relative;} 234 | .topbar h3 a,.topbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;color:#ffffff;font-size:20px;font-weight:200;line-height:1;} 235 | .topbar p{margin:0;line-height:40px;}.topbar p a:hover{background-color:transparent;color:#ffffff;} 236 | .topbar form{float:left;margin:5px 0 0 0;position:relative;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} 237 | .topbar form.pull-right{float:right;} 238 | .topbar input{background-color:#444;background-color:rgba(255, 255, 255, 0.3);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:normal;font-weight:13px;line-height:1;padding:4px 9px;color:#ffffff;color:rgba(255, 255, 255, 0.75);border:1px solid #111;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.25);-webkit-transform-style:preserve-3d;-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.topbar input:-moz-placeholder{color:#e6e6e6;} 239 | .topbar input::-webkit-input-placeholder{color:#e6e6e6;} 240 | .topbar input:hover{background-color:#bfbfbf;background-color:rgba(255, 255, 255, 0.5);color:#ffffff;} 241 | .topbar input:focus,.topbar input.focused{outline:0;background-color:#ffffff;color:#404040;text-shadow:0 1px 0 #ffffff;border:0;padding:5px 10px;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);} 242 | .topbar-inner,.topbar .fill{background-color:#222;background-color:#222222;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);} 243 | .topbar div>ul,.nav{display:block;float:left;margin:0 10px 0 0;position:relative;left:0;}.topbar div>ul>li,.nav>li{display:block;float:left;} 244 | .topbar div>ul a,.nav a{display:block;float:none;padding:10px 10px 11px;line-height:19px;text-decoration:none;}.topbar div>ul a:hover,.nav a:hover{color:#ffffff;text-decoration:none;} 245 | .topbar div>ul .active>a,.nav .active>a{background-color:#222;background-color:rgba(0, 0, 0, 0.5);} 246 | .topbar div>ul.secondary-nav,.nav.secondary-nav{float:right;margin-left:10px;margin-right:0;}.topbar div>ul.secondary-nav .menu-dropdown,.nav.secondary-nav .menu-dropdown,.topbar div>ul.secondary-nav .dropdown-menu,.nav.secondary-nav .dropdown-menu{right:0;border:0;} 247 | .topbar div>ul a.menu:hover,.nav a.menu:hover,.topbar div>ul li.open .menu,.nav li.open .menu,.topbar div>ul .dropdown-toggle:hover,.nav .dropdown-toggle:hover,.topbar div>ul .dropdown.open .dropdown-toggle,.nav .dropdown.open .dropdown-toggle{background:#444;background:rgba(255, 255, 255, 0.05);} 248 | .topbar div>ul .menu-dropdown,.nav .menu-dropdown,.topbar div>ul .dropdown-menu,.nav .dropdown-menu{background-color:#333;}.topbar div>ul .menu-dropdown a.menu,.nav .menu-dropdown a.menu,.topbar div>ul .dropdown-menu a.menu,.nav .dropdown-menu a.menu,.topbar div>ul .menu-dropdown .dropdown-toggle,.nav .menu-dropdown .dropdown-toggle,.topbar div>ul .dropdown-menu .dropdown-toggle,.nav .dropdown-menu .dropdown-toggle{color:#ffffff;}.topbar div>ul .menu-dropdown a.menu.open,.nav .menu-dropdown a.menu.open,.topbar div>ul .dropdown-menu a.menu.open,.nav .dropdown-menu a.menu.open,.topbar div>ul .menu-dropdown .dropdown-toggle.open,.nav .menu-dropdown .dropdown-toggle.open,.topbar div>ul .dropdown-menu .dropdown-toggle.open,.nav .dropdown-menu .dropdown-toggle.open{background:#444;background:rgba(255, 255, 255, 0.05);} 249 | .topbar div>ul .menu-dropdown li a,.nav .menu-dropdown li a,.topbar div>ul .dropdown-menu li a,.nav .dropdown-menu li a{color:#999;text-shadow:0 1px 0 rgba(0, 0, 0, 0.5);}.topbar div>ul .menu-dropdown li a:hover,.nav .menu-dropdown li a:hover,.topbar div>ul .dropdown-menu li a:hover,.nav .dropdown-menu li a:hover{background-color:#191919;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919));background-image:-moz-linear-gradient(top, #292929, #191919);background-image:-ms-linear-gradient(top, #292929, #191919);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919));background-image:-webkit-linear-gradient(top, #292929, #191919);background-image:-o-linear-gradient(top, #292929, #191919);background-image:linear-gradient(top, #292929, #191919);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0);color:#ffffff;} 250 | .topbar div>ul .menu-dropdown .active a,.nav .menu-dropdown .active a,.topbar div>ul .dropdown-menu .active a,.nav .dropdown-menu .active a{color:#ffffff;} 251 | .topbar div>ul .menu-dropdown .divider,.nav .menu-dropdown .divider,.topbar div>ul .dropdown-menu .divider,.nav .dropdown-menu .divider{background-color:#222;border-color:#444;} 252 | .topbar ul .menu-dropdown li a,.topbar ul .dropdown-menu li a{padding:4px 15px;} 253 | li.menu,.dropdown{position:relative;} 254 | a.menu:after,.dropdown-toggle:after{width:0;height:0;display:inline-block;content:"↓";text-indent:-99999px;vertical-align:top;margin-top:8px;margin-left:4px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} 255 | .menu-dropdown,.dropdown-menu{background-color:#ffffff;float:left;display:none;position:absolute;top:40px;z-index:900;min-width:160px;max-width:220px;_width:160px;margin-left:0;margin-right:0;padding:6px 0;zoom:1;border-color:#999;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:0 1px 1px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);box-shadow:0 2px 4px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.menu-dropdown li,.dropdown-menu li{float:none;display:block;background-color:none;} 256 | .menu-dropdown .divider,.dropdown-menu .divider{height:1px;margin:5px 0;overflow:hidden;background-color:#eee;border-bottom:1px solid #ffffff;} 257 | .topbar .dropdown-menu a,.dropdown-menu a{display:block;padding:4px 15px;clear:both;font-weight:normal;line-height:18px;color:#808080;text-shadow:0 1px 0 #ffffff;}.topbar .dropdown-menu a:hover,.dropdown-menu a:hover,.topbar .dropdown-menu a.hover,.dropdown-menu a.hover{background-color:#dddddd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));background-image:-moz-linear-gradient(top, #eeeeee, #dddddd);background-image:-ms-linear-gradient(top, #eeeeee, #dddddd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd));background-image:-webkit-linear-gradient(top, #eeeeee, #dddddd);background-image:-o-linear-gradient(top, #eeeeee, #dddddd);background-image:linear-gradient(top, #eeeeee, #dddddd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0);color:#404040;text-decoration:none;-webkit-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.025),inset 0 -1px rgba(0, 0, 0, 0.025);} 258 | .open .menu,.dropdown.open .menu,.open .dropdown-toggle,.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);} 259 | .open .menu-dropdown,.dropdown.open .menu-dropdown,.open .dropdown-menu,.dropdown.open .dropdown-menu{display:block;} 260 | .tabs,.pills{margin:0 0 18px;padding:0;list-style:none;zoom:1;}.tabs:before,.pills:before,.tabs:after,.pills:after{display:table;content:"";zoom:1;} 261 | .tabs:after,.pills:after{clear:both;} 262 | .tabs>li,.pills>li{float:left;}.tabs>li>a,.pills>li>a{display:block;} 263 | .tabs{border-color:#ddd;border-style:solid;border-width:0 0 1px;}.tabs>li{position:relative;margin-bottom:-1px;}.tabs>li>a{padding:0 15px;margin-right:2px;line-height:34px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.tabs>li>a:hover{text-decoration:none;background-color:#eee;border-color:#eee #eee #ddd;} 264 | .tabs .active>a,.tabs .active>a:hover{color:#808080;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;} 265 | .tabs .menu-dropdown,.tabs .dropdown-menu{top:35px;border-width:1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;} 266 | .tabs a.menu:after,.tabs .dropdown-toggle:after{border-top-color:#999;margin-top:15px;margin-left:5px;} 267 | .tabs li.open.menu .menu,.tabs .open.dropdown .dropdown-toggle{border-color:#999;} 268 | .tabs li.open a.menu:after,.tabs .dropdown.open .dropdown-toggle:after{border-top-color:#555;} 269 | .pills a{margin:5px 3px 5px 0;padding:0 15px;line-height:30px;text-shadow:0 1px 1px #ffffff;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}.pills a:hover{color:#ffffff;text-decoration:none;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#00438a;} 270 | .pills .active a{color:#ffffff;text-shadow:0 1px 1px rgba(0, 0, 0, 0.25);background-color:#0069d6;} 271 | .pills-vertical>li{float:none;} 272 | .tab-content>.tab-pane,.pill-content>.pill-pane{display:none;} 273 | .tab-content>.active,.pill-content>.active{display:block;} 274 | .breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#f5f5f5;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;} 275 | .breadcrumb .divider{padding:0 5px;color:#bfbfbf;} 276 | .breadcrumb .active a{color:#404040;} 277 | .hero-unit{background-color:#f5f5f5;margin-bottom:30px;padding:60px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;} 278 | .hero-unit p{font-size:18px;font-weight:200;line-height:27px;} 279 | footer{margin-top:17px;padding-top:17px;border-top:1px solid #eee;} 280 | .page-header{margin-bottom:17px;border-bottom:1px solid #ddd;-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);box-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}.page-header h1{margin-bottom:8px;} 281 | .btn.danger,.alert-message.danger,.btn.danger:hover,.alert-message.danger:hover,.btn.error,.alert-message.error,.btn.error:hover,.alert-message.error:hover,.btn.success,.alert-message.success,.btn.success:hover,.alert-message.success:hover,.btn.info,.alert-message.info,.btn.info:hover,.alert-message.info:hover{color:#ffffff;} 282 | .btn .close,.alert-message .close{font-family:Arial,sans-serif;line-height:18px;} 283 | .btn.danger,.alert-message.danger,.btn.error,.alert-message.error{background-color:#c43c35;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#c43c35 #c43c35 #882a25;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);} 284 | .btn.success,.alert-message.success{background-color:#57a957;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#57a957 #57a957 #3d773d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);} 285 | .btn.info,.alert-message.info{background-color:#339bb9;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#339bb9 #339bb9 #22697d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);} 286 | .btn{cursor:pointer;display:inline-block;background-color:#e6e6e6;background-repeat:no-repeat;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);padding:5px 14px 6px;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);color:#333;font-size:13px;line-height:normal;border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-webkit-transform-style:preserve-3d;-webkit-transition:0.1s linear all;-moz-transition:0.1s linear all;-ms-transition:0.1s linear all;-o-transition:0.1s linear all;transition:0.1s linear all;}.btn:hover{background-position:0 -15px;color:#333;text-decoration:none;} 287 | .btn:focus{outline:1px dotted #666;} 288 | .btn.primary{color:#ffffff;background-color:#0064cd;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));background-image:-moz-linear-gradient(top, #049cdb, #0064cd);background-image:-ms-linear-gradient(top, #049cdb, #0064cd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));background-image:-webkit-linear-gradient(top, #049cdb, #0064cd);background-image:-o-linear-gradient(top, #049cdb, #0064cd);background-image:linear-gradient(top, #049cdb, #0064cd);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#0064cd #0064cd #003f81;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);} 289 | .btn.active,.btn :active{-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.25),0 1px 2px rgba(0, 0, 0, 0.05);} 290 | .btn.disabled{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 291 | .btn[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-khtml-opacity:0.65;-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} 292 | .btn.large{font-size:15px;line-height:normal;padding:9px 14px 9px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;} 293 | .btn.small{padding:7px 9px 7px;font-size:11px;} 294 | :root .alert-message,:root .btn{border-radius:0 \0;} 295 | button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0;} 296 | .close{float:right;color:#000000;font-size:20px;font-weight:bold;line-height:13.5px;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;}.close:hover{color:#000000;text-decoration:none;filter:alpha(opacity=40);-khtml-opacity:0.4;-moz-opacity:0.4;opacity:0.4;} 297 | .alert-message{position:relative;padding:7px 15px;margin-bottom:18px;color:#404040;background-color:#eedc94;background-repeat:repeat-x;background-image:-khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));background-image:-moz-linear-gradient(top, #fceec1, #eedc94);background-image:-ms-linear-gradient(top, #fceec1, #eedc94);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));background-image:-webkit-linear-gradient(top, #fceec1, #eedc94);background-image:-o-linear-gradient(top, #fceec1, #eedc94);background-image:linear-gradient(top, #fceec1, #eedc94);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);border-color:#eedc94 #eedc94 #e4c652;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);border-width:1px;border-style:solid;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.25);}.alert-message .close{margin-top:1px;*margin-top:0;} 298 | .alert-message a{font-weight:bold;color:#404040;} 299 | .alert-message.danger p a,.alert-message.error p a,.alert-message.success p a,.alert-message.info p a{color:#ffffff;} 300 | .alert-message h5{line-height:18px;} 301 | .alert-message p{margin-bottom:0;} 302 | .alert-message div{margin-top:5px;margin-bottom:2px;line-height:28px;} 303 | .alert-message .btn{-webkit-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);-moz-box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);box-shadow:0 1px 0 rgba(255, 255, 255, 0.25);} 304 | .alert-message.block-message{background-image:none;background-color:#fdf5d9;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);padding:14px;border-color:#fceec1;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.alert-message.block-message ul,.alert-message.block-message p{margin-right:30px;} 305 | .alert-message.block-message ul{margin-bottom:0;} 306 | .alert-message.block-message li{color:#404040;} 307 | .alert-message.block-message .alert-actions{margin-top:5px;} 308 | .alert-message.block-message.error,.alert-message.block-message.success,.alert-message.block-message.info{color:#404040;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);} 309 | .alert-message.block-message.error{background-color:#fddfde;border-color:#fbc7c6;} 310 | .alert-message.block-message.success{background-color:#d1eed1;border-color:#bfe7bf;} 311 | .alert-message.block-message.info{background-color:#ddf4fb;border-color:#c6edf9;} 312 | .alert-message.block-message.danger p a,.alert-message.block-message.error p a,.alert-message.block-message.success p a,.alert-message.block-message.info p a{color:#404040;} 313 | .pagination{height:36px;margin:18px 0;}.pagination ul{float:left;margin:0;border:1px solid #ddd;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);} 314 | .pagination li{display:inline;} 315 | .pagination a{float:left;padding:0 14px;line-height:34px;border-right:1px solid;border-right-color:#ddd;border-right-color:rgba(0, 0, 0, 0.15);*border-right-color:#ddd;text-decoration:none;} 316 | .pagination a:hover,.pagination .active a{background-color:#c7eefe;} 317 | .pagination .disabled a,.pagination .disabled a:hover{background-color:transparent;color:#bfbfbf;} 318 | .pagination .next a{border:0;} 319 | .well{background-color:#f5f5f5;margin-bottom:20px;padding:19px;min-height:20px;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);} 320 | .modal-backdrop{background-color:#000000;position:fixed;top:0;left:0;right:0;bottom:0;z-index:10000;}.modal-backdrop.fade{opacity:0;} 321 | .modal-backdrop,.modal-backdrop.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;} 322 | .modal{position:fixed;top:50%;left:50%;z-index:11000;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal .close{margin-top:7px;} 323 | .modal.fade{-webkit-transform-style:preserve-3d;-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;} 324 | .modal.fade.in{top:50%;} 325 | .modal-header{border-bottom:1px solid #eee;padding:5px 15px;} 326 | .modal-body{padding:15px;} 327 | .modal-body form{margin-bottom:0;} 328 | .modal-footer{background-color:#f5f5f5;padding:14px 15px 15px;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;zoom:1;margin-bottom:0;}.modal-footer:before,.modal-footer:after{display:table;content:"";zoom:1;} 329 | .modal-footer:after{clear:both;} 330 | .modal-footer .btn{float:right;margin-left:5px;} 331 | .modal .popover,.modal .twipsy{z-index:12000;} 332 | .twipsy{display:block;position:absolute;visibility:visible;padding:5px;font-size:11px;z-index:1000;filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;}.twipsy.fade.in{filter:alpha(opacity=80);-khtml-opacity:0.8;-moz-opacity:0.8;opacity:0.8;} 333 | .twipsy.above .twipsy-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} 334 | .twipsy.left .twipsy-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} 335 | .twipsy.below .twipsy-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} 336 | .twipsy.right .twipsy-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} 337 | .twipsy-inner{padding:3px 8px;background-color:#000000;color:white;text-align:center;max-width:200px;text-decoration:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} 338 | .twipsy-arrow{position:absolute;width:0;height:0;} 339 | .popover{position:absolute;top:0;left:0;z-index:1000;padding:5px;display:none;}.popover.above .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} 340 | .popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} 341 | .popover.below .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} 342 | .popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} 343 | .popover .arrow{position:absolute;width:0;height:0;} 344 | .popover .inner{background:#000000;background:rgba(0, 0, 0, 0.8);padding:3px;overflow:hidden;width:280px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);} 345 | .popover .title{background-color:#f5f5f5;padding:9px 15px;line-height:1;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;border-bottom:1px solid #eee;} 346 | .popover .content{background-color:#ffffff;padding:14px;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover .content p,.popover .content ul,.popover .content ol{margin-bottom:0;} 347 | .fade{-webkit-transform-style:preserve-3d;-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;} 348 | .label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;white-space:nowrap;background-color:#bfbfbf;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}.label.important{background-color:#c43c35;} 349 | .label.warning{background-color:#f89406;} 350 | .label.success{background-color:#46a546;} 351 | .label.notice{background-color:#62cffc;} 352 | .media-grid{margin-left:-20px;margin-bottom:0;zoom:1;}.media-grid:before,.media-grid:after{display:table;content:"";zoom:1;} 353 | .media-grid:after{clear:both;} 354 | .media-grid li{display:inline;} 355 | .media-grid a{float:left;padding:4px;margin:0 0 18px 20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}.media-grid a img{display:block;} 356 | .media-grid a:hover{border-color:#0069d6;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} 357 | -------------------------------------------------------------------------------- /test/css/qunit-1.16.0.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.16.0 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright 2006, 2014 jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2014-12-03T16:32Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 1em 0.5em 1em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 1em 0.5em 1em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | } 81 | 82 | /** Tests: Pass/Fail */ 83 | 84 | #qunit-tests { 85 | list-style-position: inside; 86 | } 87 | 88 | #qunit-tests li { 89 | padding: 0.4em 1em 0.4em 1em; 90 | border-bottom: 1px solid #FFF; 91 | list-style-position: inside; 92 | } 93 | 94 | #qunit-tests > li { 95 | display: none; 96 | } 97 | 98 | #qunit-tests li.pass, #qunit-tests li.running, #qunit-tests li.fail { 99 | display: list-item; 100 | } 101 | 102 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 103 | display: none; 104 | } 105 | 106 | #qunit-tests li strong { 107 | cursor: pointer; 108 | } 109 | 110 | #qunit-tests li.skipped strong { 111 | cursor: default; 112 | } 113 | 114 | #qunit-tests li a { 115 | padding: 0.5em; 116 | color: #C2CCD1; 117 | text-decoration: none; 118 | } 119 | #qunit-tests li a:hover, 120 | #qunit-tests li a:focus { 121 | color: #000; 122 | } 123 | 124 | #qunit-tests li .runtime { 125 | float: right; 126 | font-size: smaller; 127 | } 128 | 129 | .qunit-assert-list { 130 | margin-top: 0.5em; 131 | padding: 0.5em; 132 | 133 | background-color: #FFF; 134 | 135 | border-radius: 5px; 136 | } 137 | 138 | .qunit-collapsed { 139 | display: none; 140 | } 141 | 142 | #qunit-tests table { 143 | border-collapse: collapse; 144 | margin-top: 0.2em; 145 | } 146 | 147 | #qunit-tests th { 148 | text-align: right; 149 | vertical-align: top; 150 | padding: 0 0.5em 0 0; 151 | } 152 | 153 | #qunit-tests td { 154 | vertical-align: top; 155 | } 156 | 157 | #qunit-tests pre { 158 | margin: 0; 159 | white-space: pre-wrap; 160 | word-wrap: break-word; 161 | } 162 | 163 | #qunit-tests del { 164 | background-color: #E0F2BE; 165 | color: #374E0C; 166 | text-decoration: none; 167 | } 168 | 169 | #qunit-tests ins { 170 | background-color: #FFCACA; 171 | color: #500; 172 | text-decoration: none; 173 | } 174 | 175 | /*** Test Counts */ 176 | 177 | #qunit-tests b.counts { color: #000; } 178 | #qunit-tests b.passed { color: #5E740B; } 179 | #qunit-tests b.failed { color: #710909; } 180 | 181 | #qunit-tests li li { 182 | padding: 5px; 183 | background-color: #FFF; 184 | border-bottom: none; 185 | list-style-position: inside; 186 | } 187 | 188 | /*** Passing Styles */ 189 | 190 | #qunit-tests li li.pass { 191 | color: #3C510C; 192 | background-color: #FFF; 193 | border-left: 10px solid #C6E746; 194 | } 195 | 196 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 197 | #qunit-tests .pass .test-name { color: #366097; } 198 | 199 | #qunit-tests .pass .test-actual, 200 | #qunit-tests .pass .test-expected { color: #999; } 201 | 202 | #qunit-banner.qunit-pass { background-color: #C6E746; } 203 | 204 | /*** Failing Styles */ 205 | 206 | #qunit-tests li li.fail { 207 | color: #710909; 208 | background-color: #FFF; 209 | border-left: 10px solid #EE5757; 210 | white-space: pre; 211 | } 212 | 213 | #qunit-tests > li:last-child { 214 | border-radius: 0 0 5px 5px; 215 | } 216 | 217 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 218 | #qunit-tests .fail .test-name, 219 | #qunit-tests .fail .module-name { color: #000; } 220 | 221 | #qunit-tests .fail .test-actual { color: #EE5757; } 222 | #qunit-tests .fail .test-expected { color: #008000; } 223 | 224 | #qunit-banner.qunit-fail { background-color: #EE5757; } 225 | 226 | /*** Skipped tests */ 227 | 228 | #qunit-tests .skipped { 229 | background-color: #EBECE9; 230 | } 231 | 232 | #qunit-tests .qunit-skipped-label { 233 | background-color: #F4FF77; 234 | display: inline-block; 235 | font-style: normal; 236 | color: #366097; 237 | line-height: 1.8em; 238 | padding: 0 0.5em; 239 | margin: -0.4em 0.4em -0.4em 0; 240 | } 241 | 242 | /** Result */ 243 | 244 | #qunit-testresult { 245 | padding: 0.5em 1em 0.5em 1em; 246 | 247 | color: #2B81AF; 248 | background-color: #D2E0E6; 249 | 250 | border-bottom: 1px solid #FFF; 251 | } 252 | #qunit-testresult .module-name { 253 | font-weight: 700; 254 | } 255 | 256 | /** Fixture */ 257 | 258 | #qunit-fixture { 259 | position: absolute; 260 | top: -10000px; 261 | left: -10000px; 262 | width: 1000px; 263 | height: 1000px; 264 | } 265 | -------------------------------------------------------------------------------- /test/file_reader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SparkMD5 file reader test 5 | 6 | 7 | 8 | 9 | 22 | 23 | 24 |

SparkMD5 file reader test, incremental and normal md5

25 | 26 |

Please note that the advantage of doing an incremental md5 is to keep memory usage low.

27 |

28 | Keep an eye on the memory usage of your browser. If you got chrome, open about:memory to see all the browsers memory usage (you must refresh continuously). 29 |
With normal md5, you should observe slightly faster times but high memory usage (because the entire file need to be read into an array). 30 |
With incremental md5, you should observe stable memory usage but slightly higher times. 31 |
Be aware that while using normal md5, the browser can crash due to high memory usage. 32 |

33 | 34 |
35 | 36 | 37 | 38 | 39 |
40 |
41 | 42 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /test/file_reader_binary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SparkMD5 file reader test 5 | 6 | 7 | 8 | 9 | 22 | 23 | 24 |

SparkMD5 file reader test, incremental and normal md5

25 | 26 |

Please note that the advantage of doing an incremental md5 is to keep memory usage low.

27 |

28 | Keep an eye on the memory usage of your browser. If you got chrome, open about:memory to see all the browsers memory usage (you must refresh continuously). 29 |
With normal md5, you should observe slightly faster times but high memory usage (because the entire file need to be read into an array). 30 |
With incremental md5, you should observe stable memory usage but slightly higher times. 31 |
Be aware that while using normal md5, the browser can crash due to high memory usage. 32 |

33 | 34 |
35 | 36 | 37 | 38 | 39 |
40 |
41 | 42 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SparkMD5 tests 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

SparkMD5 test

13 |

14 |
15 |

16 |
    17 |
    18 |
    19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/index.min.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SparkMD5 tests (minified version) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

    SparkMD5 test

    13 |

    14 |
    15 |

    16 |
      17 |
      18 |
      19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/readme_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SparkMD5 readme example 5 | 6 | 7 | 8 | 9 | 10 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /test/specs.js: -------------------------------------------------------------------------------- 1 | /*global test, equal*/ 2 | 3 | var hasher = new SparkMD5(), 4 | buffHasher = new SparkMD5.ArrayBuffer(); 5 | 6 | function unicodeStringToArrayBuffer(str) { 7 | if (/[\u0080-\uFFFF]/.test(str)) { 8 | str = unescape(encodeURIComponent(str)); 9 | } 10 | 11 | return stringToArrayBuffer(str); 12 | } 13 | 14 | function stringToArrayBuffer(str) { 15 | var length = str.length, 16 | buff = new ArrayBuffer(length), 17 | arr = new Uint8Array(buff), 18 | i; 19 | 20 | for (i = 0; i < length; i += 1) { 21 | arr[i] = str.charCodeAt(i); 22 | } 23 | 24 | return buff; 25 | } 26 | 27 | function binaryStringToHex(str) { 28 | var hex = '', 29 | ch, 30 | i, 31 | length = str.length; 32 | 33 | for (i = 0; i < length; i += 1) { 34 | ch = str.charCodeAt(i); 35 | hex += (ch >> 4).toString(16); 36 | hex += (ch & 0xF).toString(16); 37 | } 38 | 39 | return hex; 40 | } 41 | 42 | test('Hash of "hello"', function () { 43 | var str = 'hello', 44 | hash = '5d41402abc4b2a76b9719d911017c592'; 45 | 46 | equal(SparkMD5.hash(str), hash, 'SparkMD5.hash()'); 47 | equal(SparkMD5.hashBinary(str), hash, 'SparkMD5.hashBinary()'); 48 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), hash, 'SparkMD5.ArrayBuffer.hash()'); 49 | 50 | hasher.reset(); 51 | hasher.append(str); 52 | equal(hasher.end(), hash, 'Incremental (normal)'); 53 | hasher.appendBinary(str); 54 | equal(hasher.end(), hash, 'Incremental (binary)'); 55 | buffHasher.reset(); 56 | buffHasher.append(unicodeStringToArrayBuffer(str)); 57 | equal(buffHasher.end(), hash, 'Incremental (array buffer)'); 58 | }); 59 | 60 | test('Hash of "hello" (raw)', function () { 61 | var str = 'hello', 62 | hash = '5d41402abc4b2a76b9719d911017c592'; 63 | 64 | equal(binaryStringToHex(SparkMD5.hash(str, true)), hash, 'SparkMD5.hash()'); 65 | equal(binaryStringToHex(SparkMD5.hashBinary(str, true)), hash, 'SparkMD5.hashBinary()'); 66 | equal(binaryStringToHex(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str), true)), hash, 'SparkMD5.ArrayBuffer.hash()'); 67 | 68 | hasher.reset(); 69 | hasher.append(str); 70 | equal(binaryStringToHex(hasher.end(true)), hash, 'Incremental (normal)'); 71 | hasher.appendBinary(str); 72 | equal(binaryStringToHex(hasher.end(true)), hash, 'Incremental (binary)'); 73 | buffHasher.reset(); 74 | buffHasher.append(unicodeStringToArrayBuffer(str)); 75 | equal(binaryStringToHex(buffHasher.end(true)), hash, 'Incremental (array buffer)'); 76 | }); 77 | 78 | test('Hash of 64 bytes', function () { 79 | var str = '5d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c592', 80 | hash = 'e0b153045b08d59d4e18a98ab823ac42'; 81 | 82 | equal(SparkMD5.hash(str), hash, 'SparkMD5.hash()'); 83 | equal(SparkMD5.hashBinary(str), hash, 'SparkMD5.hashBinary()'); 84 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), hash, 'SparkMD5.ArrayBuffer.hash()'); 85 | 86 | hasher.reset(); 87 | hasher.append(str); 88 | equal(hasher.end(), hash, 'Incremental (normal)'); 89 | hasher.appendBinary(str); 90 | equal(hasher.end(), hash, 'Incremental (binary)'); 91 | buffHasher.reset(); 92 | buffHasher.append(unicodeStringToArrayBuffer(str)); 93 | equal(buffHasher.end(), hash, 'Incremental (array buffer)'); 94 | }); 95 | 96 | test('Hash of 128 bytes', function () { 97 | var str = '5d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c592', 98 | hash = 'b12bc24f5507eba4ee27092f70148415'; 99 | 100 | equal(SparkMD5.hash(str), hash, 'SparkMD5.hash()'); 101 | equal(SparkMD5.hashBinary(str), hash, 'SparkMD5.hashBinary()'); 102 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), hash, 'SparkMD5.ArrayBuffer.hash()'); 103 | 104 | hasher.reset(); 105 | hasher.append(str); 106 | equal(hasher.end(), hash, 'Incremental (normal)'); 107 | hasher.appendBinary(str); 108 | equal(hasher.end(), hash, 'Incremental (binary)'); 109 | buffHasher.reset(); 110 | buffHasher.append(unicodeStringToArrayBuffer(str)); 111 | equal(buffHasher.end(), hash, 'Incremental (array buffer)'); 112 | }); 113 | 114 | test('Hash of 160 bytes', function () { 115 | var str = '5d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a765d41402abc4b2a76b9719d911017c5925d41402abc4b2a76b9719d911017c5925d41402abc4b2a76', 116 | hash = '66a1e6b119bf30ade63378f770e52549'; 117 | 118 | equal(SparkMD5.hash(str), hash, 'SparkMD5.hash()'); 119 | equal(SparkMD5.hashBinary(str), hash, 'SparkMD5.hashBinary()'); 120 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), hash, 'SparkMD5.ArrayBuffer.hash()'); 121 | 122 | hasher.reset(); 123 | hasher.append(str); 124 | equal(hasher.end(), hash, 'Incremental (normal)'); 125 | hasher.appendBinary(str); 126 | equal(hasher.end(), hash, 'Incremental (binary)'); 127 | buffHasher.reset(); 128 | buffHasher.append(unicodeStringToArrayBuffer(str)); 129 | equal(buffHasher.end(), hash, 'Incremental (array buffer)'); 130 | }); 131 | 132 | test('Incremental usage', function () { 133 | hasher.reset(); 134 | hasher.append('5d41402abc4b2a421456'); 135 | hasher.append('5d41402abc4b2a421456'); 136 | hasher.append('5d41402abc4b2a421456a234'); 137 | 138 | equal(hasher.end(), '014d4bbb02c66c98249114dc674a7187', 'Incremental (normal) of 20+20+24'); 139 | 140 | hasher.reset(); 141 | hasher.appendBinary('5d41402abc4b2a421456'); 142 | hasher.appendBinary('5d41402abc4b2a421456'); 143 | hasher.appendBinary('5d41402abc4b2a421456a234'); 144 | 145 | equal(hasher.end(), '014d4bbb02c66c98249114dc674a7187', 'Incremental (binary) of 20+20+24'); 146 | 147 | buffHasher.reset(); 148 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 149 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 150 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 151 | 152 | equal(buffHasher.end(), '014d4bbb02c66c98249114dc674a7187', 'Incremental (array buffer) of 20+20+24'); 153 | 154 | hasher.reset(); 155 | hasher.append('5d41402abc4b2a421456'); 156 | hasher.append('5d41402abc4b2a421456'); 157 | hasher.append('5d41402abc4b2a421456'); 158 | 159 | equal(hasher.end(), 'f15937a66ae98c76c0dfbc6df2b75703', 'Incremental (normal) of 20+20+20'); 160 | 161 | hasher.reset(); 162 | hasher.appendBinary('5d41402abc4b2a421456'); 163 | hasher.appendBinary('5d41402abc4b2a421456'); 164 | hasher.appendBinary('5d41402abc4b2a421456'); 165 | 166 | equal(hasher.end(), 'f15937a66ae98c76c0dfbc6df2b75703', 'Incremental (binary) of 20+20+20'); 167 | 168 | buffHasher.reset(); 169 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 170 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 171 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 172 | 173 | equal(buffHasher.end(), 'f15937a66ae98c76c0dfbc6df2b75703', 'Incremental (array buffer) of 20+20+20'); 174 | 175 | hasher.reset(); 176 | hasher.append('5d41402abc4b2a421456'); 177 | hasher.append('5d41402abc4b2a4214565d41402abc4b2a4214565d41402abc4b2a421456'); 178 | hasher.append('5d41402abc4b2a421456'); 179 | 180 | equal(hasher.end(), '45762198a57a35c8523915898fb8c68c', 'Incremental (normal) of 20+60+20'); 181 | 182 | hasher.reset(); 183 | hasher.appendBinary('5d41402abc4b2a421456'); 184 | hasher.appendBinary('5d41402abc4b2a4214565d41402abc4b2a4214565d41402abc4b2a421456'); 185 | hasher.appendBinary('5d41402abc4b2a421456'); 186 | 187 | equal(hasher.end(), '45762198a57a35c8523915898fb8c68c', 'Incremental (binary) of 20+60+20'); 188 | 189 | buffHasher.reset(); 190 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 191 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a4214565d41402abc4b2a4214565d41402abc4b2a421456')); 192 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 193 | 194 | equal(buffHasher.end(), '45762198a57a35c8523915898fb8c68c', 'Incremental (array buffer) of 20+60+20'); 195 | 196 | }); 197 | 198 | test('Incremental usage (resume)', function () { 199 | var md5, 200 | state; 201 | 202 | hasher.reset(); 203 | hasher.append('5d41402abc4b2a421456'); 204 | hasher.append('5d41402abc4b2a421456'); 205 | hasher.append('5d41402abc4b2a421456'); 206 | hasher.append('5d41402abc4b2a421456'); 207 | hasher.append('5d41402abc4b2a421456a234'); 208 | md5 = hasher.end(); 209 | 210 | hasher.reset(); 211 | hasher.append('5d41402abc4b2a421456'); 212 | state = hasher.getState(); 213 | hasher.reset(); 214 | hasher.setState(state); 215 | hasher.append('5d41402abc4b2a421456'); 216 | hasher.append('5d41402abc4b2a421456'); 217 | hasher.append('5d41402abc4b2a421456'); 218 | hasher.append('5d41402abc4b2a421456a234'); 219 | 220 | equal(hasher.end(), md5, 'MD5 should be the same'); 221 | equal(md5, 'c9db0e4d21ebbba7014bd62353b2135e', 'Actual MD5 check'); 222 | 223 | // Same tests but for buffers 224 | buffHasher.reset(); 225 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 226 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 227 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 228 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 229 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 230 | md5 = buffHasher.end(); 231 | 232 | buffHasher.reset(); 233 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 234 | state = buffHasher.getState(); 235 | 236 | buffHasher.reset(); 237 | buffHasher.setState(state); 238 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 239 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 240 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 241 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 242 | 243 | equal(buffHasher.end(), md5, 'MD5 should be the same'); 244 | equal(md5, 'c9db0e4d21ebbba7014bd62353b2135e', 'Actual MD5 check'); 245 | }); 246 | 247 | test('Incremental usage (rolling)', function () { 248 | var md5, 249 | state; 250 | 251 | hasher.reset(); 252 | hasher.append('5d41402abc4b2a421456'); 253 | hasher.append('5d41402abc4b2a421456'); 254 | hasher.append('5d41402abc4b2a421456'); 255 | hasher.append('5d41402abc4b2a421456'); 256 | hasher.append('5d41402abc4b2a421456a234'); 257 | md5 = hasher.end(); 258 | 259 | hasher.reset(); 260 | hasher.append('5d41402abc4b2a421456'); 261 | state = hasher.getState(); 262 | hasher.end(); 263 | hasher.setState(state); 264 | hasher.append('5d41402abc4b2a421456'); 265 | hasher.append('5d41402abc4b2a421456'); 266 | hasher.append('5d41402abc4b2a421456'); 267 | hasher.append('5d41402abc4b2a421456a234'); 268 | 269 | equal(hasher.end(), md5, 'MD5 should be the same'); 270 | equal(md5, 'c9db0e4d21ebbba7014bd62353b2135e', 'Actual MD5 check'); 271 | 272 | // Same tests but for buffers 273 | buffHasher.reset(); 274 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 275 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 276 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 277 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 278 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 279 | md5 = buffHasher.end(); 280 | 281 | buffHasher.reset(); 282 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 283 | state = buffHasher.getState(); 284 | 285 | buffHasher.end(); 286 | buffHasher.setState(state); 287 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 288 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 289 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 290 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 291 | 292 | equal(buffHasher.end(), md5, 'MD5 should be the same'); 293 | equal(md5, 'c9db0e4d21ebbba7014bd62353b2135e', 'Actual MD5 check'); 294 | }); 295 | 296 | test('Incremental usage (resume with JSON.stringify)', function () { 297 | var md5, 298 | state; 299 | 300 | // Same tests but for buffers 301 | buffHasher.reset(); 302 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 303 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 304 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 305 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 306 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 307 | md5 = buffHasher.end(); 308 | 309 | buffHasher.reset(); 310 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 311 | state = JSON.stringify(buffHasher.getState()); 312 | 313 | buffHasher.reset(); 314 | buffHasher.setState(JSON.parse(state)); 315 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 316 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 317 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456')); 318 | buffHasher.append(unicodeStringToArrayBuffer('5d41402abc4b2a421456a234')); 319 | 320 | equal(buffHasher.end(), md5, 'MD5 should be the same'); 321 | equal(md5, 'c9db0e4d21ebbba7014bd62353b2135e', 'Actual MD5 check'); 322 | }); 323 | 324 | test('UTF-8', function () { 325 | var str = 'räksmörgås'; 326 | 327 | equal(SparkMD5.hash(str), 'e462805dcf84413d5eddca45a4b88a5e', 'SparkMD5.hash() of "' + str + '"'); 328 | equal(SparkMD5.hashBinary(str), '09d9d71ec8a8e3bc74e51ebd587154f3', 'SparkMD5.hashBinary() of "' + str + '"'); 329 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), 'e462805dcf84413d5eddca45a4b88a5e', 'SparkMD5.ArrayBuffer.hash() of "' + str + '"'); 330 | 331 | hasher.reset(); 332 | hasher.append(str); 333 | equal(hasher.end(), 'e462805dcf84413d5eddca45a4b88a5e', 'Incremental (normal) of "' + str + '"'); 334 | 335 | hasher.reset(); 336 | hasher.appendBinary(str); 337 | equal(hasher.end(), '09d9d71ec8a8e3bc74e51ebd587154f3', 'Incremental (binary) of "' + str + '"'); 338 | 339 | buffHasher.reset(); 340 | buffHasher.append(unicodeStringToArrayBuffer(str)); 341 | equal(buffHasher.end(), 'e462805dcf84413d5eddca45a4b88a5e', 'Incremental (array buffer) of "' + str + '"'); 342 | 343 | str = '\u30b9\u3092\u98df'; 344 | 345 | equal(SparkMD5.hash(str), '453931ab48a4a5af69f3da3c21064fc9', 'SparkMD5.hash() of "' + str + '"'); 346 | equal(SparkMD5.hashBinary(str), '24e3399be06b7cf59dbd848e18d9246c', 'SparkMD5.hashBinary() of "' + str + '"'); 347 | equal(SparkMD5.ArrayBuffer.hash(unicodeStringToArrayBuffer(str)), '453931ab48a4a5af69f3da3c21064fc9', 'SparkMD5.ArrayBuffer.hash() of "' + str + '"'); 348 | 349 | hasher.reset(); 350 | hasher.append(str); 351 | equal(hasher.end(), '453931ab48a4a5af69f3da3c21064fc9', 'Incremental (normal) of "' + str + '"'); 352 | 353 | hasher.reset(); 354 | hasher.appendBinary(str); 355 | equal(hasher.end(), '24e3399be06b7cf59dbd848e18d9246c', 'Incremental (binary) of "' + str + '"'); 356 | 357 | buffHasher.reset(); 358 | buffHasher.append(unicodeStringToArrayBuffer(str)); 359 | equal(buffHasher.end(), '453931ab48a4a5af69f3da3c21064fc9', 'Incremental (array buffer) of "' + str + '"'); 360 | }); 361 | 362 | test('Hashing a PNG - ArrayBuffer vs binary string', function () { 363 | var binString, 364 | buffer; 365 | 366 | // 1x1 transparent PNG 367 | binString = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII='); 368 | buffer = stringToArrayBuffer(binString); 369 | 370 | buffHasher.reset(); 371 | buffHasher.append(buffer); 372 | 373 | hasher.reset(); 374 | hasher.appendBinary(binString); 375 | 376 | equal(buffHasher.end(), hasher.end(), 'md5 sum should be the same for both binary strings and ArrayBuffers'); 377 | }); 378 | --------------------------------------------------------------------------------