// The PasspetEntropy XPCOM component estimates the entropy of a password.

// Shorthand for getting XPConnect interfaces, classes, objects, and services.
const XPI = Components.interfaces, XPC = Components.classes;
function XPC_(c) { return XPC[c.match(/^@/) ? c : '@mozilla.org/' + c]; }
function XPO(c, i) { return XPC_(c) ? XPC_(c).createInstance(i) : null; }
function XPS(c, i) { return XPC_(c) ? XPC_(c).getService(i) : null; }
function XQI(o, i) { return o.QueryInterface(i); }

const XPR = Components.results;
const CID = Components.ID('{99d81d3c-81a9-527e-9728-d69fbb657dee}');
const NAME = 'Passpet Entropy Estimator';
const CONTRACT = '@passpet.org/entropy-estimator;1';

// The module registers and unregisters the PasspetHash component interface.
function NSGetModule(manager, filespec) {
    return new function() {
        this.registerSelf = function(manager, filespec, location, type) {
            manager = XQI(manager, XPI.nsIComponentRegistrar);
            manager.registerFactoryLocation(
                CID, NAME, CONTRACT, filespec, location, type);
        };

        this.unregisterSelf = function(manager, location, type) {
            manager = XQI(manager, XPI.nsIComponentRegistrar);
            manager.unregisterFactoryLocation(CID, location);
        };

        this.canUnload = function(manager) {
            return true;
        };

        this.getClassObject = function(manager, cid, iid) {
            if (!iid.equals(XPI.nsIFactory)) throw XPR.NS_ERROR_NOT_IMPLEMENTED;
            if (!cid.equals(CID)) throw XPR.NS_ERROR_NO_INTERFACE;
            return new function() {
                this.createInstance = function(outer, iid) {
                    if (outer != null) throw XPR.NS_ERROR_NO_AGGREGATION;
                    return XQI(new service(), iid);
                };
            };
        };
    };
};

// Estimate the entropy of a password.

// Ultimately this is a psychological task rather than a purely
// mathematical one --- the entropy of your password depends on the
// process generating the password, and the better the attacker's
// model of that process, the more quickly they can guess your
// password.  To the extent that the attacker's model of the process
// is worse than ours, we'll underestimate how difficult it will be
// for them; to the extent that the attacker's model is better than
// ours, we'll overestimate how difficult it will be for them.

// Our model here is oversimplified.  The guy who's coming up with the
// password does so by concatenating some sequence of randomly,
// independently chosen tokens; possible tokens include about 3000
// common passwords, all 128 7-bit bytes, and end-of-string.  Not
// having any very concrete idea about the relative probabilities of
// these things, we figure that end-of-string is the most common,
// followed by the first 128 most common passwords interleaved with
// the 8-bit bytes (first the numbers, then the lowercase letters,
// then the uppercase letters, then punctuation, then everything
// else), followed by the rest of the common passwords; and we assume
// a pure Zipf distribution for these tokens.

// You could do better by using a larger wordlist, paying attention to
// pop culture and popular human names, distributing letters and
// digraphs more according to some real-world set of distributions,
// and making common substitutions in the tokens to get less-probable
// tokens, such as "pa55w0rd" for "password" (the third-most-common
// password.) 

// But I didn't.
                 
// XXX what to do about non-ASCII?

// This list has been compiled by Solar Designer of Openwall Project,
// http://www.openwall.com/wordlists/
//
// This is a list of passwords most commonly seen on a set of Unix
// systems in mid-1990's, sorted for decreasing number of occurrences
// (that is, more common passwords are listed first).
//
// Last update: 2005/12/16 (3107 entries)

// Extracted from John the Ripper password cracker, Copyright (c)
// 1996-2006 by Solar Designer, which says (in doc/LICENSE):
// This version of John the Ripper is hereby being made available to you
// under the terms of the GNU General Public License version 2 as published
// by the Free Software Foundation.

