├── images ├── passwdmaker128.png ├── passwdmaker16.png └── passwdmaker48.png ├── html ├── background.html ├── popup.html └── options.html ├── javascript ├── content.js ├── securehash.js ├── passwordmaker │ ├── sha1.js │ ├── l33t.js │ ├── sha256.js │ ├── md4.js │ ├── hashutils.js │ ├── ripemd160.js │ ├── md5.js │ ├── md5_v6.js │ └── aes.js ├── import.js ├── popup.js ├── profile.js ├── options.js ├── settings.js ├── jquery-ui.min.js └── json2.js ├── manifest.json ├── README.markdown ├── css ├── popup.css ├── options.css └── awesome-buttons.css ├── test ├── import.js ├── index.html └── qunit.css └── LICENSE /images/passwdmaker128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamghill/chrome-passwordmaker/master/images/passwdmaker128.png -------------------------------------------------------------------------------- /images/passwdmaker16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamghill/chrome-passwordmaker/master/images/passwdmaker16.png -------------------------------------------------------------------------------- /images/passwdmaker48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamghill/chrome-passwordmaker/master/images/passwdmaker48.png -------------------------------------------------------------------------------- /html/background.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /javascript/content.js: -------------------------------------------------------------------------------- 1 | chrome.extension.onRequest.addListener(function(request, sender, sendResponse) { 2 | if (request.password) { 3 | fillPasswords(request.password); 4 | } else if (request.hasPasswordField) { 5 | sendResponse({hasField: hasPasswordField()}); 6 | } 7 | }); 8 | 9 | function fillPasswords(password) { 10 | jQuery("input[type=password]").val(password); 11 | } 12 | 13 | function hasPasswordField() { 14 | fields = jQuery("input[type=password]"); 15 | 16 | hasFields = false; 17 | 18 | if (fields && fields.length > 0) { 19 | hasFields = true; 20 | } 21 | 22 | return hasFields; 23 | } -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PasswordMaker Pro", 3 | "version": "0.1.12", 4 | "description": "A chrome extension based on passwordmaker.org . Create unique passwords for every webpage using a hashing algorythm.", 5 | "icons": { 6 | "16": "images/passwdmaker16.png", 7 | "48": "images/passwdmaker48.png", 8 | "128":"images/passwdmaker128.png" 9 | }, 10 | "browser_action": { 11 | "default_icon": "images/passwdmaker48.png", 12 | "popup": "html/popup.html" 13 | }, 14 | "permissions": [ 15 | "tabs" 16 | ], 17 | "content_scripts": [ { 18 | "js": [ "javascript/jquery.min.js", "javascript/content.js" ], 19 | "matches": [ "http://*/*", "https://*/*" ] 20 | } ], 21 | "background_page": "html/background.html", 22 | "options_page": "html/options.html" 23 | } 24 | -------------------------------------------------------------------------------- /javascript/securehash.js: -------------------------------------------------------------------------------- 1 | if (typeof(ChromePasswordMaker_SecureHash) != "object") { 2 | var ChromePasswordMaker_SecureHash = { 3 | seed: 'q#-f21@xNh9sJaKv6TLv8ipR%YgT&RnwMP4Zz2pMya&C44B137+wRkk7C08BF*b1', 4 | sha256_charset: 'FByDU98TAfzvkuaxgUH3HuMJ1jspdFu9', 5 | sha1_charset: '0cOJL6EsNlHFMWkbyPCU0EoBOZ80Ck2j', 6 | md5_charset: 'BPVB1oCrr2BJzhH6qM43kq9lLUqMQWxj', 7 | md4_charset: 'szPBOPb2WZwWCOYylDNb0kda4HPdp9I7', 8 | 9 | make_hash: function (text) { 10 | var hash = PasswordMaker_SHA256.any_sha256(text, Settings.masterPasswordCharSet); 11 | return this._hash(hash); 12 | }, 13 | 14 | update_old_hash: function (oldhash) { 15 | return this._hash(oldhash); 16 | }, 17 | 18 | _hash: function (hash) { 19 | for(var i = 0; i < 16; i++) { 20 | hash = PasswordMaker_SHA256.any_sha256(hash + this.seed, this.sha256_charset); 21 | hash = PasswordMaker_SHA1.any_sha1(hash + this.seed, this.sha1_charset); 22 | hash = PasswordMaker_MD5.any_md5(hash + this.seed, this.md5_charset); 23 | hash = PasswordMaker_MD4.any_md4(hash + this.seed, this.md4_charset); 24 | } 25 | hash = 'n' + hash.substring(1); 26 | return hash; 27 | } 28 | }; 29 | } -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Chrome PasswordMaker Pro 2 | 3 | ![Dummy Screenshot](http://img405.imageshack.us/img405/6676/bildschirmfoto20100418u.png) 4 | 5 | The only thing that kept me from switching to chrome completly was a missing port of the passwordmaker.org 6 | extension. Luckily there was one available in the extension directory. 7 | Sadly that extension is only a simple port of the html page that is offered on passwordmaker.org. 8 | 9 | This extension fixes this. It's a real port with all the bells and whistles you expect. 10 | 11 | # Installation 12 | 13 | You can install this plugin from the chrome extensions library. 14 | 15 | # Note on Patches/Pull Requests 16 | 17 | * Fork the project. 18 | * Make your feature addition or bug fix. 19 | * Commit, do not mess with version in manifest.json 20 | (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) 21 | * Send me a pull request. Bonus points for topic branches. 22 | 23 | # Copyright 24 | 25 | Copyright (c) 2010 Bodo Tasche, PasswordMaker.org . See LICENSE for details. A list of all contributers can be found here. -------------------------------------------------------------------------------- /css/popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 200px; 3 | height: 10px; 4 | font-family: sans-serif; 5 | font-size: 13px; 6 | } 7 | 8 | form { 9 | display:none; 10 | } 11 | 12 | label { 13 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 14 | font-size: 12px; 15 | font-weight: bold; 16 | color: #888888; 17 | } 18 | 19 | #head { 20 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 21 | border-bottom: 1px solid #eeeeee; 22 | margin-bottom: 5px; 23 | padding-bottom: 5px; 24 | vertical-align: middle; 25 | font-weight: bold; 26 | } 27 | 28 | #head img { 29 | position: absolute; 30 | top: 8px; 31 | } 32 | 33 | #head span { 34 | margin-left: 20px; 35 | } 36 | 37 | .input { 38 | margin: 0px; 39 | width: 200px; 40 | border: 1px solid #000000; 41 | } 42 | 43 | #generated{ 44 | color: #5E80F0; 45 | font-weight: bold; 46 | text-align: center; 47 | width: 200px; 48 | border: 1px solid #000000; 49 | font-size:15px; 50 | } 51 | 52 | #generated{ 53 | color: #5E80F0; 54 | font-style: italic; 55 | text-align: center; 56 | width: 200px; 57 | border: 1px solid #000000; 58 | font-size:15px; 59 | } 60 | 61 | select { 62 | margin: 0px; 63 | width: 200px; 64 | border: 1px solid #000000; 65 | } 66 | 67 | .row { 68 | margin-bottom: 5px; 69 | } 70 | 71 | #injectpasswordrow { 72 | float: left; 73 | } 74 | 75 | #options { 76 | float: right; 77 | } 78 | 79 | #button-row { 80 | margin-top: 5px; 81 | margin-bottom: 5px; 82 | } 83 | 84 | .largebutton { 85 | width: 180px; 86 | text-align: center; 87 | } 88 | 89 | #copypassword { 90 | float: left; 91 | } 92 | 93 | .hidden { 94 | margin-left: -500px; 95 | margin-top: -500px; 96 | } 97 | -------------------------------------------------------------------------------- /test/import.js: -------------------------------------------------------------------------------- 1 | module("rdf import"); 2 | 3 | var rdf_doc1 = RdfImporter.loadDoc($($('#rdf1').val())); 4 | 5 | test("parse global settings", function () { 6 | var s = rdf_doc1.settings; 7 | 8 | same(s.rdf_about, 'http://passwordmaker.mozdev.org/globalSettings'); 9 | same(s.hideMasterPassword, false); 10 | same(s.storeLocation, 'memory'); 11 | }); 12 | 13 | test("find profiles", function () { 14 | same(rdf_doc1.profiles.length, 2); 15 | }); 16 | 17 | test("load profile 1", function () { 18 | var p = rdf_doc1.profiles[0]; 19 | 20 | same(p.rdf_about, 'rdf:#$5PGpU1'); 21 | same(p.title,'nospecial'); 22 | same(p.url_protocol, false); 23 | same(p.url_subdomain, false); 24 | same(p.url_domain, true); 25 | same(p.url_path, true); 26 | same(p.hashAlgorithm, 'hmac-sha256_fix'); 27 | same(p.username, 'username1'); 28 | same(p.modifier, 'modifier1'); 29 | same(p.passwordLength, 20); 30 | same(p.selectedCharset, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); 31 | same(p.passwordPrefix, 'prefix1'); 32 | same(p.passwordSuffix, 'suffix1'); 33 | same(p.whereToUseL33t, 'before-hashing'); 34 | same(p.l33tLevel, 1); 35 | }); 36 | 37 | test("load profile 2", function () { 38 | var p = rdf_doc1.profiles[1]; 39 | 40 | same(p.rdf_about, 'http://passwordmaker.mozdev.org/defaults'); 41 | same(p.title,'Defaults'); 42 | same(p.url_protocol, false); 43 | same(p.url_subdomain, false); 44 | same(p.url_domain, true); 45 | same(p.url_path, true); 46 | same(p.hashAlgorithm, 'sha256'); 47 | same(p.username, 'username1'); 48 | same(p.modifier, 'modifier1'); 49 | same(p.passwordLength, 15); 50 | same(p.selectedCharset, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%'); 51 | same(p.passwordPrefix, 'prefix1'); 52 | same(p.passwordSuffix, 'suffix1'); 53 | same(p.whereToUseL33t, 'off'); 54 | same(p.l33tLevel, 1); 55 | }); 56 | 57 | test("save profiles", function () { 58 | var profiles = rdf_doc1.profiles; 59 | 60 | same(profiles.length, 2); 61 | same(Settings.getProfiles().length, 1); 62 | 63 | RdfImporter.saveProfiles(profiles); 64 | 65 | same(Settings.getProfiles().length, 3); 66 | }); 67 | 68 | test("save settings", function () { 69 | var settings = rdf_doc1.settings; 70 | 71 | Settings.setHidePassword(false); 72 | Settings.setStoreLocation('disk'); 73 | 74 | same(Settings.shouldHidePassword(), false); 75 | same(Settings.storeLocation, 'disk'); 76 | 77 | RdfImporter.saveSettings({hideMasterPassword: true, storeLocation: 'memory'}); 78 | 79 | same(Settings.shouldHidePassword(), true); 80 | same(Settings.storeLocation, 'memory'); 81 | }); 82 | -------------------------------------------------------------------------------- /html/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 27 |
28 |
29 |
30 | 35 |
36 |
37 | 39 |
40 |
41 |
42 | 43 | 44 | Show password 45 |
46 |
47 |
48 |
49 | 50 |
51 | 54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /javascript/passwordmaker/sha1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined 3 | * in FIPS PUB 180-1 4 | * Version 2.1 Copyright Paul Johnston 2000 - 2002. 5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 6 | * Distributed under the BSD License 7 | * See http://pajhome.org.uk/crypt/md5 for details. 8 | * 9 | * Modified by Eric H. Jung (grimholtz@yahoo.com) 10 | */ 11 | 12 | if (typeof(PasswordMaker_SHA1) != "object") { 13 | var PasswordMaker_SHA1 = { 14 | 15 | any_sha1 : function(s, e){ return PasswordMaker_HashUtils.rstr2any(this.rstr_sha1(PasswordMaker_HashUtils.str2rstr_utf8(s)), e); }, 16 | any_hmac_sha1 : function(k, d, e){ return PasswordMaker_HashUtils.rstr2any(this.rstr_hmac_sha1(PasswordMaker_HashUtils.str2rstr_utf8(k), PasswordMaker_HashUtils.str2rstr_utf8(d)), e); }, 17 | 18 | /* 19 | * Calculate the SHA1 of a raw string 20 | */ 21 | rstr_sha1 : function(s) { 22 | return PasswordMaker_HashUtils.binb2rstr(this.binb_sha1(PasswordMaker_HashUtils.rstr2binb(s), s.length * PasswordMaker_HashUtils.chrsz)); 23 | }, 24 | 25 | /* 26 | * Calculate the SHA-1 of an array of big-endian words and a bit length 27 | */ 28 | binb_sha1 : function(x, len) { 29 | /* append padding */ 30 | x[len >> 5] |= 0x80 << (24 - len % 32); 31 | x[((len + 64 >> 9) << 4) + 15] = len; 32 | 33 | var w = Array(80); 34 | var a = 1732584193; 35 | var b = -271733879; 36 | var c = -1732584194; 37 | var d = 271733878; 38 | var e = -1009589776; 39 | 40 | for(var i = 0; i < x.length; i += 16) { 41 | var olda = a; 42 | var oldb = b; 43 | var oldc = c; 44 | var oldd = d; 45 | var olde = e; 46 | 47 | for(var j = 0; j < 80; j++) { 48 | if(j < 16) w[j] = x[i + j]; 49 | else w[j] = PasswordMaker_HashUtils.bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); 50 | var t = PasswordMaker_HashUtils.safe_add(PasswordMaker_HashUtils.safe_add(PasswordMaker_HashUtils.bit_rol(a, 5), this.sha1_ft(j, b, c, d)), 51 | PasswordMaker_HashUtils.safe_add(PasswordMaker_HashUtils.safe_add(e, w[j]), this.sha1_kt(j))); 52 | e = d; 53 | d = c; 54 | c = PasswordMaker_HashUtils.bit_rol(b, 30); 55 | b = a; 56 | a = t; 57 | } 58 | 59 | a = PasswordMaker_HashUtils.safe_add(a, olda); 60 | b = PasswordMaker_HashUtils.safe_add(b, oldb); 61 | c = PasswordMaker_HashUtils.safe_add(c, oldc); 62 | d = PasswordMaker_HashUtils.safe_add(d, oldd); 63 | e = PasswordMaker_HashUtils.safe_add(e, olde); 64 | } 65 | return Array(a, b, c, d, e); 66 | 67 | }, 68 | 69 | /* 70 | * Perform the appropriate triplet combination function for the current 71 | * iteration 72 | */ 73 | sha1_ft : function(t, b, c, d) { 74 | if(t < 20) return (b & c) | ((~b) & d); 75 | if(t < 40) return b ^ c ^ d; 76 | if(t < 60) return (b & c) | (b & d) | (c & d); 77 | return b ^ c ^ d; 78 | }, 79 | 80 | /* 81 | * Determine the appropriate additive constant for the current iteration 82 | */ 83 | sha1_kt : function(t) { 84 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : 85 | (t < 60) ? -1894007588 : -899497514; 86 | }, 87 | 88 | /* 89 | * Calculate the HMAC-SHA1 of a key and some data (raw strings) 90 | */ 91 | rstr_hmac_sha1 : function(key, data) { 92 | var bkey = PasswordMaker_HashUtils.rstr2binb(key); 93 | if(bkey.length > 16) bkey = this.binb_sha1(bkey, key.length * 8); 94 | 95 | var ipad = Array(16), opad = Array(16); 96 | for(var i = 0; i < 16; i++) { 97 | ipad[i] = bkey[i] ^ 0x36363636; 98 | opad[i] = bkey[i] ^ 0x5C5C5C5C; 99 | } 100 | 101 | var hash = this.binb_sha1(ipad.concat(PasswordMaker_HashUtils.rstr2binb(data)), 512 + data.length * 8); 102 | return PasswordMaker_HashUtils.binb2rstr(this.binb_sha1(opad.concat(hash), 512 + 160)); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /javascript/passwordmaker/l33t.js: -------------------------------------------------------------------------------- 1 | /** 2 | PasswordMaker - Creates and manages passwords 3 | Copyright (C) 2005 Eric H. Jung and LeahScape, Inc. 4 | http://passwordmaker.org/ 5 | grimholtz@yahoo.com 6 | 7 | This library is free software; you can redistribute it and/or modify it 8 | under the terms of the GNU Lesser General Public License as published by 9 | the Free Software Foundation; either version 2.1 of the License, or (at 10 | your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, but WITHOUT 13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 15 | for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License 18 | along with this library; if not, write to the Free Software Foundation, 19 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | **/ 21 | 22 | /************************************************** 23 | * ECMAScript leetspeak - Version 1.0 by * 24 | * Eric H. Jung * 25 | * * 26 | * Ported from Oliver Gobin's * 27 | * PHP leetspeak - Version 1.0 * 28 | * http://www.ogobin.org/bin/scripts/31337.php.inc * 29 | * * 30 | * What is leetspeak? * 31 | * http://www.wikipedia.org/wiki/Leet * 32 | * http://www.heise.de/ct/00/11/003/ * 33 | ***************************************************/ 34 | 35 | if (typeof(PasswordMaker_l33t) != "boolean") { 36 | var PasswordMaker_l33t = true; 37 | var PasswordMaker_l33t = { 38 | alphabet : new Array(/a/g, /b/g, /c/g, /d/g, /e/g, /f/g, /g/g, /h/g, /i/g, /j/g, /k/g, /l/g, /m/g, /n/g, /o/g, /p/g, /q/g, /r/g, /s/g, /t/g, /u/g, /v/g, /w/g, /x/g, /y/g, /z/g), 39 | levels : new Array( 40 | new Array("4", "b", "c", "d", "3", "f", "g", "h", "i", "j", "k", "1", "m", "n", "0", "p", "9", "r", "s", "7", "u", "v", "w", "x", "y", "z"), 41 | new Array("4", "b", "c", "d", "3", "f", "g", "h", "1", "j", "k", "1", "m", "n", "0", "p", "9", "r", "5", "7", "u", "v", "w", "x", "y", "2"), 42 | new Array("4", "8", "c", "d", "3", "f", "6", "h", "'", "j", "k", "1", "m", "n", "0", "p", "9", "r", "5", "7", "u", "v", "w", "x", "'/", "2"), 43 | new Array("@", "8", "c", "d", "3", "f", "6", "h", "'", "j", "k", "1", "m", "n", "0", "p", "9", "r", "5", "7", "u", "v", "w", "x", "'/", "2"), 44 | new Array("@", "|3", "c", "d", "3", "f", "6", "#", "!", "7", "|<", "1", "m", "n", "0", "|>", "9", "|2", "$", "7", "u", "\\/", "w", "x", "'/", "2"), 45 | new Array("@", "|3", "c", "|)", "&", "|=", "6", "#", "!", ",|", "|<", "1", "m", "n", "0", "|>", "9", "|2", "$", "7", "u", "\\/", "w", "x", "'/", "2"), 46 | new Array("@", "|3", "[", "|)", "&", "|=", "6", "#", "!", ",|", "|<", "1", "^^", "^/", "0", "|*", "9", "|2", "5", "7", "(_)", "\\/", "\\/\\/", "><", "'/", "2"), 47 | new Array("@", "8", "(", "|)", "&", "|=", "6", "|-|", "!", "_|", "|\(", "1", "|\\/|", "|\\|", "()", "|>", "(,)", "|2", "$", "|", "|_|", "\\/", "\\^/", ")(", "'/", "\"/_"), 48 | new Array("@", "8", "(", "|)", "&", "|=", "6", "|-|", "!", "_|", "|\{", "|_", "/\\/\\", "|\\|", "()", "|>", "(,)", "|2", "$", "|", "|_|", "\\/", "\\^/", ")(", "'/", "\"/_")), 49 | 50 | /** 51 | * Convert the string in _message_ to l33t-speak 52 | * using the l33t level specified by _leetLevel_. 53 | * l33t levels are 1-9 with 1 being the simplest 54 | * form of l33t-speak and 9 being the most complex. 55 | * 56 | * Note that _message_ is converted to lower-case if 57 | * the l33t conversion is performed. 58 | * Future versions can support mixed-case, if we need it. 59 | * 60 | * Using a _leetLevel_ <= 0 results in the original message 61 | * being returned. 62 | * 63 | */ 64 | convert : function(leetLevel, message) { 65 | if (leetLevel > -1) { 66 | var ret = message.toLowerCase(); 67 | for (var item = 0; item < this.alphabet.length; item++) 68 | ret = ret.replace(this.alphabet[item], this.levels[leetLevel][item]); 69 | return ret; 70 | } 71 | return message; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /css/options.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | } 4 | 5 | #content { 6 | width: 750px; 7 | margin-left: auto; 8 | margin-right: auto; 9 | } 10 | 11 | #header { 12 | border-bottom: 1px solid #aaaaaa; 13 | background-color: #eeeeee; 14 | margin-bottom: 10px; 15 | } 16 | 17 | #header h1 { 18 | margin-bottom: 0px; 19 | padding-top: 15px; 20 | padding-bottom: 15px; 21 | width: 750px; 22 | margin-left: auto; 23 | margin-right: auto; 24 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 25 | font-style: italic; 26 | } 27 | 28 | #list { 29 | padding: 5px; 30 | width: 210px; 31 | float: left; 32 | border-right: 1px solid #aaaaaa; 33 | } 34 | 35 | #list ul { 36 | padding-left: 10px; 37 | list-style-type: none; 38 | } 39 | 40 | #list li:before { 41 | content: "\0020 \0020 \0020 \00BB \0020"; 42 | color: #aaaaaa; 43 | } 44 | 45 | #list .button { 46 | width: 120px; 47 | } 48 | 49 | h2 { 50 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 51 | } 52 | 53 | #profileNameTB { 54 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 55 | font-size: 2em; 56 | } 57 | 58 | .subrow { 59 | padding-top: 3px; 60 | } 61 | 62 | #showSettings { 63 | margin-top: 20px; 64 | } 65 | 66 | #showImport { 67 | margin-top: 20px; 68 | } 69 | 70 | #list h2 { 71 | padding-top: 0px; 72 | margin-top: 0px; 73 | } 74 | 75 | #profile_setting { 76 | padding: 5px; 77 | width: 505px; 78 | float: right; 79 | } 80 | 81 | #general_settings { 82 | padding: 5px; 83 | width: 505px; 84 | float: right; 85 | display: none; 86 | } 87 | 88 | #import_settings { 89 | padding: 5px; 90 | width: 505px; 91 | float: right; 92 | display: none; 93 | } 94 | 95 | #import_settings p { 96 | padding-left: 2px; 97 | } 98 | 99 | #importText { 100 | width: 505px; 101 | height: 150px; 102 | } 103 | 104 | #profile_setting h2 { 105 | padding-top: 0px; 106 | margin-top: 0px; 107 | } 108 | 109 | #buttons { 110 | margin-top: 20px; 111 | margin-left: 135px; 112 | width: 300px; 113 | } 114 | 115 | #buttons #remove { 116 | float: right; 117 | } 118 | 119 | #buttons #save { 120 | float: left; 121 | } 122 | 123 | #import_buttons { 124 | width: 505px; 125 | text-align: right; 126 | } 127 | 128 | .row { 129 | margin-bottom: 5px; 130 | } 131 | 132 | .secondColumn { 133 | margin-left: 135px; 134 | } 135 | 136 | label { 137 | position: absolute; 138 | text-align:right; 139 | width:130px; 140 | margin-top: 0.2em; 141 | } 142 | 143 | label.disabled { 144 | color: #aaaaaa; 145 | } 146 | 147 | label.checkbox { 148 | position: relative; 149 | } 150 | 151 | input[type="checkbox"] { 152 | width: 20px; 153 | } 154 | 155 | select { 156 | margin-left: 135px; 157 | width: 300px; 158 | } 159 | 160 | input { 161 | margin-left: 135px; 162 | width: 300px; 163 | } 164 | 165 | .url_example span.selected { 166 | color: #FFDB13; 167 | } 168 | 169 | .url_example { 170 | margin-left: 135px; 171 | width: 300px; 172 | text-align: center; 173 | background-color: #000000; 174 | border-radius: 7px !important; 175 | -moz-border-radius: 7px !important; 176 | -webkit-border-radius: 7px !important; 177 | margin-bottom: 10px; 178 | color: #ffffff; 179 | font-size: 12px; 180 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 181 | font-style: italic; 182 | padding-top: 10px; 183 | padding-bottom: 10px; 184 | } 185 | 186 | #pledgie { 187 | margin-top: 30px; 188 | } 189 | 190 | #footer { 191 | font-family: Georgia, Palatino, Palatino Linotype, Times, Times New Roman, serif; 192 | font-style: italic; 193 | font-size: 0.8em; 194 | margin-top: 30px; 195 | width: 100%; 196 | text-align: center; 197 | } 198 | 199 | #footer a { 200 | background-color: #dddddd; 201 | font-style: normal; 202 | color: #000000; 203 | padding: 4px; 204 | border-radius: 5px !important; 205 | -moz-border-radius: 5px !important; 206 | -webkit-border-radius: 5px !important; 207 | } 208 | -------------------------------------------------------------------------------- /javascript/import.js: -------------------------------------------------------------------------------- 1 | function strToBool(v) { 2 | return v.toString() === 'true'; 3 | } 4 | 5 | var RdfImporter = { 6 | attrMap: { 7 | about: { 8 | name: 'rdf_about', 9 | }, 10 | 11 | // Settings 12 | // TODO? master password 13 | maskmasterpassword: { 14 | name: 'hideMasterPassword', 15 | convert: strToBool, 16 | }, 17 | masterpasswordstorage: { 18 | name: 'storeLocation', 19 | convert: function (v) { 20 | return {'store-on-disk': 'disk', 'store-in-memory': 'memory'}[v]; 21 | }, 22 | }, 23 | 24 | // Profiles 25 | name: { 26 | name: 'title', 27 | }, 28 | whereleetlb: { 29 | name: 'whereToUseL33t', 30 | }, 31 | leetlevellb: { 32 | name: 'l33tLevel', 33 | convert: parseInt, 34 | }, 35 | hashalgorithmlb: { 36 | name: 'hashAlgorithm', 37 | convert: function (v) { 38 | // rest of the names are the same 39 | return {'hmac-sha256-fixed': 'hmac-sha256_fix', 40 | 'md5-v0.6': 'md5_v6', 41 | 'hmac-md5-v0.6': 'hmac-md5_v6'}[v] || v; 42 | }, 43 | }, 44 | passwordlength: { 45 | name: 'passwordLength', 46 | convert: parseInt, 47 | }, 48 | usernametb: { 49 | name: 'username', 50 | }, 51 | counter: { 52 | name: 'modifier', 53 | }, 54 | charset: { 55 | name: 'selectedCharset', 56 | }, 57 | prefix: { 58 | name: 'passwordPrefix', 59 | }, 60 | suffix: { 61 | name: 'passwordSuffix', 62 | }, 63 | protocolcb: { 64 | name: 'url_protocol', 65 | convert: strToBool, 66 | }, 67 | subdomaincb: { 68 | name: 'url_subdomain', 69 | convert: strToBool, 70 | }, 71 | domaincb: { 72 | name: 'url_domain', 73 | convert: strToBool, 74 | }, 75 | pathcb: { 76 | name: 'url_path', 77 | convert: strToBool, 78 | }, 79 | } 80 | } 81 | 82 | RdfImporter.loadDoc = function(rdf) { 83 | var profiles = [], 84 | defaultProfile = {}, 85 | settings = {}, 86 | that = this; 87 | // check over every Description, but will ignore groups and anything without 88 | // settings/profile attributes 89 | $(rdf).find('RDF\\:Description').each(function(){ 90 | var prof = {}; 91 | for(var i=0;i 3 | 4 | 5 | QUnit Test Suite 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 24 |