const common_passwords = [
    '12345', 'abc123', 'password', 'computer', '123456', 'tigger', '1234',
    'a1b2c3', 'qwerty', '123', 'xxx', 'money', 'test', 'carmen', 'mickey',
    'secret', 'summer', 'internet', 'service', '', 'canada', 'hello',
    'ranger', 'shadow', 'baseball', 'donald', 'harley', 'hockey', 'letmein',
    'maggie', 'mike', 'mustang', 'snoopy', 'buster', 'dragon', 'jordan',
    'michael', 'michelle', 'mindy', 'patrick', '123abc', 'andrew', 'bear',
    'calvin', 'changeme', 'diamond', 'fuckme', 'fuckyou', 'matthew',
    'miller', 'ou812', 'tiger', 'trustno1', '12345678', 'alex', 'apple',
    'avalon', 'brandy', 'chelsea', 'coffee', 'dave', 'falcon', 'freedom',
    'gandalf', 'golf', 'green', 'helpme', 'linda', 'magic', 'merlin',
    'molson', 'newyork', 'soccer', 'thomas', 'wizard', 'Monday', 'asdfgh',
    'bandit', 'batman', 'boris', 'butthead', 'dorothy', 'eeyore', 'fishing',
    'football', 'george', 'happy', 'iloveyou', 'jennifer', 'jonathan',
    'love', 'marina', 'master', 'missy', 'monday', 'monkey', 'natasha',
    'ncc1701', 'newpass', 'pamela', 'pepper', 'piglet', 'poohbear',
    'pookie', 'rabbit', 'rachel', 'rocket', 'rose', 'smile', 'sparky',
    'spring', 'steven', 'success', 'sunshine', 'thx1138', 'victoria',
    'whatever', 'zapata', '1', '8675309', 'Internet', 'amanda', 'andy',
    'angel', 'august', 'barney', 'biteme', 'boomer', 'brian', 'casey',
    'coke', 'cowboy', 'delta', 'doctor', 'fisher', 'foobar', 'island',
    'john', 'joshua', 'karen', 'marley', 'orange', 'please', 'rascal',
    'richard', 'sarah', 'scooter', 'shalom', 'silver', 'skippy', 'stanley',
    'taylor', 'welcome', 'zephyr', '111111', '1928', 'aaaaaa', 'abc',
    'access', 'albert', 'alexander', 'andrea', 'anna', 'anthony',
    'asdfjkl;', 'ashley', 'basf', 'basketball', 'beavis', 'black', 'bob',
    'booboo', 'bradley', 'brandon', 'buddy', 'caitlin', 'camaro', 'charlie',
    'chicken', 'chris', 'cindy', 'cricket', 'dakota', 'dallas', 'daniel',
    'david', 'debbie', 'dolphin', 'elephant', 'emily', 'fish', 'fred',
    'friend', 'fucker', 'ginger', 'goodluck', 'hammer', 'heather', 'help',
    'iceman', 'jason', 'jessica', 'jesus', 'joseph', 'jupiter', 'justin',
    'kevin', 'knight', 'lacrosse', 'lakers', 'lizard', 'madison', 'mary',
    'mother', 'muffin', 'murphy', 'ncc1701d', 'newuser', 'nirvana', 'none',
    'paris', 'pat', 'pentium', 'phoenix', 'picture', 'rainbow', 'sandy',
    'saturn', 'scott', 'shannon', 'shithead', 'skeeter', 'sophie',
    'special', 'stephanie', 'stephen', 'steve', 'sweetie', 'teacher',
    'tennis', 'test123', 'tommy', 'topgun', 'tristan', 'wally', 'william',
    'wilson', '1q2w3e', '654321', '666666', '777', 'a12345', 'a1b2c3d4',
    'alpha', 'amber', 'angela', 'angie', 'archie', 'asdf', 'blazer',
    'bond007', 'booger', 'charles', 'christin', 'claire', 'control',
    'danny', 'david1', 'dennis', 'digital', 'disney', 'dog', 'duck', 'duke',
    'edward', 'elvis', 'felix', 'flipper', 'floyd', 'franklin', 'frodo',
    'guest', 'honda', 'horses', 'hunter', 'indigo', 'info', 'james',
    'jasper', 'jeremy', 'joe', 'julian', 'kelsey', 'killer', 'kingfish',
    'lauren', 'marie', 'maryjane', 'matrix', 'maverick', 'mayday',
    'mercury', 'micro', 'mitchell', 'morgan', 'mountain', 'niners',
    'nothing', 'oliver', 'peace', 'peanut', 'pearljam', 'phantom',
    'popcorn', 'princess', 'psycho', 'pumpkin', 'purple', 'randy',
    'rebecca', 'reddog', 'robert', 'rocky', 'roses', 'salmon', 'sam',
    'samson', 'sharon', 'sierra', 'smokey', 'startrek', 'steelers',
    'stimpy', 'sunflower', 'superman', 'support', 'sydney', 'techno',
    'telecom', 'test1', 'walter', 'willie', 'willow', 'winner', 'ziggy',
    'zxcvbnm', '7777', 'OU812', 'a', 'absolut', 'alaska', 'alexis', 'alice',
    'animal', 'apples', 'babylon5', 'backup', 'barbara', 'benjamin', 'bill',
    'billy', 'bird33', 'blue', 'bluebird', 'bobby', 'bonnie', 'bubba',
    'camera', 'chocolate', 'clark', 'claudia', 'cocacola', 'compton',
    'connect', 'cookie', 'cruise', 'deliver', 'douglas', 'dreamer',
    'dreams', 'duckie', 'eagles', 'eddie', 'einstein', 'enter', 'explorer',
    'faith', 'family', 'ferrari', 'fire', 'flamingo', 'flip', 'flower',
    'foxtrot', 'francis', 'freddy', 'friday', 'froggy', 'galileo', 'giants',
    'gizmo', 'global', 'goofy', 'gopher', 'hansolo', 'happy1', 'hendrix',
    'henry', 'herman', 'homer', 'honey', 'house', 'houston', 'iguana',
    'indiana', 'insane', 'inside', 'irish', 'ironman', 'jake', 'jane',
    'jasmin', 'jeanne', 'jerry', 'jim', 'joey', 'justice', 'katherine',
    'kermit', 'kitty', 'koala', 'larry', 'leslie', 'logan', 'lucky', 'mark',
    'martin', 'matt', 'minnie', 'misty', 'mitch', 'mom', 'mouse', 'nancy',
    'nascar', 'nelson', 'netware', 'pantera', 'parker', 'passwd', 'penguin',
    'peter', 'phil', 'phish', 'piano', 'pizza', 'porsche911', 'prince',
    'punkin', 'pyramid', 'rain', 'raymond', 'red', 'robin', 'roger',
    'rosebud', 'route66', 'royal', 'running', 'sadie', 'sasha', 'security',
    'sergei', 'sheena', 'sheila', 'skiing', 'snapple', 'snowball',
    'sparrow', 'spencer', 'spike', 'star', 'stealth', 'student', 'sun',
    'sunny', 'sylvia', 'tamara', 'taurus', 'tech', 'teresa', 'theresa',
    'thunderbird', 'tigers', 'tony', 'toyota', 'training', 'travel',
    'truck', 'tuesday', 'victory', 'video', 'viper1', 'volvo', 'wesley',
    'whisky', 'winnie', 'winter', 'wolves', 'xyz123', 'zorro', '!@#$%',
    '007', '123123', '1234567', '1969', '5683', '696969', '888888',
    'Anthony', 'Bond007', 'Friday', 'Hendrix', 'Joshua', 'Matthew',
    'October', 'Taurus', 'Tigger', 'aaa', 'aaron', 'abby', 'abcdef',
    'adidas', 'adrian', 'alexandr', 'alfred', 'arthur', 'athena', 'austin',
    'awesome', 'badger', 'bamboo', 'beagle', 'bears', 'beatles',
    'beautiful', 'beaver', 'benny', 'bigmac', 'bingo', 'bitch', 'blonde',
    'boogie', 'boston', 'brenda', 'bright', 'bubba1', 'bubbles', 'buffy',
    'button', 'buttons', 'cactus', 'candy', 'captain', 'carlos', 'caroline',
    'carrie', 'casper', 'catalog', 'catch22', 'challenge', 'chance',
    'charity', 'charlotte', 'cheese', 'cheryl', 'chloe', 'chris1', 'clancy',
    'clipper', 'coltrane', 'compaq', 'conrad', 'cooper', 'cooter', 'copper',
    'cosmos', 'cougar', 'cracker', 'crawford', 'crystal', 'curtis',
    'cyclone', 'cyrano', 'dan', 'dance', 'dawn', 'dean', 'deutsch',
    'diablo', 'dilbert', 'dollars', 'dookie', 'doom', 'dumbass', 'dundee',
    'e-mail', 'elizabeth', 'eric', 'europe', 'export', 'farmer', 'firebird',
    'fletcher', 'fluffy', 'ford', 'fountain', 'fox', 'france', 'freak1',
    'friends', 'frog', 'fuckoff', 'gabriel', 'gabriell', 'galaxy', 'gambit',
    'garden', 'garfield', 'garlic', 'garnet', 'genesis', 'genius',
    'godzilla', 'goforit', 'golfer', 'goober', 'grace', 'grateful',
    'greenday', 'groovy', 'grover', 'guitar', 'hacker', 'harry', 'hazel',
    'hector', 'herbert', 'hoops', 'horizon', 'hornet', 'howard', 'icecream',
    'imagine', 'impala', 'informix', 'jack', 'janice', 'jasmine', 'jason1',
    'jeanette', 'jeffrey', 'jenifer', 'jenni', 'jesus1', 'jewels', 'joker',
    'julie', 'julie1', 'junior', 'justin1', 'kathleen', 'keith', 'kelly',
    'kelly1', 'kennedy', 'kevin1', 'knicks', 'lady', 'larry1', 'ledzep',
    'lee', 'leonard', 'lestat', 'library', 'lincoln', 'lionking', 'london',
    'louise', 'lucky1', 'lucy', 'maddog', 'mailman', 'majordomo', 'mantra',
    'margaret', 'mariposa', 'market', 'marlboro', 'martin1', 'marty',
    'master1', 'mazda1', 'mensuck', 'mercedes', 'metal', 'metallic',
    'midori', 'mikey', 'millie', 'mirage', 'mmm', 'molly', 'monet',
    'money1', 'monica', 'monopoly', 'mookie', 'moose', 'moroni', 'music',
    'naomi', 'nathan', 'ncc1701e', 'nesbitt', 'news', 'nguyen', 'nicholas',
    'nicole', 'nimrod', 'october', 'olive', 'olivia', 'one', 'online',
    'open', 'oscar', 'oxford', 'pacific', 'painter', 'peaches', 'penelope',
    'pepsi', 'pete', 'petunia', 'philip', 'phoenix1', 'photo', 'pickle',
    'player', 'poiuyt', 'porsche', 'porter', 'ppp', 'puppy', 'python',
    'quality', 'quest', 'raquel', 'raven', 'remember', 'republic',
    'research', 'robbie', 'robert1', 'roman', 'rugby', 'runner', 'russell',
    'ryan', 'sailing', 'sailor', 'samantha', 'savage', 'sbdc', 'scarlett',
    'school', 'sean', 'seven', 'shadow1', 'sheba', 'shelby', 'shit',
    'shoes', 'simba', 'simple', 'skipper', 'smiley', 'snake', 'snickers',
    'sniper', 'snoopdog', 'snowman', 'sonic', 'spitfire', 'sprite',
    'spunky', 'starwars', 'station', 'stella', 'stingray', 'storm',
    'stormy', 'stupid', 'sumuinen', 'sunny1', 'sunrise', 'supra', 'surfer',
    'susan', 'tammy', 'tango', 'tanya', 'tara', 'teddy1', 'temp', 'testing',
    'theboss', 'theking', 'thumper', 'tina', 'tintin', 'tomcat', 'trebor',
    'trek', 'trevor', 'tweety', 'unicorn', 'valentine', 'valerie',
    'vanilla', 'veronica', 'victor', 'vincent', 'viper', 'warrior',
    'warriors', 'weasel', 'wheels', 'wilbur', 'winston', 'wisdom', 'wombat',
    'xanadu', 'xavier', 'xxxx', 'yellow', 'zaphod', 'zeppelin', 'zeus',
    '!@#$%^', '!@#$%^&*', '*', '0007', '1022', '10sne1', '1111', '1212',
    '1911', '1948', '1973', '1978', '1996', '1p2o3i', '2000', '2222',
    '3bears', '5252', 'Andrew', 'Broadway', 'Champs', 'Family', 'Fisher',
    'Friends', 'Jeanne', 'Killer', 'Knight', 'Master', 'Michael',
    'Michelle', 'Pentium', 'Pepper', 'Raistlin', 'Sierra', 'Snoopy',
    'Tennis', 'Tuesday', 'abacab', 'abcd', 'abcd1234', 'abcdefg', 'abigail',
    'account', 'ace', 'acropolis', 'adam', 'adi', 'alex1', 'alice1',
    'allison', 'alpine', 'amy', 'anders', 'andre1', 'andrea1', 'angel1',
    'anita', 'annette', 'antares', 'apache', 'apollo', 'aragorn', 'arizona',
    'arnold', 'arsenal', 'asdfasdf', 'asdfg', 'asdfghjk', 'avenger',
    'avenir', 'baby', 'babydoll', 'bach', 'bailey', 'banana', 'barry',
    'basil', 'basket', 'bass', 'batman1', 'beaner', 'beast', 'beatrice',
    'beer', 'bella', 'ben', 'bertha', 'bigben', 'bigdog', 'biggles',
    'bigman', 'binky', 'biology', 'bishop', 'bliss', 'blondie', 'blowfish',
    'bluefish', 'bmw', 'bobcat', 'bosco', 'boss', 'braves', 'brazil',
    'bridges', 'bruce', 'bruno', 'brutus', 'buck', 'buffalo', 'bugsy',
    'bull', 'bulldog', 'bullet', 'bullshit', 'bunny', 'business', 'butch',
    'butler', 'butter', 'california', 'cannondale', 'canon', 'carebear',
    'carol', 'carol1', 'carole', 'cassie', 'castle', 'catalina',
    'catherine', 'catnip', 'cccccc', 'celine', 'center', 'champion',
    'chanel', 'chaos', 'chelsea1', 'chester1', 'chicago', 'chico', 'chip',
    'christian', 'christy', 'church', 'cinder', 'civil', 'colleen',
    'colorado', 'columbia', 'commander', 'connie', 'content', 'cook',
    'cookies', 'cooking', 'cordelia', 'corona', 'cowboys', 'coyote',
    'crack1', 'craig', 'creative', 'crow', 'cuddles', 'cuervo', 'cutie',
    'cyber', 'daddy', 'daisie', 'daisy', 'daniel1', 'danielle', 'dark1',
    'database', 'davids', 'deadhead', 'death', 'denali', 'denis', 'depeche',
    'derek', 'design', 'destiny', 'diana', 'diane', 'dickens', 'dickhead',
    'digger', 'dodger', 'don', 'donna', 'dougie', 'draft', 'dragonfly',
    'dylan', 'eagle', 'eclipse', 'electric', 'emerald', 'emmitt', 'entropy',
    'etoile', 'excalibur', 'express', 'farout', 'farside', 'feedback',
    'fender', 'fidel', 'fiona', 'fireman', 'firenze', 'fish1', 'flash',
    'fletch', 'florida', 'flowers', 'fool', 'foster', 'fozzie', 'francesco',
    'francine', 'francois', 'frank', 'french', 'fuckface', 'fun',
    'gargoyle', 'gasman', 'gemini', 'general', 'gerald', 'germany',
    'gilbert', 'goaway', 'gold', 'golden', 'goldfish', 'goose', 'gordon',
    'graham', 'grant', 'graphic', 'gregory', 'gretchen', 'gunner',
    'hal9000', 'hannah', 'harold', 'harrison', 'harvey', 'hawkeye',
    'heaven', 'heidi', 'helen', 'helena', 'hell', 'herzog', 'hithere',
    'hobbit', 'huey', 'ibanez', 'idontknow', 'image', 'integra', 'intern',
    'intrepid', 'ireland', 'irene', 'isaac', 'isabel', 'jackie', 'jackson',
    'jaguar', 'jamaica', 'japan', 'jeff', 'jenny1', 'jessie', 'jethrotull',
    'jkl123', 'joel', 'johan', 'johanna1', 'johnny', 'joker1', 'jordan23',
    'judith', 'julia', 'jumanji', 'jussi', 'kangaroo', 'karen1', 'kathy',
    'keepout', 'keith1', 'kenneth', 'kidder', 'kim', 'kimberly', 'king',
    'kingdom', 'kirk', 'kitkat', 'kramer', 'kris', 'kristen', 'lambda',
    'laura', 'laurie', 'law', 'lawrence', 'lawyer', 'legend', 'leon',
    'liberty', 'light', 'lindsay', 'lindsey', 'lisa', 'liverpool',
    'logical', 'lola', 'lonely', 'lorrie', 'louis', 'lovely', 'loveme',
    'lucas', 'm', 'madonna', 'mail', 'major', 'malcolm', 'malibu',
    'marathon', 'marcel', 'maria1', 'mariah', 'mariah1', 'marilyn',
    'mariner', 'mario', 'mark1', 'marvin', 'maurice', 'max', 'maxine',
    'maxwell', 'me', 'media', 'meggie', 'melanie', 'melissa', 'melody',
    'merlot', 'mexico', 'michael1', 'michele', 'midnight', 'midway',
    'mike1', 'miki', 'mine', 'miracle', 'misha', 'mishka', 'mmouse',
    'molly1', 'monique', 'montreal', 'moocow', 'moon', 'moore', 'mopar',
    'morris', 'mort', 'mortimer', 'mouse1', 'mulder', 'nautica', 'nellie',
    'nermal', 'new', 'newton', 'nicarao', 'nick', 'nina', 'nirvana1',
    'nissan', 'norman', 'notebook', 'ocean', 'olivier', 'ollie', 'olsen',
    'opera', 'opus', 'oranges', 'oregon', 'orion', 'overkill', 'pacers',
    'packer', 'panda', 'pandora', 'panther', 'passion', 'patricia', 'pearl',
    'peewee', 'pencil', 'penny', 'people', 'percy', 'person', 'peter1',
    'petey', 'picard', 'picasso', 'pierre', 'pinkfloyd', 'pit', 'plus',
    'polar', 'polaris', 'police', 'polo', 'pookie1', 'poppy', 'power',
    'predator', 'preston', 'primus', 'prometheus', 'public', 'q1w2e3',
    'queen', 'queenie', 'quentin', 'radio', 'ralph', 'random', 'rangers',
    'raptor', 'rastafarian', 'reality', 'redrum', 'remote', 'reptile',
    'reynolds', 'rhonda', 'ricardo', 'ricardo1', 'ricky', 'river',
    'roadrunner', 'rob', 'robinhood', 'robotech', 'rocknroll', 'rocky1',
    'rodeo', 'rolex', 'ronald', 'rouge', 'roxy', 'roy', 'ruby', 'ruthie',
    'sabrina', 'sakura', 'salasana', 'sally', 'sampson', 'samuel', 'sandra',
    'santa', 'sapphire', 'scarecrow', 'scarlet', 'scorpio', 'scott1',
    'scottie', 'scout', 'scruffy', 'scuba1', 'seattle', 'serena', 'sergey',
    'shanti', 'shark', 'shogun', 'simon', 'singer', 'skibum', 'skull',
    'skunk', 'skywalker', 'slacker', 'smashing', 'smiles', 'snowflake',
    'snowski', 'snuffy', 'soccer1', 'soleil', 'sonny', 'sound', 'spanky',
    'speedy', 'spider', 'spooky', 'stacey', 'star69', 'start', 'starter',
    'steven1', 'sting1', 'stinky', 'strawberry', 'stuart', 'sugar',
    'sunbird', 'sundance', 'superfly', 'suzanne', 'suzuki', 'swimmer',
    'swimming', 'system', 'taffy', 'tarzan', 'tbird', 'teddy', 'teddybear',
    'teflon', 'temporal', 'terminal', 'terry', 'the', 'theatre', 'thejudge',
    'thunder', 'thursday', 'time', 'tinker', 'toby', 'today', 'tokyo',
    'tootsie', 'tornado', 'tracy', 'tree', 'tricia', 'trident', 'trojan',
    'trout', 'truman', 'trumpet', 'tucker', 'turtle', 'tyler', 'utopia',
    'vader', 'val', 'valhalla', 'visa', 'voyager', 'warcraft', 'warlock',
    'warren', 'water', 'wayne', 'wendy', 'williams', 'willy', 'win95',
    'windsurf', 'winona', 'wolf', 'wolf1', 'woody', 'woofwoof', 'wrangler',
    'wright', 'www', 'xcountry', 'xfiles', 'xxxxxx', 'y', 'yankees', 'yoda',
    'yukon', 'yvonne', 'zebra', 'zenith', 'zigzag', 'zombie', 'zxc123',
    'zxcvb', 'zzz', '000000', '007007', '11111', '11111111', '1213', '1214',
    '1225', '123321', '1313', '1316', '1332', '1412', '1430', '171717',
    '1818', '181818', '1950', '1952', '1953', '1955', '1956', '1960',
    '1964', '1975', '1977', '1991', '1a2b3c', '1chris', '1kitty', '1qw23e',
    '2001', '2020', '2112', '22', '2200', '2252', '2kids', '3010', '3112',
    '3141', '333', '3533', '4055', '4444', '4788', '4854', '4runner',
    '5050', '5121', '54321', '55555', '57chevy', '6262', '6301', '6969',
    '7777777', '789456', '7dwarfs', '88888888', 'Abcdefg', 'Alexis',
    'Alpha', 'Animals', 'Ariel', 'BOSS', 'Bailey', 'Bastard', 'Beavis',
    'Bismillah', 'Bonzo', 'Booboo', 'Boston', 'Canucks', 'Cardinal',
    'Carol', 'Celtics', 'ChangeMe', 'Charlie', 'Chris', 'Computer',
    'Cougar', 'Creative', 'Curtis', 'Daniel', 'Darkman', 'Denise', 'Dragon',
    'Eagles', 'Elizabeth', 'Esther', 'Figaro', 'Fishing', 'Fortune',
    'Freddy', 'Front242', 'Gandalf', 'Geronimo', 'Gingers', 'Golden',
    'Goober', 'Gretel', 'HARLEY', 'Hacker', 'Hammer', 'Harley', 'Heather',
    'Henry', 'Hershey', 'Homer', 'Jackson', 'Janet', 'Jennifer', 'Jersey',
    'Jessica', 'Joanna', 'Johnson', 'Jordan', 'KILLER', 'Katie', 'Kitten',
    'Liberty', 'Lindsay', 'Lizard', 'Madeline', 'Margaret', 'Maxwell',
    'Mellon', 'Merlot', 'Metallic', 'Michel1', 'Money', 'Monster',
    'Montreal', 'Newton', 'Nicholas', 'Noriko', 'Paladin', 'Pamela',
    'Password', 'Peaches', 'Peanuts', 'Peter', 'Phoenix', 'Piglet',
    'Pookie', 'Princess', 'Purple', 'Rabbit', 'Raiders', 'Random',
    'Rebecca', 'Robert', 'Russell', 'Sammy', 'Saturn', 'Service', 'Shadow',
    'Sidekick', 'Skeeter', 'Smokey', 'Sparky', 'Speedy', 'Sterling',
    'Steven', 'Summer', 'Sunshine', 'Superman', 'Sverige', 'Swoosh',
    'Taylor', 'Theresa', 'Thomas', 'Thunder', 'Vernon', 'Victoria',
    'Vincent', 'Waterloo', 'Webster', 'Willow', 'Winnie', 'Wolverine',
    'Woodrow', 'World', 'aa', 'aaaa', 'aardvark', 'abbott', 'abcd123',
    'abcde', 'accord', 'active', 'acura', 'adg', 'admin', 'admin1',
    'adrock', 'aerobics', 'africa', 'agent', 'airborne', 'airwolf',
    'aki123', 'alfaro', 'ali', 'alicia', 'alien', 'aliens', 'alina',
    'aline', 'alison', 'allegro', 'allen', 'allstate', 'aloha', 'alpha1',
    'altamira', 'althea', 'altima', 'altima1', 'amanda1', 'amazing',
    'america', 'amour', 'anderson', 'andre', 'andrew!', 'andrew1',
    'andromed', 'angels', 'angie1', 'ann', 'anne', 'anneli', 'annie',
    'anything', 'apple1', 'apple2', 'applepie', 'april', 'aptiva', 'aqua',
    'aquarius', 'ariane', 'ariel', 'arlene', 'arrow', 'artemis', 'asdf1234',
    'asdf;lkj', 'asdfjkl', 'ashley1', 'ashraf', 'ashton', 'assmunch',
    'asterix', 'attila', 'autumn', 'avatar', 'ayelet', 'aylmer', 'babes',
    'bambi', 'baraka', 'barbie', 'barn', 'barney1', 'barnyard', 'barrett',
    'bart', 'bartman', 'bball', 'beaches', 'beanie', 'beans', 'beasty',
    'beauty', 'beavis1', 'bebe', 'becca', 'belgium', 'belize', 'belle',
    'belmont', 'benji', 'benson', 'beowulf', 'bernardo', 'berry', 'beryl',
    'best', 'beta', 'betacam', 'betsy', 'betty', 'bharat', 'bichon',
    'bigal', 'bigboss', 'bigred', 'biker', 'bilbo', 'bills', 'billy1',
    'bimmer', 'bioboy', 'biochem', 'birdie', 'birdy', 'birthday', 'biscuit',
    'bitter', 'biz', 'blackjack', 'blah', 'blanche', 'blinds', 'blitz',
    'blood', 'blowjob', 'blowme', 'blueeyes', 'bluejean', 'blues', 'boat',
    'bogart', 'bogey', 'bogus', 'bombay', 'boobie', 'boots', 'bootsie',
    'boulder', 'bourbon', 'boxer', 'boxers', 'bozo', 'brain', 'branch',
    'brandi', 'brent', 'brewster', 'bridge', 'britain', 'broker', 'bronco',
    'bronte', 'brooke', 'brother', 'bryan', 'bubble', 'bucks', 'buddha',
    'budgie', 'buffett', 'bugs', 'bulls', 'burns', 'burton', 'butterfly',
    'buzz', 'byron', 'c00per', 'calendar', 'calgary', 'calvin1', 'camay',
    'camel', 'camille', 'campbell', 'camping', 'cancer', 'canela', 'cannon',
    'car', 'carbon', 'carl', 'carnage', 'carolyn', 'carrot', 'cascade',
    'cat', 'catfish', 'cathy', 'catwoman', 'cecile', 'celica', 'cement',
    'cessna', 'chad', 'chainsaw', 'chameleon', 'chang', 'change', 'chantal',
    'charger', 'chat', 'cherry', 'chess', 'chiara', 'chiefs', 'china',
    'chinacat', 'chinook', 'chouette', 'chris123', 'christ1', 'christmas',
    'christopher', 'chronos', 'chuck', 'cicero', 'cindy1', 'cinema',
    'circuit', 'cirque', 'cirrus', 'civic', 'clapton', 'clarkson', 'class',
    'claude', 'claudel', 'cleo', 'cliff', 'clock', 'clueless', 'cobain',
    'cobra', 'cody', 'colette', 'college', 'color', 'colors', 'colt45',
    'comet', 'concept', 'concorde', 'confused', 'cool', 'coolbean', 'cora',
    'corky', 'cornflake', 'corvette', 'corwin', 'cosmo', 'country',
    'courier', 'cows', 'crescent', 'cross', 'crowley', 'crusader',
    'cthulhu', 'cuda', 'cunningham', 'cunt', 'cupcake', 'current',
    'cutlass', 'cynthia', 'daedalus', 'dagger', 'dagger1', 'daily', 'dale',
    'dammit', 'damogran', 'dana', 'dancer', 'daphne', 'darkstar', 'darren',
    'darryl', 'darwin', 'data1', 'datatrain', 'daytek', 'dead', 'deborah',
    'december', 'decker', 'deedee', 'deeznuts', 'def', 'delano', 'delete',
    'demon', 'denise', 'denny', 'desert', 'deskjet', 'detroit', 'devil',
    'devine', 'devon', 'dexter', 'dharma', 'dianne', 'diesel', 'dillweed',
    'dim', 'dipper', 'director', 'disco', 'dixie', 'dixon', 'doc',
    'dodgers', 'dogbert', 'doggy', 'doitnow', 'dollar', 'dolly',
    'dominique', 'domino', 'dontknow', 'doogie', 'doors', 'dork', 'doudou',
    'doug', 'downtown', 'dragon1', 'driver', 'dude', 'dudley', 'dutch',
    'dutchess', 'dwight', 'eagle1', 'easter', 'eastern', 'edith', 'edmund',
    'effie', 'eieio', 'eight', 'element', 'elina1', 'elissa', 'ella',
    'ellen', 'elliot', 'elsie', 'empire', 'engage', 'enigma', 'enterprise',
    'eric1', 'erin', 'ernie1', 'escort', 'escort1', 'estelle', 'eugene',
    'evelyn', 'excel', 'explore', 'eyal', 'faculty', 'fairview', 'family1',
    'fatboy', 'faust', 'felipe', 'fenris', 'ferguson', 'ferret', 'ferris',
    'finance', 'fireball', 'first', 'fishes', 'fishhead', 'fishie',
    'flanders', 'fleurs', 'flight', 'florida1', 'flowerpot', 'flute', 'fly',
    'flyboy', 'flyer', 'forward', 'franka', 'freddie', 'frederic', 'free',
    'freebird', 'freeman', 'frisco', 'fritz', 'froggie', 'froggies',
    'frogs', 'front242', 'frontier', 'fucku', 'fugazi', 'funguy', 'funtime',
    'future', 'fuzz', 'gabby', 'gaby', 'gaelic', 'gambler', 'games',
    'gammaphi', 'garcia', 'garfunkel', 'garth', 'gary', 'gaston', 'gateway',
    'gateway2', 'gator1', 'george1', 'georgia', 'german', 'germany1',
    'getout', 'ggeorge', 'ghost', 'gibbons', 'gibson', 'gigi', 'gilgamesh',
    'giselle', 'glider1', 'gmoney', 'goat', 'goblin', 'goblue', 'godiva',
    'goethe', 'gofish', 'gollum', 'gone', 'good', 'gramps', 'grandma',
    'gravis', 'gray', 'greed', 'greg', 'greg1', 'gremlin', 'greta',
    'gretzky', 'grizzly', 'grumpy', 'guess', 'guido', 'guitar1', 'gumby',
    'gustavo', 'h2opolo', 'haggis', 'haha', 'hailey', 'hal', 'halloween',
    'hallowell', 'hamid', 'hamilton', 'hamlet', 'hank', 'hanna', 'hanson',
    'happy123', 'happyday', 'hardcore', 'harley1', 'haro', 'harriet',
    'harris', 'harvard', 'hawk', 'hawkeye1', 'health', 'health1', 'heart',
    'heather1', 'heather2', 'hedgehog', 'heikki', 'helene', 'hello1',
    'hello123', 'hello8', 'hellohello', 'help123', 'helper', 'hermes',
    'heythere', 'highland', 'hilda', 'hillary', 'histoire', 'history',
    'hitler', 'hobbes', 'holiday', 'holly', 'homerj', 'honda1', 'hongkong',
    'hoosier', 'hootie', 'hope', 'horse', 'hosehead', 'hotrod', 'huang',
    'hudson', 'hugh', 'hugo', 'hummer', 'huskies', 'hydrogen', 'i',
    'ib6ub9', 'idiot', 'if6was9', 'iforget', 'ilmari', 'iloveu', 'impact',
    'indonesia', 'ingvar', 'insight', 'instruct', 'integral', 'iomega',
    'irina', 'iris', 'irmeli', 'isabelle', 'israel', 'italia', 'italy',
    'izzy', 'j0ker', 'j1l2t3', 'jackie1', 'jacob', 'jakey', 'james1',
    'jamesbond', 'jamie', 'jamjam', 'jan', 'jazz', 'jean', 'jedi',
    'jeepster', 'jeffrey1', 'jennie', 'jenny', 'jensen', 'jer', 'jesse',
    'jesse1', 'jester', 'jethro', 'jetta1', 'jimbob', 'jimi', 'jimmy',
    'joanie', 'joanna', 'joelle', 'john316', 'jordie', 'jorge', 'josee',
    'josh', 'journey', 'joy', 'joyce', 'jubilee', 'juhani', 'jules',
    'julia2', 'julien', 'juliet', 'jumbo', 'jump', 'junebug', 'juniper',
    'justdoit', 'justice4', 'kalamazo', 'kali', 'karin', 'karine', 'karma',
    'kat', 'kate', 'katerina', 'katie', 'katie1', 'kayla', 'kcin', 'keeper',
    'keller', 'kendall', 'kenny', 'kerala', 'kerrya', 'ketchup', 'khan',
    'kids', 'kings', 'kissa2', 'kissme', 'kitten', 'kittycat', 'kiwi',
    'kkkkkk', 'kleenex', 'kombat', 'kristi', 'kristine', 'lab1', 'labtec',
    'laddie', 'ladybug', 'lamer', 'lance', 'laser', 'laserjet', 'lassie1',
    'laurel', 'lawson', 'leader', 'leaf', 'leblanc', 'legal', 'leland',
    'lemon', 'leo', 'lester', 'letter', 'letters', 'lev', 'lexus1', 'libra',
    'life', 'lights', 'lima', 'lionel', 'lions', 'lissabon', 'little',
    'liz', 'lizzy', 'logger', 'logos', 'loislane', 'loki', 'lolita',
    'lonestar', 'longer', 'longhorn', 'looney', 'loren', 'lori', 'lorna',
    'loser', 'lost', 'lotus', 'lou', 'lovers', 'loveyou', 'lucia',
    'lucifer', 'lucky14', 'macha', 'macross', 'macse30', 'maddie', 'madmax',
    'madoka', 'magic1', 'magnum', 'maiden', 'maine', 'makeitso', 'mallard',
    'manageme', 'manson', 'manuel', 'marc', 'marcus', 'maria', 'marielle',
    'marine', 'marino', 'marshall', 'mart', 'martha', 'math', 'matti1',
    'mattingly', 'maxmax', 'meatloaf', 'mech', 'mechanic', 'medical',
    'megan', 'meister', 'melina', 'memphis', 'mercer', 'merde', 'mermaid',
    'merrill', 'miami', 'michal', 'michel', 'michigan', 'michou', 'mickel',
    'mickey1', 'microsoft', 'midvale', 'mikael', 'milano', 'miles',
    'millenium', 'million', 'minou', 'miranda', 'miriam', 'mission',
    'mmmmmm', 'mobile', 'mobydick', 'modem', 'mojo', 'monkey1', 'monroe',
    'montana', 'montana3', 'montrose', 'monty', 'moomoo', 'moonbeam',
    'morecats', 'morpheus', 'motor', 'motorola', 'movies', 'mowgli',
    'mozart', 'mulder1', 'munchkin', 'murray', 'muscle', 'mustang1',
    'nadia', 'nadine', 'napoleon', 'nation', 'national', 'neil', 'neko',
    'nesbit', 'nestle', 'neutrino', 'newaccount', 'newlife', 'newyork1',
    'nexus6', 'nichole', 'nicklaus', 'nightshadow', 'nightwind', 'nike',
    'nikita', 'nikki', 'nintendo', 'nisse', 'nokia', 'nomore', 'none1',
    'nopass', 'normal', 'norton', 'notta1', 'nouveau', 'novell', 'noway',
    'nugget', 'number9', 'numbers', 'nurse', 'nutmeg', 'oaxaca', 'obiwan',
    'obsession', 'ohshit', 'oicu812', 'omega', 'openup', 'orchid', 'oreo',
    'orlando', 'orville', 'otter', 'ozzy', 'paagal', 'packard', 'packers',
    'packrat', 'paint', 'paloma', 'pam', 'pancake', 'panic', 'papa',
    'paradigm', 'park', 'parola', 'parrot', 'partner', 'pascal', 'pass',
    'patches', 'patriots', 'paula', 'pauline', 'pavel', 'payton', 'peach',
    'peanuts', 'pedro1', 'peggy', 'pekka', 'perfect', 'performa', 'perry',
    'peterk', 'peterpan', 'phialpha', 'philips', 'phillips', 'phishy',
    'phone', 'piano1', 'pianoman', 'pianos', 'pierce', 'pigeon', 'pink',
    'pioneer', 'pipeline', 'piper1', 'pirate', 'pisces', 'plato', 'play',
    'playboy', 'pluto', 'poetic', 'poetry', 'pole', 'pontiac', 'pookey',
    'pope', 'popeye', 'prayer', 'precious', 'prelude', 'premier', 'print',
    'printing', 'prof', 'provider', 'puddin', 'pulsar', 'pussy', 'pussy1',
    'pyro', 'qqq111', 'quebec', 'qwer', 'qwert', 'qwerty12', 'qwertyui',
    'r0ger', 'rabbit1', 'racer', 'racerx', 'rachelle', 'racoon', 'radar',
    'rafiki', 'raleigh', 'ram', 'rambo', 'randy1', 'rasta1', 'ratio',
    'ravens', 'redcloud', 'redfish', 'redman', 'redskins', 'redwing',
    'redwood', 'reed', 'reggae', 'reggie', 'reliant', 'rene', 'renee',
    'renegade', 'rescue', 'revolution', 'rex', 'reznor', 'rhino',
    'rhjrjlbk', 'richard1', 'richards', 'richmond', 'riley', 'ripper',
    'ripple', 'rita', 'robby', 'roberts', 'robocop', 'robotics', 'roche',
    'rock', 'rocket1', 'rockie', 'rockon', 'roger1', 'rogers', 'roland',
    'rommel', 'roni', 'rookie', 'rootbeer', 'rosie', 'rossigno', 'rufus',
    'rugger', 'rush', 'rusty', 'ruthless', 'sabbath', 'sabina', 'safety',
    'safety1', 'saigon', 'saint', 'samIam', 'samiam', 'sammie', 'sammy',
    'samsam', 'sandi', 'sanjose', 'saphire', 'sarah1', 'saskia', 'sassy',
    'satori', 'saturday', 'saturn5', 'schnapps', 'science', 'scooby',
    'scoobydoo', 'scooter1', 'scorpion', 'scotch', 'scotty', 'scouts',
    'scuba', 'search', 'secret3', 'seeker', 'seoul', 'september', 'server',
    'services', 'seven7', 'sex', 'sexy', 'shaggy', 'shanghai', 'shanny',
    'shaolin', 'shasta', 'shayne', 'shazam', 'shelly', 'shelter', 'sherry',
    'ship', 'shirley', 'shorty', 'shotgun', 'sidney', 'sigmachi', 'signal',
    'signature', 'simba1', 'simsim', 'sinatra', 'sirius', 'skate', 'skip',
    'skipper1', 'skydive', 'skyler', 'slayer', 'sleepy', 'slick', 'slider',
    'slip', 'smegma', 'smile1', 'smiths', 'smitty', 'smoke', 'smurfy',
    'snakes', 'snapper', 'snoop', 'snow', 'sober1', 'solomon', 'sonics',
    'sony', 'sophia', 'space', 'sparks', 'spartan', 'spazz', 'sphynx',
    'spike1', 'spock', 'sponge', 'spoon', 'spot', 'sprocket', 'spurs',
    'squash', 'stan', 'starbuck', 'stargate', 'starlight', 'stars', 'steel',
    'steph1', 'stephi', 'steve1', 'stevens', 'stewart', 'sting', 'stivers',
    'stocks', 'stone', 'storage', 'stranger', 'strat', 'strato', 'stretch',
    'strong', 'stud', 'student2', 'studio', 'stumpy', 'sucker', 'suckme',
    'sue', 'sultan', 'summit', 'sunfire', 'sunset', 'super', 'superstar',
    'surfing', 'susan1', 'susanna', 'sutton', 'suzy', 'swanson', 'sweden',
    'sweetpea', 'sweety', 'swim', 'switzer', 'swordfish', 'system5',
    't-bone', 'tab', 'tabatha', 'tacobell', 'taiwan', 'talon', 'tamtam',
    'tanner', 'tapani', 'targas', 'target', 'tarheel', 'tasha', 'tata',
    'tattoo', 'tazdevil', 'tequila', 'terry1', 'test2', 'test3', 'tester',
    'testi', 'testtest', 'texas', 'thankyou', 'theend', 'thelorax',
    'thisisit', 'thompson', 'thorne', 'thrasher', 'tiger2', 'tightend',
    'tika', 'tim', 'timber', 'timothy', 'tinkerbell', 'tnt', 'tom', 'tool',
    'topcat', 'topher', 'toshiba', 'total', 'toto1', 'tototo', 'toucan',
    'transfer', 'transit', 'transport', 'trapper', 'trash', 'travis', 'tre',
    'treasure', 'trees', 'tricky', 'trish', 'triton', 'trombone', 'trophy',
    'trouble', 'trucker', 'tucson', 'tula', 'turbo', 'turbo2', 'twins',
    'tyler1', 'ultimate', 'unique', 'united', 'unity', 'unix', 'upsilon',
    'ursula', 'user1', 'vacation', 'valley', 'vampire', 'vanessa', 'vedder',
    'velo', 'venice', 'venus', 'vermont', 'vette', 'vicki', 'vicky',
    'victor1', 'vikram', 'vincent1', 'violet', 'violin', 'virago', 'virgil',
    'virginia', 'vision', 'visual', 'volcano', 'volley', 'voodoo', 'vortex',
    'waiting', 'walden', 'waldo', 'walleye', 'wanker', 'warner', 'water1',
    'wayne1', 'webmaster', 'webster', 'wedge', 'weezer', 'wendy1',
    'western', 'whale1', 'whit', 'white', 'whitney', 'whocares', 'whoville',
    'wibble', 'wildcat', 'will', 'william1', 'wilma', 'wind', 'window',
    'winniethepooh', 'wolfgang', 'wolverine', 'wombat1', 'wonder', 'word',
    'world', 'x-files', 'x-men', 'xanth', 'xxx123', 'xxxxxxxx', 'xyz',
    'yamaha', 'yankee', 'yogibear', 'yolanda', 'yomama', 'yvette',
    'zachary', 'zack', 'zebras', 'zepplin', 'zoltan', 'zoomer', 'zxc',
    'zxcvbn', '!@#$%^&', '00000000', '121212', '1234qwer', '123go',
    '131313', '13579', '1701d', '21122112', '369', '5555', '80486', '90210',
    '911', '99999999', '@#$%^&', 'ABC123', 'Abcdef', 'Asdfgh', 'Casio',
    'Changeme', 'FuckYou', 'Fuckyou', 'Gizmo', 'Hello', 'JSBach', 'Michel',
    'NCC1701', 'PPP', 'Qwert', 'Qwerty', 'Windows', 'Zxcvb', 'Zxcvbnm',
    'action', 'advil', 'allo', 'amelie', 'anaconda', 'angus', 'apollo13',
    'artist', 'aspen', 'ass', 'asshole', 'ath', 'benoit', 'bernard',
    'bernie', 'bigbird', 'bird', 'blizzard', 'bluesky', 'bonjour',
    'booster', 'byteme', 'caesar', 'cardinal', 'carolina', 'cats', 'cedic',
    'cesar', 'chandler', 'changeit', 'chapman', 'charlie1', 'chevy',
    'chiquita', 'chocolat', 'christia', 'christoph', 'classroom', 'cloclo',
    'coco', 'corrado', 'cougars', 'courtney', 'dasha', 'demo', 'dirk',
    'dolphins', 'dominic', 'donkey', 'doom2', 'dusty', 'e', 'energy',
    'fearless', 'fiction', 'forest', 'french1', 'fubar', 'gator', 'gilles',
    'glenn', 'go', 'gocougs', 'good-luck', 'graymail', 'guinness',
    'hilbert', 'hola', 'home', 'homebrew', 'hotdog', 'indian', 'jared',
    'jimbo', 'jkm', 'johnson', 'jojo', 'josie', 'judy', 'koko', 'kristin',
    'lloyd', 'lorraine', 'lulu', 'lynn', 'm1911a1', 'mac', 'macintosh',
    'mailer', 'mars', 'maxime', 'memory', 'meow', 'mimi', 'mirror', 'nat',
    'ne1410s', 'ne1469', 'ne14a69', 'nebraska', 'nemesis', 'network',
    'newcourt', 'nigel', 'niki', 'nite', 'notused', 'oatmeal', 'patton',
    'paul', 'pedro', 'planet', 'players', 'politics', 'pomme', 'portland',
    'praise', 'property', 'protel', 'psalms', 'qwaszx', 'raiders', 'rambo1',
    'rancid', 'ruth', 'sales', 'salut', 'scrooge', 'shawn', 'shelley',
    'skidoo', 'softball', 'spain', 'speedo', 'sports', 'sss', 'ssssss',
    'steele', 'steph', 'stephani', 'sunday', 'surf', 'sylvie', 'symbol',
    'tiffany', 'tigre', 'toronto', 'trixie', 'undead', 'valentin', 'velvet',
    'viking', 'walker', 'watson', 'young', 'zhongguo'];