QUnit Test Suite

25 |

26 |
27 |

28 |
29 | 30 |
31 | 109 |
110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /test/qunit.css: -------------------------------------------------------------------------------- 1 | /** Font Family and Sizes */ 2 | 3 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 4 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; 5 | } 6 | 7 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 8 | #qunit-tests { font-size: smaller; } 9 | 10 | 11 | /** Resets */ 12 | 13 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 14 | margin: 0; 15 | padding: 0; 16 | } 17 | 18 | 19 | /** Header */ 20 | 21 | #qunit-header { 22 | padding: 0.5em 0 0.5em 1em; 23 | 24 | color: #8699a4; 25 | background-color: #0d3349; 26 | 27 | font-size: 1.5em; 28 | line-height: 1em; 29 | font-weight: normal; 30 | 31 | border-radius: 15px 15px 0 0; 32 | -moz-border-radius: 15px 15px 0 0; 33 | -webkit-border-top-right-radius: 15px; 34 | -webkit-border-top-left-radius: 15px; 35 | } 36 | 37 | #qunit-header a { 38 | text-decoration: none; 39 | color: #c2ccd1; 40 | } 41 | 42 | #qunit-header a:hover, 43 | #qunit-header a:focus { 44 | color: #fff; 45 | } 46 | 47 | #qunit-banner { 48 | height: 5px; 49 | } 50 | 51 | #qunit-testrunner-toolbar { 52 | padding: 0.5em 0 0.5em 2em; 53 | color: #5E740B; 54 | background-color: #eee; 55 | } 56 | 57 | #qunit-userAgent { 58 | padding: 0.5em 0 0.5em 2.5em; 59 | background-color: #2b81af; 60 | color: #fff; 61 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 62 | } 63 | 64 | 65 | /** Tests: Pass/Fail */ 66 | 67 | #qunit-tests { 68 | list-style-position: inside; 69 | } 70 | 71 | #qunit-tests li { 72 | padding: 0.4em 0.5em 0.4em 2.5em; 73 | border-bottom: 1px solid #fff; 74 | list-style-position: inside; 75 | } 76 | 77 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 78 | display: none; 79 | } 80 | 81 | #qunit-tests li strong { 82 | cursor: pointer; 83 | } 84 | 85 | #qunit-tests li a { 86 | padding: 0.5em; 87 | color: #c2ccd1; 88 | text-decoration: none; 89 | } 90 | #qunit-tests li a:hover, 91 | #qunit-tests li a:focus { 92 | color: #000; 93 | } 94 | 95 | #qunit-tests ol { 96 | margin-top: 0.5em; 97 | padding: 0.5em; 98 | 99 | background-color: #fff; 100 | 101 | border-radius: 15px; 102 | -moz-border-radius: 15px; 103 | -webkit-border-radius: 15px; 104 | 105 | box-shadow: inset 0px 2px 13px #999; 106 | -moz-box-shadow: inset 0px 2px 13px #999; 107 | -webkit-box-shadow: inset 0px 2px 13px #999; 108 | } 109 | 110 | #qunit-tests table { 111 | border-collapse: collapse; 112 | margin-top: .2em; 113 | } 114 | 115 | #qunit-tests th { 116 | text-align: right; 117 | vertical-align: top; 118 | padding: 0 .5em 0 0; 119 | } 120 | 121 | #qunit-tests td { 122 | vertical-align: top; 123 | } 124 | 125 | #qunit-tests pre { 126 | margin: 0; 127 | white-space: pre-wrap; 128 | word-wrap: break-word; 129 | } 130 | 131 | #qunit-tests del { 132 | background-color: #e0f2be; 133 | color: #374e0c; 134 | text-decoration: none; 135 | } 136 | 137 | #qunit-tests ins { 138 | background-color: #ffcaca; 139 | color: #500; 140 | text-decoration: none; 141 | } 142 | 143 | /*** Test Counts */ 144 | 145 | #qunit-tests b.counts { color: black; } 146 | #qunit-tests b.passed { color: #5E740B; } 147 | #qunit-tests b.failed { color: #710909; } 148 | 149 | #qunit-tests li li { 150 | margin: 0.5em; 151 | padding: 0.4em 0.5em 0.4em 0.5em; 152 | background-color: #fff; 153 | border-bottom: none; 154 | list-style-position: inside; 155 | } 156 | 157 | /*** Passing Styles */ 158 | 159 | #qunit-tests li li.pass { 160 | color: #5E740B; 161 | background-color: #fff; 162 | border-left: 26px solid #C6E746; 163 | } 164 | 165 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 166 | #qunit-tests .pass .test-name { color: #366097; } 167 | 168 | #qunit-tests .pass .test-actual, 169 | #qunit-tests .pass .test-expected { color: #999999; } 170 | 171 | #qunit-banner.qunit-pass { background-color: #C6E746; } 172 | 173 | /*** Failing Styles */ 174 | 175 | #qunit-tests li li.fail { 176 | color: #710909; 177 | background-color: #fff; 178 | border-left: 26px solid #EE5757; 179 | } 180 | 181 | #qunit-tests > li:last-child { 182 | border-radius: 0 0 15px 15px; 183 | -moz-border-radius: 0 0 15px 15px; 184 | -webkit-border-bottom-right-radius: 15px; 185 | -webkit-border-bottom-left-radius: 15px; 186 | } 187 | 188 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 189 | #qunit-tests .fail .test-name, 190 | #qunit-tests .fail .module-name { color: #000000; } 191 | 192 | #qunit-tests .fail .test-actual { color: #EE5757; } 193 | #qunit-tests .fail .test-expected { color: green; } 194 | 195 | #qunit-banner.qunit-fail { background-color: #EE5757; } 196 | 197 | 198 | /** Result */ 199 | 200 | #qunit-testresult { 201 | padding: 0.5em 0.5em 0.5em 2.5em; 202 | 203 | color: #2b81af; 204 | background-color: #D2E0E6; 205 | 206 | border-bottom: 1px solid white; 207 | } 208 | 209 | /** Fixture */ 210 | 211 | #qunit-fixture { 212 | position: absolute; 213 | top: -10000px; 214 | left: -10000px; 215 | } 216 | -------------------------------------------------------------------------------- /javascript/popup.js: -------------------------------------------------------------------------------- 1 | var currentTab = null; 2 | 3 | function setPasswordColors(foreground, background) { 4 | $("#generated").css("background-color", background); 5 | $("#generated").css("color", foreground); 6 | $("#password").css("background-color", background); 7 | $("#password").css("color", foreground); 8 | $("#confirmation").css("background-color", background); 9 | $("#confirmation").css("color", foreground); 10 | } 11 | 12 | function updateFields(e) { 13 | var password = $("#password").val(); 14 | var confirmation = $("#confirmation").val(); 15 | var profileId = $("#profile").val(); 16 | var profile = Settings.getProfile(profileId); 17 | 18 | Settings.setStoreLocation($("#store_location").val()); 19 | Settings.setPassword(password); 20 | Settings.setActiveProfileId(profileId); 21 | 22 | if (password == "") { 23 | $("#generatedForClipboard").val(""); 24 | $("#generated").val("Enter password"); 25 | setPasswordColors("#000000", "#85FFAB") 26 | } else if ( ! matchesHash(password) ) { 27 | $("#generatedForClipboard").val(""); 28 | $("#generated").val("Master password mismatch"); 29 | setPasswordColors("#FFFFFF", "#FF7272") 30 | } else if (!Settings.keepMasterPasswordHash() && password != confirmation) { 31 | $("#generatedForClipboard").val(""); 32 | $("#generated").val("Password wrong"); 33 | setPasswordColors("#FFFFFF", "#FF7272") 34 | } else { 35 | if (profile != null) { 36 | var generatedPassword = profile.getPassword($("#usedtext").val(), password); 37 | $("#generated").val(generatedPassword); 38 | $("#generatedForClipboard").val(generatedPassword); 39 | showCopy(); 40 | } else { 41 | $("#generated").val(""); 42 | $("#generatedForClipboard").val(""); 43 | } 44 | setPasswordColors("#000000", "#FFFFFF") 45 | // pressed enter in confirmation field 46 | if(e && e.keyCode == 13){ 47 | chrome.tabs.sendRequest(currentTab, {hasPasswordField: true}, function(response) { 48 | if (response.hasField) { 49 | fillPassword(); 50 | } 51 | }); 52 | } 53 | } 54 | if (Settings.keepMasterPasswordHash()) { 55 | $("#confirmation_row").css('display', 'none'); 56 | } else { 57 | $("#confirmation_row").css('display', 'block'); 58 | } 59 | } 60 | 61 | function matchesHash(password) { 62 | if (!Settings.keepMasterPasswordHash()) return true; 63 | var saved_hash = Settings.masterPasswordHash(); 64 | var new_hash = ChromePasswordMaker_SecureHash.make_hash(password); 65 | return new_hash == saved_hash ; 66 | } 67 | 68 | function updateUsedText(url) { 69 | var profile = Settings.getProfile($("#profile").val()); 70 | $("#usedtext").val(profile.getUrl(url)); 71 | } 72 | 73 | function fetchUrlAndUpdateUsedText() { 74 | chrome.windows.getCurrent(function(obj) { 75 | chrome.tabs.getSelected(obj.id, function(tab) { 76 | updateUsedText(tab.url); 77 | }); 78 | }); 79 | } 80 | 81 | function showInject() { 82 | $("#injectpasswordrow").fadeIn(); 83 | } 84 | 85 | function showCopy() { 86 | $("#copypassword").fadeIn(); 87 | } 88 | 89 | function init(url) { 90 | var profiles = Settings.getProfiles(); 91 | Settings.getPassword(function(password) { 92 | $("#password").val(password); 93 | $("#confirmation").val(password); 94 | 95 | var options = ""; 96 | for (var i in profiles) { 97 | var profile = profiles[i]; 98 | options += "