function shuffle_lists(a, b) {
    var rv = [];
    var ii;
    for (ii = 0; ii < a.length && ii < b.length; ii++) {
        rv.push(a[ii]);
        rv.push(b[ii]);
    }
    return rv.concat(a.slice(ii), b.slice(ii));
}

function rmdups(list_of_strings) {
    var rv = [];
    var mymap = {};
    for (var ii = 0; ii < list_of_strings.length; ii++) {
        var str = list_of_strings[ii];
        if (!mymap[str]) {
            mymap[str] = 1;
            rv.push(str);
        }
    }
    return rv;
}

function password_tokens() {
    var tokens = [''].concat(common_passwords);
    const chars = ('1234567890 ' +
                   'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                   '!@#$%^&*()_-+=[]{}\\|:;"\',<.>/?`~' +
                   '\000\001\002\003\004\005\006\007' +
                   '\010\011\012\013\014\015\016\017' +
                   '\020\021\022\023\024\025\026\027' +
                   '\030\031\032\033\034\035\036\037').split('');
    return rmdups(shuffle_lists(tokens, chars));
}

function PasswordToken(string) {
    this.tok = string;
}

PasswordToken.prototype.probability = function(container) {
    return container.freq(this) / container.totalfreq();
}

PasswordToken.prototype.bits = function(container) {
    return Math.log(this.probability(container))/Math.log(0.5);
}

function map(func, alist) {
    var rv = [];
    for (var ii = 0; ii < alist.length; ii++) rv.push(func(alist[ii]));
    return rv;
}
                 
function sum(alist) {
    var rv = 0;
    for (var ii = 0; ii < alist.length; ii++) rv += alist[ii];
    return rv;
}

function TokenContainer(tokens) {
    this.tokens = tokens;
    this.freqs = {};
    this.by_first_char = {};
    for (var ii = 0; ii < tokens.length; ii++) {
        var tok = this.tokens[ii];
        this.freqs[tok.tok] = 1.0/(ii+1);

        var first_char = tok.tok.charAt(0); // returns '' if tok.tok == ''
        if (this.by_first_char[first_char] == null) {
            this.by_first_char[first_char] = [];
        }
        this.by_first_char[first_char].push(tok);
    }
}

TokenContainer.prototype.freq = function(token) {
    return this.freqs[token.tok];
}

TokenContainer.prototype.totalfreq = function() {
    var container = this;
    if (!this._totalfreq) {
        this._totalfreq = sum(map(function(tok) { return container.freq(tok) },
                                  this.tokens));
    }
    return this._totalfreq;
}

TokenContainer.prototype.dissect = function(astring) {
    var ii = 0;
    var rv = [];
    while (ii < astring.length) {
        var candidate_tokens = this.by_first_char[astring.charAt(ii)];
        var best_token = new PasswordToken('');
        for (var jj = 0; jj < candidate_tokens.length; jj++) {
            var token = candidate_tokens[jj];
            var len = token.tok.length;
            if (len >= best_token.tok.length) {
                var chunk = astring.slice(ii, ii + len);
                if (chunk == token.tok) best_token = token;
            }
        }
        rv.push(best_token);
        ii += best_token.tok.length;
    }
    rv.push(new PasswordToken(''));
    return rv;
}

TokenContainer.prototype.listbits = function(toklist) {
    var container = this;
    return sum(map(function(tok) { return tok.bits(container) }, toklist));
}

TokenContainer.prototype.password_bits = function(password) {
    var result = this.listbits(this.dissect(password));
    return result;
}

function show_token_list(toklist) {
    return map(function(tok) { return tok.tok }, toklist);
}

const service = function() {
    const estimator = new TokenContainer(map(function(tok) {
        return new PasswordToken(tok)
    }, password_tokens()));

    this.getPasswordEntropyBits = function(password) {
        // Derate the estimated entropy by a factor of 3 to partly
        // compensate for its dumb world model.
        return estimator.password_bits(password) / 3;
    }

    // This method implements the nsISupports interface.
    this.QueryInterface = function(iid) {
        if (iid.equals(XPI.IPasspetEntropy)) return this;
        if (iid.equals(XPI.nsISupports)) return this;
        throw XPR.NS_ERROR_NO_INTERFACE;
    };
};

