").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n});
diff --git a/js/mnemonic.js b/js/mnemonic.js
new file mode 100644
index 0000000..2f4c19f
--- /dev/null
+++ b/js/mnemonic.js
@@ -0,0 +1,256 @@
+/*
+ mnemonic.js : Converts between 4-byte aligned strings and a human-readable
+ sequence of words. Uses 1626 common words taken from wikipedia article:
+ http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/Contemporary_poetry
+ Originally written in python special for Electrum (lightweight Bitcoin client).
+ This version has been reimplemented in javascript and placed in public domain.
+*/
+
+function mn_encode(str) {
+ var out = [];
+ var n = mn_words.length;
+ for (var i = 0; i < str.length; i += 8) {
+ var x = parseInt(str.substr(i, 8), 16);
+ var w1 = (x % n);
+ var w2 = (Math.floor(x/n) + w1) % n;
+ var w3 = (Math.floor(Math.floor(x/n)/n) + w2) % n;
+ out = out.concat([mn_words[w1], mn_words[w2], mn_words[w3]]);
+ }
+ return out.join(' ');
+}
+
+function mn_mod(a, b) {
+ return a < 0 ? b + a : a % b;
+}
+
+function mn_decode(str) {
+ var out = '';
+ var n = mn_words.length;
+ str = str.replace(/^[ \r\n]+|[ \r\n ]+$/gm,'');
+ var wlist = str.split(/[ \r\n]+/);
+ for (var i = 0; i < wlist.length; i += 3) {
+ var w1 = mn_words.indexOf(wlist[i]);
+ var w2 = mn_words.indexOf(wlist[i+1]) % n;
+ var w3 = mn_words.indexOf(wlist[i+2]) % n;
+ var x = w1 + n * mn_mod((w2 - w1), n) + n * n * mn_mod((w3 - w2), n);
+ out += ('0000000' + x.toString(16)).slice(-8);
+ }
+ return out;
+}
+
+var mn_words = [
+ "like", "just", "love", "know", "never", "want", "time", "out", "there",
+ "make", "look", "eye", "down", "only", "think", "heart", "back", "then",
+ "into", "about", "more", "away", "still", "them", "take", "thing", "even",
+ "through", "long", "always", "world", "too", "friend", "tell", "try",
+ "hand", "thought", "over", "here", "other", "need", "smile", "again",
+ "much", "cry", "been", "night", "ever", "little", "said", "end", "some",
+ "those", "around", "mind", "people", "girl", "leave", "dream", "left",
+ "turn", "myself", "give", "nothing", "really", "off", "before",
+ "something", "find", "walk", "wish", "good", "once", "place", "ask",
+ "stop", "keep", "watch", "seem", "everything", "wait", "got", "yet",
+ "made", "remember", "start", "alone", "run", "hope", "maybe", "believe",
+ "body", "hate", "after", "close", "talk", "stand", "own", "each", "hurt",
+ "help", "home", "god", "soul", "new", "many", "two", "inside", "should",
+ "true", "first", "fear", "mean", "better", "play", "another", "gone",
+ "change", "use", "wonder", "someone", "hair", "cold", "open", "best",
+ "any", "behind", "happen", "water", "dark", "laugh", "stay", "forever",
+ "name", "work", "show", "sky", "break", "came", "deep", "door", "put",
+ "black", "together", "upon", "happy", "such", "great", "white", "matter",
+ "fill", "past", "please", "burn", "cause", "enough", "touch", "moment",
+ "soon", "voice", "scream", "anything", "stare", "sound", "red", "everyone",
+ "hide", "kiss", "truth", "death", "beautiful", "mine", "blood", "broken",
+ "very", "pass", "next", "forget", "tree", "wrong", "air", "mother",
+ "understand", "lip", "hit", "wall", "memory", "sleep", "free", "high",
+ "realize", "school", "might", "skin", "sweet", "perfect", "blue", "kill",
+ "breath", "dance", "against", "fly", "between", "grow", "strong", "under",
+ "listen", "bring", "sometimes", "speak", "pull", "person", "become",
+ "family", "begin", "ground", "real", "small", "father", "sure", "feet",
+ "rest", "young", "finally", "land", "across", "today", "different", "guy",
+ "line", "fire", "reason", "reach", "second", "slowly", "write", "eat",
+ "smell", "mouth", "step", "learn", "three", "floor", "promise", "breathe",
+ "darkness", "push", "earth", "guess", "save", "song", "above", "along",
+ "both", "color", "house", "almost", "sorry", "anymore", "brother", "okay",
+ "dear", "game", "fade", "already", "apart", "warm", "beauty", "heard",
+ "notice", "question", "shine", "began", "piece", "whole", "shadow",
+ "secret", "street", "within", "finger", "point", "morning", "whisper",
+ "child", "moon", "green", "story", "glass", "kid", "silence", "since",
+ "soft", "yourself", "empty", "shall", "angel", "answer", "baby", "bright",
+ "dad", "path", "worry", "hour", "drop", "follow", "power", "war", "half",
+ "flow", "heaven", "act", "chance", "fact", "least", "tired", "children",
+ "near", "quite", "afraid", "rise", "sea", "taste", "window", "cover",
+ "nice", "trust", "lot", "sad", "cool", "force", "peace", "return", "blind",
+ "easy", "ready", "roll", "rose", "drive", "held", "music", "beneath",
+ "hang", "mom", "paint", "emotion", "quiet", "clear", "cloud", "few",
+ "pretty", "bird", "outside", "paper", "picture", "front", "rock", "simple",
+ "anyone", "meant", "reality", "road", "sense", "waste", "bit", "leaf",
+ "thank", "happiness", "meet", "men", "smoke", "truly", "decide", "self",
+ "age", "book", "form", "alive", "carry", "escape", "damn", "instead",
+ "able", "ice", "minute", "throw", "catch", "leg", "ring", "course",
+ "goodbye", "lead", "poem", "sick", "corner", "desire", "known", "problem",
+ "remind", "shoulder", "suppose", "toward", "wave", "drink", "jump",
+ "woman", "pretend", "sister", "week", "human", "joy", "crack", "grey",
+ "pray", "surprise", "dry", "knee", "less", "search", "bleed", "caught",
+ "clean", "embrace", "future", "king", "son", "sorrow", "chest", "hug",
+ "remain", "sat", "worth", "blow", "daddy", "final", "parent", "tight",
+ "also", "create", "lonely", "safe", "cross", "dress", "evil", "silent",
+ "bone", "fate", "perhaps", "anger", "class", "scar", "snow", "tiny",
+ "tonight", "continue", "control", "dog", "edge", "mirror", "month",
+ "suddenly", "comfort", "given", "loud", "quickly", "gaze", "plan", "rush",
+ "stone", "town", "battle", "ignore", "spirit", "stood", "stupid", "yours",
+ "brown", "build", "dust", "hey", "kept", "pay", "phone", "twist",
+ "although", "ball", "beyond", "hidden", "nose", "taken", "fail", "float",
+ "pure", "somehow", "wash", "wrap", "angry", "cheek", "creature",
+ "forgotten", "heat", "rip", "single", "space", "special", "weak",
+ "whatever", "yell", "anyway", "blame", "job", "choose", "country", "curse",
+ "drift", "echo", "figure", "grew", "laughter", "neck", "suffer", "worse",
+ "yeah", "disappear", "foot", "forward", "knife", "mess", "somewhere",
+ "stomach", "storm", "beg", "idea", "lift", "offer", "breeze", "field",
+ "five", "often", "simply", "stuck", "win", "allow", "confuse", "enjoy",
+ "except", "flower", "seek", "strength", "calm", "grin", "gun", "heavy",
+ "hill", "large", "ocean", "shoe", "sigh", "straight", "summer", "tongue",
+ "accept", "crazy", "everyday", "exist", "grass", "mistake", "sent", "shut",
+ "surround", "table", "ache", "brain", "destroy", "heal", "nature", "shout",
+ "sign", "stain", "choice", "doubt", "glance", "glow", "mountain", "queen",
+ "stranger", "throat", "tomorrow", "city", "either", "fish", "flame",
+ "rather", "shape", "spin", "spread", "ash", "distance", "finish", "image",
+ "imagine", "important", "nobody", "shatter", "warmth", "became", "feed",
+ "flesh", "funny", "lust", "shirt", "trouble", "yellow", "attention",
+ "bare", "bite", "money", "protect", "amaze", "appear", "born", "choke",
+ "completely", "daughter", "fresh", "friendship", "gentle", "probably",
+ "six", "deserve", "expect", "grab", "middle", "nightmare", "river",
+ "thousand", "weight", "worst", "wound", "barely", "bottle", "cream",
+ "regret", "relationship", "stick", "test", "crush", "endless", "fault",
+ "itself", "rule", "spill", "art", "circle", "join", "kick", "mask",
+ "master", "passion", "quick", "raise", "smooth", "unless", "wander",
+ "actually", "broke", "chair", "deal", "favorite", "gift", "note", "number",
+ "sweat", "box", "chill", "clothes", "lady", "mark", "park", "poor",
+ "sadness", "tie", "animal", "belong", "brush", "consume", "dawn", "forest",
+ "innocent", "pen", "pride", "stream", "thick", "clay", "complete", "count",
+ "draw", "faith", "press", "silver", "struggle", "surface", "taught",
+ "teach", "wet", "bless", "chase", "climb", "enter", "letter", "melt",
+ "metal", "movie", "stretch", "swing", "vision", "wife", "beside", "crash",
+ "forgot", "guide", "haunt", "joke", "knock", "plant", "pour", "prove",
+ "reveal", "steal", "stuff", "trip", "wood", "wrist", "bother", "bottom",
+ "crawl", "crowd", "fix", "forgive", "frown", "grace", "loose", "lucky",
+ "party", "release", "surely", "survive", "teacher", "gently", "grip",
+ "speed", "suicide", "travel", "treat", "vein", "written", "cage", "chain",
+ "conversation", "date", "enemy", "however", "interest", "million", "page",
+ "pink", "proud", "sway", "themselves", "winter", "church", "cruel", "cup",
+ "demon", "experience", "freedom", "pair", "pop", "purpose", "respect",
+ "shoot", "softly", "state", "strange", "bar", "birth", "curl", "dirt",
+ "excuse", "lord", "lovely", "monster", "order", "pack", "pants", "pool",
+ "scene", "seven", "shame", "slide", "ugly", "among", "blade", "blonde",
+ "closet", "creek", "deny", "drug", "eternity", "gain", "grade", "handle",
+ "key", "linger", "pale", "prepare", "swallow", "swim", "tremble", "wheel",
+ "won", "cast", "cigarette", "claim", "college", "direction", "dirty",
+ "gather", "ghost", "hundred", "loss", "lung", "orange", "present", "swear",
+ "swirl", "twice", "wild", "bitter", "blanket", "doctor", "everywhere",
+ "flash", "grown", "knowledge", "numb", "pressure", "radio", "repeat",
+ "ruin", "spend", "unknown", "buy", "clock", "devil", "early", "false",
+ "fantasy", "pound", "precious", "refuse", "sheet", "teeth", "welcome",
+ "add", "ahead", "block", "bury", "caress", "content", "depth", "despite",
+ "distant", "marry", "purple", "threw", "whenever", "bomb", "dull",
+ "easily", "grasp", "hospital", "innocence", "normal", "receive", "reply",
+ "rhyme", "shade", "someday", "sword", "toe", "visit", "asleep", "bought",
+ "center", "consider", "flat", "hero", "history", "ink", "insane", "muscle",
+ "mystery", "pocket", "reflection", "shove", "silently", "smart", "soldier",
+ "spot", "stress", "train", "type", "view", "whether", "bus", "energy",
+ "explain", "holy", "hunger", "inch", "magic", "mix", "noise", "nowhere",
+ "prayer", "presence", "shock", "snap", "spider", "study", "thunder",
+ "trail", "admit", "agree", "bag", "bang", "bound", "butterfly", "cute",
+ "exactly", "explode", "familiar", "fold", "further", "pierce", "reflect",
+ "scent", "selfish", "sharp", "sink", "spring", "stumble", "universe",
+ "weep", "women", "wonderful", "action", "ancient", "attempt", "avoid",
+ "birthday", "branch", "chocolate", "core", "depress", "drunk",
+ "especially", "focus", "fruit", "honest", "match", "palm", "perfectly",
+ "pillow", "pity", "poison", "roar", "shift", "slightly", "thump", "truck",
+ "tune", "twenty", "unable", "wipe", "wrote", "coat", "constant", "dinner",
+ "drove", "egg", "eternal", "flight", "flood", "frame", "freak", "gasp",
+ "glad", "hollow", "motion", "peer", "plastic", "root", "screen", "season",
+ "sting", "strike", "team", "unlike", "victim", "volume", "warn", "weird",
+ "attack", "await", "awake", "built", "charm", "crave", "despair", "fought",
+ "grant", "grief", "horse", "limit", "message", "ripple", "sanity",
+ "scatter", "serve", "split", "string", "trick", "annoy", "blur", "boat",
+ "brave", "clearly", "cling", "connect", "fist", "forth", "imagination",
+ "iron", "jock", "judge", "lesson", "milk", "misery", "nail", "naked",
+ "ourselves", "poet", "possible", "princess", "sail", "size", "snake",
+ "society", "stroke", "torture", "toss", "trace", "wise", "bloom", "bullet",
+ "cell", "check", "cost", "darling", "during", "footstep", "fragile",
+ "hallway", "hardly", "horizon", "invisible", "journey", "midnight", "mud",
+ "nod", "pause", "relax", "shiver", "sudden", "value", "youth", "abuse",
+ "admire", "blink", "breast", "bruise", "constantly", "couple", "creep",
+ "curve", "difference", "dumb", "emptiness", "gotta", "honor", "plain",
+ "planet", "recall", "rub", "ship", "slam", "soar", "somebody", "tightly",
+ "weather", "adore", "approach", "bond", "bread", "burst", "candle",
+ "coffee", "cousin", "crime", "desert", "flutter", "frozen", "grand",
+ "heel", "hello", "language", "level", "movement", "pleasure", "powerful",
+ "random", "rhythm", "settle", "silly", "slap", "sort", "spoken", "steel",
+ "threaten", "tumble", "upset", "aside", "awkward", "bee", "blank", "board",
+ "button", "card", "carefully", "complain", "crap", "deeply", "discover",
+ "drag", "dread", "effort", "entire", "fairy", "giant", "gotten", "greet",
+ "illusion", "jeans", "leap", "liquid", "march", "mend", "nervous", "nine",
+ "replace", "rope", "spine", "stole", "terror", "accident", "apple",
+ "balance", "boom", "childhood", "collect", "demand", "depression",
+ "eventually", "faint", "glare", "goal", "group", "honey", "kitchen",
+ "laid", "limb", "machine", "mere", "mold", "murder", "nerve", "painful",
+ "poetry", "prince", "rabbit", "shelter", "shore", "shower", "soothe",
+ "stair", "steady", "sunlight", "tangle", "tease", "treasure", "uncle",
+ "begun", "bliss", "canvas", "cheer", "claw", "clutch", "commit", "crimson",
+ "crystal", "delight", "doll", "existence", "express", "fog", "football",
+ "gay", "goose", "guard", "hatred", "illuminate", "mass", "math", "mourn",
+ "rich", "rough", "skip", "stir", "student", "style", "support", "thorn",
+ "tough", "yard", "yearn", "yesterday", "advice", "appreciate", "autumn",
+ "bank", "beam", "bowl", "capture", "carve", "collapse", "confusion",
+ "creation", "dove", "feather", "girlfriend", "glory", "government",
+ "harsh", "hop", "inner", "loser", "moonlight", "neighbor", "neither",
+ "peach", "pig", "praise", "screw", "shield", "shimmer", "sneak", "stab",
+ "subject", "throughout", "thrown", "tower", "twirl", "wow", "army",
+ "arrive", "bathroom", "bump", "cease", "cookie", "couch", "courage", "dim",
+ "guilt", "howl", "hum", "husband", "insult", "led", "lunch", "mock",
+ "mostly", "natural", "nearly", "needle", "nerd", "peaceful", "perfection",
+ "pile", "price", "remove", "roam", "sanctuary", "serious", "shiny",
+ "shook", "sob", "stolen", "tap", "vain", "void", "warrior", "wrinkle",
+ "affection", "apologize", "blossom", "bounce", "bridge", "cheap",
+ "crumble", "decision", "descend", "desperately", "dig", "dot", "flip",
+ "frighten", "heartbeat", "huge", "lazy", "lick", "odd", "opinion",
+ "process", "puzzle", "quietly", "retreat", "score", "sentence", "separate",
+ "situation", "skill", "soak", "square", "stray", "taint", "task", "tide",
+ "underneath", "veil", "whistle", "anywhere", "bedroom", "bid", "bloody",
+ "burden", "careful", "compare", "concern", "curtain", "decay", "defeat",
+ "describe", "double", "dreamer", "driver", "dwell", "evening", "flare",
+ "flicker", "grandma", "guitar", "harm", "horrible", "hungry", "indeed",
+ "lace", "melody", "monkey", "nation", "object", "obviously", "rainbow",
+ "salt", "scratch", "shown", "shy", "stage", "stun", "third", "tickle",
+ "useless", "weakness", "worship", "worthless", "afternoon", "beard",
+ "boyfriend", "bubble", "busy", "certain", "chin", "concrete", "desk",
+ "diamond", "doom", "drawn", "due", "felicity", "freeze", "frost", "garden",
+ "glide", "harmony", "hopefully", "hunt", "jealous", "lightning", "mama",
+ "mercy", "peel", "physical", "position", "pulse", "punch", "quit", "rant",
+ "respond", "salty", "sane", "satisfy", "savior", "sheep", "slept",
+ "social", "sport", "tuck", "utter", "valley", "wolf", "aim", "alas",
+ "alter", "arrow", "awaken", "beaten", "belief", "brand", "ceiling",
+ "cheese", "clue", "confidence", "connection", "daily", "disguise", "eager",
+ "erase", "essence", "everytime", "expression", "fan", "flag", "flirt",
+ "foul", "fur", "giggle", "glorious", "ignorance", "law", "lifeless",
+ "measure", "mighty", "muse", "north", "opposite", "paradise", "patience",
+ "patient", "pencil", "petal", "plate", "ponder", "possibly", "practice",
+ "slice", "spell", "stock", "strife", "strip", "suffocate", "suit",
+ "tender", "tool", "trade", "velvet", "verse", "waist", "witch", "aunt",
+ "bench", "bold", "cap", "certainly", "click", "companion", "creator",
+ "dart", "delicate", "determine", "dish", "dragon", "drama", "drum", "dude",
+ "everybody", "feast", "forehead", "former", "fright", "fully", "gas",
+ "hook", "hurl", "invite", "juice", "manage", "moral", "possess", "raw",
+ "rebel", "royal", "scale", "scary", "several", "slight", "stubborn",
+ "swell", "talent", "tea", "terrible", "thread", "torment", "trickle",
+ "usually", "vast", "violence", "weave", "acid", "agony", "ashamed", "awe",
+ "belly", "blend", "blush", "character", "cheat", "common", "company",
+ "coward", "creak", "danger", "deadly", "defense", "define", "depend",
+ "desperate", "destination", "dew", "duck", "dusty", "embarrass", "engine",
+ "example", "explore", "foe", "freely", "frustrate", "generation", "glove",
+ "guilty", "health", "hurry", "idiot", "impossible", "inhale", "jaw",
+ "kingdom", "mention", "mist", "moan", "mumble", "mutter", "observe", "ode",
+ "pathetic", "pattern", "pie", "prefer", "puff", "rape", "rare", "revenge",
+ "rude", "scrape", "spiral", "squeeze", "strain", "sunset", "suspend",
+ "sympathy", "thigh", "throne", "total", "unseen", "weapon", "weary"
+];
diff --git a/js/qrcode.js b/js/qrcode.js
new file mode 100644
index 0000000..c80e817
--- /dev/null
+++ b/js/qrcode.js
@@ -0,0 +1,1634 @@
+//---------------------------------------------------------------------
+//
+// QR Code Generator for JavaScript
+//
+// Copyright (c) 2009 Kazuhiko Arase
+//
+// URL: http://www.d-project.com/
+//
+// Licensed under the MIT license:
+// http://www.opensource.org/licenses/mit-license.php
+//
+// The word 'QR Code' is registered trademark of
+// DENSO WAVE INCORPORATED
+// http://www.denso-wave.com/qrcode/faqpatent-e.html
+//
+//---------------------------------------------------------------------
+
+var qrcode = function() {
+
+ //---------------------------------------------------------------------
+ // qrcode
+ //---------------------------------------------------------------------
+
+ /**
+ * qrcode
+ * @param typeNumber 1 to 10
+ * @param errorCorrectLevel 'L','M','Q','H'
+ */
+ var qrcode = function(typeNumber, errorCorrectLevel) {
+
+ var PAD0 = 0xEC;
+ var PAD1 = 0x11;
+
+ var _typeNumber = typeNumber;
+ var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
+ var _modules = null;
+ var _moduleCount = 0;
+ var _dataCache = null;
+ var _dataList = new Array();
+
+ var _this = {};
+
+ var makeImpl = function(test, maskPattern) {
+
+ _moduleCount = _typeNumber * 4 + 17;
+ _modules = function(moduleCount) {
+ var modules = new Array(moduleCount);
+ for (var row = 0; row < moduleCount; row += 1) {
+ modules[row] = new Array(moduleCount);
+ for (var col = 0; col < moduleCount; col += 1) {
+ modules[row][col] = null;
+ }
+ }
+ return modules;
+ }(_moduleCount);
+
+ setupPositionProbePattern(0, 0);
+ setupPositionProbePattern(_moduleCount - 7, 0);
+ setupPositionProbePattern(0, _moduleCount - 7);
+ setupPositionAdjustPattern();
+ setupTimingPattern();
+ setupTypeInfo(test, maskPattern);
+
+ if (_typeNumber >= 7) {
+ setupTypeNumber(test);
+ }
+
+ if (_dataCache == null) {
+ _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
+ }
+
+ mapData(_dataCache, maskPattern);
+ };
+
+ var setupPositionProbePattern = function(row, col) {
+
+ for (var r = -1; r <= 7; r += 1) {
+
+ if (row + r <= -1 || _moduleCount <= row + r) continue;
+
+ for (var c = -1; c <= 7; c += 1) {
+
+ if (col + c <= -1 || _moduleCount <= col + c) continue;
+
+ if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
+ || (0 <= c && c <= 6 && (r == 0 || r == 6) )
+ || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
+ _modules[row + r][col + c] = true;
+ } else {
+ _modules[row + r][col + c] = false;
+ }
+ }
+ }
+ };
+
+ var getBestMaskPattern = function() {
+
+ var minLostPoint = 0;
+ var pattern = 0;
+
+ for (var i = 0; i < 8; i += 1) {
+
+ makeImpl(true, i);
+
+ var lostPoint = QRUtil.getLostPoint(_this);
+
+ if (i == 0 || minLostPoint > lostPoint) {
+ minLostPoint = lostPoint;
+ pattern = i;
+ }
+ }
+
+ return pattern;
+ };
+
+ var setupTimingPattern = function() {
+
+ for (var r = 8; r < _moduleCount - 8; r += 1) {
+ if (_modules[r][6] != null) {
+ continue;
+ }
+ _modules[r][6] = (r % 2 == 0);
+ }
+
+ for (var c = 8; c < _moduleCount - 8; c += 1) {
+ if (_modules[6][c] != null) {
+ continue;
+ }
+ _modules[6][c] = (c % 2 == 0);
+ }
+ };
+
+ var setupPositionAdjustPattern = function() {
+
+ var pos = QRUtil.getPatternPosition(_typeNumber);
+
+ for (var i = 0; i < pos.length; i += 1) {
+
+ for (var j = 0; j < pos.length; j += 1) {
+
+ var row = pos[i];
+ var col = pos[j];
+
+ if (_modules[row][col] != null) {
+ continue;
+ }
+
+ for (var r = -2; r <= 2; r += 1) {
+
+ for (var c = -2; c <= 2; c += 1) {
+
+ if (r == -2 || r == 2 || c == -2 || c == 2
+ || (r == 0 && c == 0) ) {
+ _modules[row + r][col + c] = true;
+ } else {
+ _modules[row + r][col + c] = false;
+ }
+ }
+ }
+ }
+ }
+ };
+
+ var setupTypeNumber = function(test) {
+
+ var bits = QRUtil.getBCHTypeNumber(_typeNumber);
+
+ for (var i = 0; i < 18; i += 1) {
+ var mod = (!test && ( (bits >> i) & 1) == 1);
+ _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
+ }
+
+ for (var i = 0; i < 18; i += 1) {
+ var mod = (!test && ( (bits >> i) & 1) == 1);
+ _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+ }
+ };
+
+ var setupTypeInfo = function(test, maskPattern) {
+
+ var data = (_errorCorrectLevel << 3) | maskPattern;
+ var bits = QRUtil.getBCHTypeInfo(data);
+
+ // vertical
+ for (var i = 0; i < 15; i += 1) {
+
+ var mod = (!test && ( (bits >> i) & 1) == 1);
+
+ if (i < 6) {
+ _modules[i][8] = mod;
+ } else if (i < 8) {
+ _modules[i + 1][8] = mod;
+ } else {
+ _modules[_moduleCount - 15 + i][8] = mod;
+ }
+ }
+
+ // horizontal
+ for (var i = 0; i < 15; i += 1) {
+
+ var mod = (!test && ( (bits >> i) & 1) == 1);
+
+ if (i < 8) {
+ _modules[8][_moduleCount - i - 1] = mod;
+ } else if (i < 9) {
+ _modules[8][15 - i - 1 + 1] = mod;
+ } else {
+ _modules[8][15 - i - 1] = mod;
+ }
+ }
+
+ // fixed module
+ _modules[_moduleCount - 8][8] = (!test);
+ };
+
+ var mapData = function(data, maskPattern) {
+
+ var inc = -1;
+ var row = _moduleCount - 1;
+ var bitIndex = 7;
+ var byteIndex = 0;
+ var maskFunc = QRUtil.getMaskFunction(maskPattern);
+
+ for (var col = _moduleCount - 1; col > 0; col -= 2) {
+
+ if (col == 6) col -= 1;
+
+ while (true) {
+
+ for (var c = 0; c < 2; c += 1) {
+
+ if (_modules[row][col - c] == null) {
+
+ var dark = false;
+
+ if (byteIndex < data.length) {
+ dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
+ }
+
+ var mask = maskFunc(row, col - c);
+
+ if (mask) {
+ dark = !dark;
+ }
+
+ _modules[row][col - c] = dark;
+ bitIndex -= 1;
+
+ if (bitIndex == -1) {
+ byteIndex += 1;
+ bitIndex = 7;
+ }
+ }
+ }
+
+ row += inc;
+
+ if (row < 0 || _moduleCount <= row) {
+ row -= inc;
+ inc = -inc;
+ break;
+ }
+ }
+ }
+ };
+
+ var createBytes = function(buffer, rsBlocks) {
+
+ var offset = 0;
+
+ var maxDcCount = 0;
+ var maxEcCount = 0;
+
+ var dcdata = new Array(rsBlocks.length);
+ var ecdata = new Array(rsBlocks.length);
+
+ for (var r = 0; r < rsBlocks.length; r += 1) {
+
+ var dcCount = rsBlocks[r].dataCount;
+ var ecCount = rsBlocks[r].totalCount - dcCount;
+
+ maxDcCount = Math.max(maxDcCount, dcCount);
+ maxEcCount = Math.max(maxEcCount, ecCount);
+
+ dcdata[r] = new Array(dcCount);
+
+ for (var i = 0; i < dcdata[r].length; i += 1) {
+ dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
+ }
+ offset += dcCount;
+
+ var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
+ var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
+
+ var modPoly = rawPoly.mod(rsPoly);
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
+ for (var i = 0; i < ecdata[r].length; i += 1) {
+ var modIndex = i + modPoly.getLength() - ecdata[r].length;
+ ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0;
+ }
+ }
+
+ var totalCodeCount = 0;
+ for (var i = 0; i < rsBlocks.length; i += 1) {
+ totalCodeCount += rsBlocks[i].totalCount;
+ }
+
+ var data = new Array(totalCodeCount);
+ var index = 0;
+
+ for (var i = 0; i < maxDcCount; i += 1) {
+ for (var r = 0; r < rsBlocks.length; r += 1) {
+ if (i < dcdata[r].length) {
+ data[index] = dcdata[r][i];
+ index += 1;
+ }
+ }
+ }
+
+ for (var i = 0; i < maxEcCount; i += 1) {
+ for (var r = 0; r < rsBlocks.length; r += 1) {
+ if (i < ecdata[r].length) {
+ data[index] = ecdata[r][i];
+ index += 1;
+ }
+ }
+ }
+
+ return data;
+ };
+
+ var createData = function(typeNumber, errorCorrectLevel, dataList) {
+
+ var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
+
+ var buffer = qrBitBuffer();
+
+ for (var i = 0; i < dataList.length; i += 1) {
+ var data = dataList[i];
+ buffer.put(data.getMode(), 4);
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
+ data.write(buffer);
+ }
+
+ // calc num max data.
+ var totalDataCount = 0;
+ for (var i = 0; i < rsBlocks.length; i += 1) {
+ totalDataCount += rsBlocks[i].dataCount;
+ }
+
+ if (buffer.getLengthInBits() > totalDataCount * 8) {
+ throw new Error('code length overflow. ('
+ + buffer.getLengthInBits()
+ + '>'
+ + totalDataCount * 8
+ + ')');
+ }
+
+ // end code
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
+ buffer.put(0, 4);
+ }
+
+ // padding
+ while (buffer.getLengthInBits() % 8 != 0) {
+ buffer.putBit(false);
+ }
+
+ // padding
+ while (true) {
+
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(PAD0, 8);
+
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(PAD1, 8);
+ }
+
+ return createBytes(buffer, rsBlocks);
+ };
+
+ _this.addData = function(data) {
+ var newData = qr8BitByte(data);
+ _dataList.push(newData);
+ _dataCache = null;
+ };
+
+ _this.isDark = function(row, col) {
+ if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
+ throw new Error(row + ',' + col);
+ }
+ return _modules[row][col];
+ };
+
+ _this.getModuleCount = function() {
+ return _moduleCount;
+ };
+
+ _this.make = function() {
+ makeImpl(false, getBestMaskPattern() );
+ };
+
+ _this.createTableTag = function(cellSize, margin) {
+
+ cellSize = cellSize || 2;
+ margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
+
+ var qrHtml = '';
+
+ qrHtml += '
';
+ qrHtml += '';
+
+ for (var r = 0; r < _this.getModuleCount(); r += 1) {
+
+ qrHtml += '';
+
+ for (var c = 0; c < _this.getModuleCount(); c += 1) {
+ qrHtml += ' | ';
+ }
+
+ qrHtml += '
';
+ }
+
+ qrHtml += '';
+ qrHtml += '
';
+
+ return qrHtml;
+ };
+
+ _this.createImgTag = function(cellSize, margin) {
+
+ cellSize = cellSize || 2;
+ margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
+
+ var size = _this.getModuleCount() * cellSize + margin * 2;
+ var min = margin;
+ var max = size - margin;
+
+ return createImgTag(size, size, function(x, y) {
+ if (min <= x && x < max && min <= y && y < max) {
+ var c = Math.floor( (x - min) / cellSize);
+ var r = Math.floor( (y - min) / cellSize);
+ return _this.isDark(r, c)? 0 : 1;
+ } else {
+ return 1;
+ }
+ } );
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // qrcode.stringToBytes
+ //---------------------------------------------------------------------
+
+ qrcode.stringToBytes = function(s) {
+ var bytes = new Array();
+ for (var i = 0; i < s.length; i += 1) {
+ var c = s.charCodeAt(i);
+ bytes.push(c & 0xff);
+ }
+ return bytes;
+ };
+
+ //---------------------------------------------------------------------
+ // qrcode.createStringToBytes
+ //---------------------------------------------------------------------
+
+ /**
+ * @param unicodeData base64 string of byte array.
+ * [16bit Unicode],[16bit Bytes], ...
+ * @param numChars
+ */
+ qrcode.createStringToBytes = function(unicodeData, numChars) {
+
+ // create conversion map.
+
+ var unicodeMap = function() {
+
+ var bin = base64DecodeInputStream(unicodeData);
+ var read = function() {
+ var b = bin.read();
+ if (b == -1) throw new Error();
+ return b;
+ };
+
+ var count = 0;
+ var unicodeMap = {};
+ while (true) {
+ var b0 = bin.read();
+ if (b0 == -1) break;
+ var b1 = read();
+ var b2 = read();
+ var b3 = read();
+ var k = String.fromCharCode( (b0 << 8) | b1);
+ var v = (b2 << 8) | b3;
+ unicodeMap[k] = v;
+ count += 1;
+ }
+ if (count != numChars) {
+ throw new Error(count + ' != ' + numChars);
+ }
+
+ return unicodeMap;
+ }();
+
+ var unknownChar = '?'.charCodeAt(0);
+
+ return function(s) {
+ var bytes = new Array();
+ for (var i = 0; i < s.length; i += 1) {
+ var c = s.charCodeAt(i);
+ if (c < 128) {
+ bytes.push(c);
+ } else {
+ var b = unicodeMap[s.charAt(i)];
+ if (typeof b == 'number') {
+ if ( (b & 0xff) == b) {
+ // 1byte
+ bytes.push(b);
+ } else {
+ // 2bytes
+ bytes.push(b >>> 8);
+ bytes.push(b & 0xff);
+ }
+ } else {
+ bytes.push(unknownChar);
+ }
+ }
+ }
+ return bytes;
+ };
+ };
+
+ //---------------------------------------------------------------------
+ // QRMode
+ //---------------------------------------------------------------------
+
+ var QRMode = {
+ MODE_NUMBER : 1 << 0,
+ MODE_ALPHA_NUM : 1 << 1,
+ MODE_8BIT_BYTE : 1 << 2,
+ MODE_KANJI : 1 << 3
+ };
+
+ //---------------------------------------------------------------------
+ // QRErrorCorrectLevel
+ //---------------------------------------------------------------------
+
+ var QRErrorCorrectLevel = {
+ L : 1,
+ M : 0,
+ Q : 3,
+ H : 2
+ };
+
+ //---------------------------------------------------------------------
+ // QRMaskPattern
+ //---------------------------------------------------------------------
+
+ var QRMaskPattern = {
+ PATTERN000 : 0,
+ PATTERN001 : 1,
+ PATTERN010 : 2,
+ PATTERN011 : 3,
+ PATTERN100 : 4,
+ PATTERN101 : 5,
+ PATTERN110 : 6,
+ PATTERN111 : 7
+ };
+
+ //---------------------------------------------------------------------
+ // QRUtil
+ //---------------------------------------------------------------------
+
+ var QRUtil = function() {
+
+ var PATTERN_POSITION_TABLE = [
+ [],
+ [6, 18],
+ [6, 22],
+ [6, 26],
+ [6, 30],
+ [6, 34],
+ [6, 22, 38],
+ [6, 24, 42],
+ [6, 26, 46],
+ [6, 28, 50],
+ [6, 30, 54],
+ [6, 32, 58],
+ [6, 34, 62],
+ [6, 26, 46, 66],
+ [6, 26, 48, 70],
+ [6, 26, 50, 74],
+ [6, 30, 54, 78],
+ [6, 30, 56, 82],
+ [6, 30, 58, 86],
+ [6, 34, 62, 90],
+ [6, 28, 50, 72, 94],
+ [6, 26, 50, 74, 98],
+ [6, 30, 54, 78, 102],
+ [6, 28, 54, 80, 106],
+ [6, 32, 58, 84, 110],
+ [6, 30, 58, 86, 114],
+ [6, 34, 62, 90, 118],
+ [6, 26, 50, 74, 98, 122],
+ [6, 30, 54, 78, 102, 126],
+ [6, 26, 52, 78, 104, 130],
+ [6, 30, 56, 82, 108, 134],
+ [6, 34, 60, 86, 112, 138],
+ [6, 30, 58, 86, 114, 142],
+ [6, 34, 62, 90, 118, 146],
+ [6, 30, 54, 78, 102, 126, 150],
+ [6, 24, 50, 76, 102, 128, 154],
+ [6, 28, 54, 80, 106, 132, 158],
+ [6, 32, 58, 84, 110, 136, 162],
+ [6, 26, 54, 82, 110, 138, 166],
+ [6, 30, 58, 86, 114, 142, 170]
+ ];
+ var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
+ var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
+ var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
+
+ var _this = {};
+
+ var getBCHDigit = function(data) {
+ var digit = 0;
+ while (data != 0) {
+ digit += 1;
+ data >>>= 1;
+ }
+ return digit;
+ };
+
+ _this.getBCHTypeInfo = function(data) {
+ var d = data << 10;
+ while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
+ d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
+ }
+ return ( (data << 10) | d) ^ G15_MASK;
+ };
+
+ _this.getBCHTypeNumber = function(data) {
+ var d = data << 12;
+ while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
+ d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
+ }
+ return (data << 12) | d;
+ };
+
+ _this.getPatternPosition = function(typeNumber) {
+ return PATTERN_POSITION_TABLE[typeNumber - 1];
+ };
+
+ _this.getMaskFunction = function(maskPattern) {
+
+ switch (maskPattern) {
+
+ case QRMaskPattern.PATTERN000 :
+ return function(i, j) { return (i + j) % 2 == 0; };
+ case QRMaskPattern.PATTERN001 :
+ return function(i, j) { return i % 2 == 0; };
+ case QRMaskPattern.PATTERN010 :
+ return function(i, j) { return j % 3 == 0; };
+ case QRMaskPattern.PATTERN011 :
+ return function(i, j) { return (i + j) % 3 == 0; };
+ case QRMaskPattern.PATTERN100 :
+ return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
+ case QRMaskPattern.PATTERN101 :
+ return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
+ case QRMaskPattern.PATTERN110 :
+ return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
+ case QRMaskPattern.PATTERN111 :
+ return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
+
+ default :
+ throw new Error('bad maskPattern:' + maskPattern);
+ }
+ };
+
+ _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
+ var a = qrPolynomial([1], 0);
+ for (var i = 0; i < errorCorrectLength; i += 1) {
+ a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
+ }
+ return a;
+ };
+
+ _this.getLengthInBits = function(mode, type) {
+
+ if (1 <= type && type < 10) {
+
+ // 1 - 9
+
+ switch(mode) {
+ case QRMode.MODE_NUMBER : return 10;
+ case QRMode.MODE_ALPHA_NUM : return 9;
+ case QRMode.MODE_8BIT_BYTE : return 8;
+ case QRMode.MODE_KANJI : return 8;
+ default :
+ throw new Error('mode:' + mode);
+ }
+
+ } else if (type < 27) {
+
+ // 10 - 26
+
+ switch(mode) {
+ case QRMode.MODE_NUMBER : return 12;
+ case QRMode.MODE_ALPHA_NUM : return 11;
+ case QRMode.MODE_8BIT_BYTE : return 16;
+ case QRMode.MODE_KANJI : return 10;
+ default :
+ throw new Error('mode:' + mode);
+ }
+
+ } else if (type < 41) {
+
+ // 27 - 40
+
+ switch(mode) {
+ case QRMode.MODE_NUMBER : return 14;
+ case QRMode.MODE_ALPHA_NUM : return 13;
+ case QRMode.MODE_8BIT_BYTE : return 16;
+ case QRMode.MODE_KANJI : return 12;
+ default :
+ throw new Error('mode:' + mode);
+ }
+
+ } else {
+ throw new Error('type:' + type);
+ }
+ };
+
+ _this.getLostPoint = function(qrcode) {
+
+ var moduleCount = qrcode.getModuleCount();
+
+ var lostPoint = 0;
+
+ // LEVEL1
+
+ for (var row = 0; row < moduleCount; row += 1) {
+ for (var col = 0; col < moduleCount; col += 1) {
+
+ var sameCount = 0;
+ var dark = qrcode.isDark(row, col);
+
+ for (var r = -1; r <= 1; r += 1) {
+
+ if (row + r < 0 || moduleCount <= row + r) {
+ continue;
+ }
+
+ for (var c = -1; c <= 1; c += 1) {
+
+ if (col + c < 0 || moduleCount <= col + c) {
+ continue;
+ }
+
+ if (r == 0 && c == 0) {
+ continue;
+ }
+
+ if (dark == qrcode.isDark(row + r, col + c) ) {
+ sameCount += 1;
+ }
+ }
+ }
+
+ if (sameCount > 5) {
+ lostPoint += (3 + sameCount - 5);
+ }
+ }
+ };
+
+ // LEVEL2
+
+ for (var row = 0; row < moduleCount - 1; row += 1) {
+ for (var col = 0; col < moduleCount - 1; col += 1) {
+ var count = 0;
+ if (qrcode.isDark(row, col) ) count += 1;
+ if (qrcode.isDark(row + 1, col) ) count += 1;
+ if (qrcode.isDark(row, col + 1) ) count += 1;
+ if (qrcode.isDark(row + 1, col + 1) ) count += 1;
+ if (count == 0 || count == 4) {
+ lostPoint += 3;
+ }
+ }
+ }
+
+ // LEVEL3
+
+ for (var row = 0; row < moduleCount; row += 1) {
+ for (var col = 0; col < moduleCount - 6; col += 1) {
+ if (qrcode.isDark(row, col)
+ && !qrcode.isDark(row, col + 1)
+ && qrcode.isDark(row, col + 2)
+ && qrcode.isDark(row, col + 3)
+ && qrcode.isDark(row, col + 4)
+ && !qrcode.isDark(row, col + 5)
+ && qrcode.isDark(row, col + 6) ) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ for (var col = 0; col < moduleCount; col += 1) {
+ for (var row = 0; row < moduleCount - 6; row += 1) {
+ if (qrcode.isDark(row, col)
+ && !qrcode.isDark(row + 1, col)
+ && qrcode.isDark(row + 2, col)
+ && qrcode.isDark(row + 3, col)
+ && qrcode.isDark(row + 4, col)
+ && !qrcode.isDark(row + 5, col)
+ && qrcode.isDark(row + 6, col) ) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ // LEVEL4
+
+ var darkCount = 0;
+
+ for (var col = 0; col < moduleCount; col += 1) {
+ for (var row = 0; row < moduleCount; row += 1) {
+ if (qrcode.isDark(row, col) ) {
+ darkCount += 1;
+ }
+ }
+ }
+
+ var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+ lostPoint += ratio * 10;
+
+ return lostPoint;
+ };
+
+ return _this;
+ }();
+
+ //---------------------------------------------------------------------
+ // QRMath
+ //---------------------------------------------------------------------
+
+ var QRMath = function() {
+
+ var EXP_TABLE = new Array(256);
+ var LOG_TABLE = new Array(256);
+
+ // initialize tables
+ for (var i = 0; i < 8; i += 1) {
+ EXP_TABLE[i] = 1 << i;
+ }
+ for (var i = 8; i < 256; i += 1) {
+ EXP_TABLE[i] = EXP_TABLE[i - 4]
+ ^ EXP_TABLE[i - 5]
+ ^ EXP_TABLE[i - 6]
+ ^ EXP_TABLE[i - 8];
+ }
+ for (var i = 0; i < 255; i += 1) {
+ LOG_TABLE[EXP_TABLE[i] ] = i;
+ }
+
+ var _this = {};
+
+ _this.glog = function(n) {
+
+ if (n < 1) {
+ throw new Error('glog(' + n + ')');
+ }
+
+ return LOG_TABLE[n];
+ };
+
+ _this.gexp = function(n) {
+
+ while (n < 0) {
+ n += 255;
+ }
+
+ while (n >= 256) {
+ n -= 255;
+ }
+
+ return EXP_TABLE[n];
+ };
+
+ return _this;
+ }();
+
+ //---------------------------------------------------------------------
+ // qrPolynomial
+ //---------------------------------------------------------------------
+
+ function qrPolynomial(num, shift) {
+
+ if (typeof num.length == 'undefined') {
+ throw new Error(num.length + '/' + shift);
+ }
+
+ var _num = function() {
+ var offset = 0;
+ while (offset < num.length && num[offset] == 0) {
+ offset += 1;
+ }
+ var _num = new Array(num.length - offset + shift);
+ for (var i = 0; i < num.length - offset; i += 1) {
+ _num[i] = num[i + offset];
+ }
+ return _num;
+ }();
+
+ var _this = {};
+
+ _this.get = function(index) {
+ return _num[index];
+ };
+
+ _this.getLength = function() {
+ return _num.length;
+ };
+
+ _this.multiply = function(e) {
+
+ var num = new Array(_this.getLength() + e.getLength() - 1);
+
+ for (var i = 0; i < _this.getLength(); i += 1) {
+ for (var j = 0; j < e.getLength(); j += 1) {
+ num[i + j] ^= QRMath.gexp(QRMath.glog(_this.get(i) ) + QRMath.glog(e.get(j) ) );
+ }
+ }
+
+ return qrPolynomial(num, 0);
+ };
+
+ _this.mod = function(e) {
+
+ if (_this.getLength() - e.getLength() < 0) {
+ return _this;
+ }
+
+ var ratio = QRMath.glog(_this.get(0) ) - QRMath.glog(e.get(0) );
+
+ var num = new Array(_this.getLength() );
+ for (var i = 0; i < _this.getLength(); i += 1) {
+ num[i] = _this.get(i);
+ }
+
+ for (var i = 0; i < e.getLength(); i += 1) {
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio);
+ }
+
+ // recursive call
+ return qrPolynomial(num, 0).mod(e);
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // QRRSBlock
+ //---------------------------------------------------------------------
+
+ var QRRSBlock = function() {
+
+ var RS_BLOCK_TABLE = [
+
+ // L
+ // M
+ // Q
+ // H
+
+ // 1
+ [1, 26, 19],
+ [1, 26, 16],
+ [1, 26, 13],
+ [1, 26, 9],
+
+ // 2
+ [1, 44, 34],
+ [1, 44, 28],
+ [1, 44, 22],
+ [1, 44, 16],
+
+ // 3
+ [1, 70, 55],
+ [1, 70, 44],
+ [2, 35, 17],
+ [2, 35, 13],
+
+ // 4
+ [1, 100, 80],
+ [2, 50, 32],
+ [2, 50, 24],
+ [4, 25, 9],
+
+ // 5
+ [1, 134, 108],
+ [2, 67, 43],
+ [2, 33, 15, 2, 34, 16],
+ [2, 33, 11, 2, 34, 12],
+
+ // 6
+ [2, 86, 68],
+ [4, 43, 27],
+ [4, 43, 19],
+ [4, 43, 15],
+
+ // 7
+ [2, 98, 78],
+ [4, 49, 31],
+ [2, 32, 14, 4, 33, 15],
+ [4, 39, 13, 1, 40, 14],
+
+ // 8
+ [2, 121, 97],
+ [2, 60, 38, 2, 61, 39],
+ [4, 40, 18, 2, 41, 19],
+ [4, 40, 14, 2, 41, 15],
+
+ // 9
+ [2, 146, 116],
+ [3, 58, 36, 2, 59, 37],
+ [4, 36, 16, 4, 37, 17],
+ [4, 36, 12, 4, 37, 13],
+
+ // 10
+ [2, 86, 68, 2, 87, 69],
+ [4, 69, 43, 1, 70, 44],
+ [6, 43, 19, 2, 44, 20],
+ [6, 43, 15, 2, 44, 16]
+ ];
+
+ var qrRSBlock = function(totalCount, dataCount) {
+ var _this = {};
+ _this.totalCount = totalCount;
+ _this.dataCount = dataCount;
+ return _this;
+ };
+
+ var _this = {};
+
+ var getRsBlockTable = function(typeNumber, errorCorrectLevel) {
+
+ switch(errorCorrectLevel) {
+ case QRErrorCorrectLevel.L :
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
+ case QRErrorCorrectLevel.M :
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
+ case QRErrorCorrectLevel.Q :
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
+ case QRErrorCorrectLevel.H :
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
+ default :
+ return undefined;
+ }
+ };
+
+ _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {
+
+ var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);
+
+ if (typeof rsBlock == 'undefined') {
+ throw new Error('bad rs block @ typeNumber:' + typeNumber +
+ '/errorCorrectLevel:' + errorCorrectLevel);
+ }
+
+ var length = rsBlock.length / 3;
+
+ var list = new Array();
+
+ for (var i = 0; i < length; i += 1) {
+
+ var count = rsBlock[i * 3 + 0];
+ var totalCount = rsBlock[i * 3 + 1];
+ var dataCount = rsBlock[i * 3 + 2];
+
+ for (var j = 0; j < count; j += 1) {
+ list.push(qrRSBlock(totalCount, dataCount) );
+ }
+ }
+
+ return list;
+ };
+
+ return _this;
+ }();
+
+ //---------------------------------------------------------------------
+ // qrBitBuffer
+ //---------------------------------------------------------------------
+
+ var qrBitBuffer = function() {
+
+ var _buffer = new Array();
+ var _length = 0;
+
+ var _this = {};
+
+ _this.getBuffer = function() {
+ return _buffer;
+ };
+
+ _this.get = function(index) {
+ var bufIndex = Math.floor(index / 8);
+ return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
+ };
+
+ _this.put = function(num, length) {
+ for (var i = 0; i < length; i += 1) {
+ _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
+ }
+ };
+
+ _this.getLengthInBits = function() {
+ return _length;
+ };
+
+ _this.putBit = function(bit) {
+
+ var bufIndex = Math.floor(_length / 8);
+ if (_buffer.length <= bufIndex) {
+ _buffer.push(0);
+ }
+
+ if (bit) {
+ _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
+ }
+
+ _length += 1;
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // qr8BitByte
+ //---------------------------------------------------------------------
+
+ var qr8BitByte = function(data) {
+
+ var _mode = QRMode.MODE_8BIT_BYTE;
+ var _data = data;
+ var _bytes = qrcode.stringToBytes(data);
+
+ var _this = {};
+
+ _this.getMode = function() {
+ return _mode;
+ };
+
+ _this.getLength = function(buffer) {
+ return _bytes.length;
+ };
+
+ _this.write = function(buffer) {
+ for (var i = 0; i < _bytes.length; i += 1) {
+ buffer.put(_bytes[i], 8);
+ }
+ };
+
+ return _this;
+ };
+
+ //=====================================================================
+ // GIF Support etc.
+ //
+
+ //---------------------------------------------------------------------
+ // byteArrayOutputStream
+ //---------------------------------------------------------------------
+
+ var byteArrayOutputStream = function() {
+
+ var _bytes = new Array();
+
+ var _this = {};
+
+ _this.writeByte = function(b) {
+ _bytes.push(b & 0xff);
+ };
+
+ _this.writeShort = function(i) {
+ _this.writeByte(i);
+ _this.writeByte(i >>> 8);
+ };
+
+ _this.writeBytes = function(b, off, len) {
+ off = off || 0;
+ len = len || b.length;
+ for (var i = 0; i < len; i += 1) {
+ _this.writeByte(b[i + off]);
+ }
+ };
+
+ _this.writeString = function(s) {
+ for (var i = 0; i < s.length; i += 1) {
+ _this.writeByte(s.charCodeAt(i) );
+ }
+ };
+
+ _this.toByteArray = function() {
+ return _bytes;
+ };
+
+ _this.toString = function() {
+ var s = '';
+ s += '[';
+ for (var i = 0; i < _bytes.length; i += 1) {
+ if (i > 0) {
+ s += ',';
+ }
+ s += _bytes[i];
+ }
+ s += ']';
+ return s;
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // base64EncodeOutputStream
+ //---------------------------------------------------------------------
+
+ var base64EncodeOutputStream = function() {
+
+ var _buffer = 0;
+ var _buflen = 0;
+ var _length = 0;
+ var _base64 = '';
+
+ var _this = {};
+
+ var writeEncoded = function(b) {
+ _base64 += String.fromCharCode(encode(b & 0x3f) );
+ };
+
+ var encode = function(n) {
+ if (n < 0) {
+ // error.
+ } else if (n < 26) {
+ return 0x41 + n;
+ } else if (n < 52) {
+ return 0x61 + (n - 26);
+ } else if (n < 62) {
+ return 0x30 + (n - 52);
+ } else if (n == 62) {
+ return 0x2b;
+ } else if (n == 63) {
+ return 0x2f;
+ }
+ throw new Error('n:' + n);
+ };
+
+ _this.writeByte = function(n) {
+
+ _buffer = (_buffer << 8) | (n & 0xff);
+ _buflen += 8;
+ _length += 1;
+
+ while (_buflen >= 6) {
+ writeEncoded(_buffer >>> (_buflen - 6) );
+ _buflen -= 6;
+ }
+ };
+
+ _this.flush = function() {
+
+ if (_buflen > 0) {
+ writeEncoded(_buffer << (6 - _buflen) );
+ _buffer = 0;
+ _buflen = 0;
+ }
+
+ if (_length % 3 != 0) {
+ // padding
+ var padlen = 3 - _length % 3;
+ for (var i = 0; i < padlen; i += 1) {
+ _base64 += '=';
+ }
+ }
+ };
+
+ _this.toString = function() {
+ return _base64;
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // base64DecodeInputStream
+ //---------------------------------------------------------------------
+
+ var base64DecodeInputStream = function(str) {
+
+ var _str = str;
+ var _pos = 0;
+ var _buffer = 0;
+ var _buflen = 0;
+
+ var _this = {};
+
+ _this.read = function() {
+
+ while (_buflen < 8) {
+
+ if (_pos >= _str.length) {
+ if (_buflen == 0) {
+ return -1;
+ }
+ throw new Error('unexpected end of file./' + _buflen);
+ }
+
+ var c = _str.charAt(_pos);
+ _pos += 1;
+
+ if (c == '=') {
+ _buflen = 0;
+ return -1;
+ } else if (c.match(/^\s$/) ) {
+ // ignore if whitespace.
+ continue;
+ }
+
+ _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
+ _buflen += 6;
+ }
+
+ var n = (_buffer >>> (_buflen - 8) ) & 0xff;
+ _buflen -= 8;
+ return n;
+ };
+
+ var decode = function(c) {
+ if (0x41 <= c && c <= 0x5a) {
+ return c - 0x41;
+ } else if (0x61 <= c && c <= 0x7a) {
+ return c - 0x61 + 26;
+ } else if (0x30 <= c && c <= 0x39) {
+ return c - 0x30 + 52;
+ } else if (c == 0x2b) {
+ return 62;
+ } else if (c == 0x2f) {
+ return 63;
+ } else {
+ throw new Error('c:' + c);
+ }
+ };
+
+ return _this;
+ };
+
+ //---------------------------------------------------------------------
+ // gifImage (B/W)
+ //---------------------------------------------------------------------
+
+ var gifImage = function(width, height) {
+
+ var _width = width;
+ var _height = height;
+ var _data = new Array(width * height);
+
+ var _this = {};
+
+ _this.setPixel = function(x, y, pixel) {
+ _data[y * _width + x] = pixel;
+ };
+
+ _this.write = function(out) {
+
+ //---------------------------------
+ // GIF Signature
+
+ out.writeString('GIF87a');
+
+ //---------------------------------
+ // Screen Descriptor
+
+ out.writeShort(_width);
+ out.writeShort(_height);
+
+ out.writeByte(0x80); // 2bit
+ out.writeByte(0);
+ out.writeByte(0);
+
+ //---------------------------------
+ // Global Color Map
+
+ // black
+ out.writeByte(0x00);
+ out.writeByte(0x00);
+ out.writeByte(0x00);
+
+ // white
+ out.writeByte(0xff);
+ out.writeByte(0xff);
+ out.writeByte(0xff);
+
+ //---------------------------------
+ // Image Descriptor
+
+ out.writeString(',');
+ out.writeShort(0);
+ out.writeShort(0);
+ out.writeShort(_width);
+ out.writeShort(_height);
+ out.writeByte(0);
+
+ //---------------------------------
+ // Local Color Map
+
+ //---------------------------------
+ // Raster Data
+
+ var lzwMinCodeSize = 2;
+ var raster = getLZWRaster(lzwMinCodeSize);
+
+ out.writeByte(lzwMinCodeSize);
+
+ var offset = 0;
+
+ while (raster.length - offset > 255) {
+ out.writeByte(255);
+ out.writeBytes(raster, offset, 255);
+ offset += 255;
+ }
+
+ out.writeByte(raster.length - offset);
+ out.writeBytes(raster, offset, raster.length - offset);
+ out.writeByte(0x00);
+
+ //---------------------------------
+ // GIF Terminator
+ out.writeString(';');
+ };
+
+ var bitOutputStream = function(out) {
+
+ var _out = out;
+ var _bitLength = 0;
+ var _bitBuffer = 0;
+
+ var _this = {};
+
+ _this.write = function(data, length) {
+
+ if ( (data >>> length) != 0) {
+ throw new Error('length over');
+ }
+
+ while (_bitLength + length >= 8) {
+ _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
+ length -= (8 - _bitLength);
+ data >>>= (8 - _bitLength);
+ _bitBuffer = 0;
+ _bitLength = 0;
+ }
+
+ _bitBuffer = (data << _bitLength) | _bitBuffer;
+ _bitLength = _bitLength + length;
+ };
+
+ _this.flush = function() {
+ if (_bitLength > 0) {
+ _out.writeByte(_bitBuffer);
+ }
+ };
+
+ return _this;
+ };
+
+ var getLZWRaster = function(lzwMinCodeSize) {
+
+ var clearCode = 1 << lzwMinCodeSize;
+ var endCode = (1 << lzwMinCodeSize) + 1;
+ var bitLength = lzwMinCodeSize + 1;
+
+ // Setup LZWTable
+ var table = lzwTable();
+
+ for (var i = 0; i < clearCode; i += 1) {
+ table.add(String.fromCharCode(i) );
+ }
+ table.add(String.fromCharCode(clearCode) );
+ table.add(String.fromCharCode(endCode) );
+
+ var byteOut = byteArrayOutputStream();
+ var bitOut = bitOutputStream(byteOut);
+
+ // clear code
+ bitOut.write(clearCode, bitLength);
+
+ var dataIndex = 0;
+
+ var s = String.fromCharCode(_data[dataIndex]);
+ dataIndex += 1;
+
+ while (dataIndex < _data.length) {
+
+ var c = String.fromCharCode(_data[dataIndex]);
+ dataIndex += 1;
+
+ if (table.contains(s + c) ) {
+
+ s = s + c;
+
+ } else {
+
+ bitOut.write(table.indexOf(s), bitLength);
+
+ if (table.size() < 0xfff) {
+
+ if (table.size() == (1 << bitLength) ) {
+ bitLength += 1;
+ }
+
+ table.add(s + c);
+ }
+
+ s = c;
+ }
+ }
+
+ bitOut.write(table.indexOf(s), bitLength);
+
+ // end code
+ bitOut.write(endCode, bitLength);
+
+ bitOut.flush();
+
+ return byteOut.toByteArray();
+ };
+
+ var lzwTable = function() {
+
+ var _map = {};
+ var _size = 0;
+
+ var _this = {};
+
+ _this.add = function(key) {
+ if (_this.contains(key) ) {
+ throw new Error('dup key:' + key);
+ }
+ _map[key] = _size;
+ _size += 1;
+ };
+
+ _this.size = function() {
+ return _size;
+ };
+
+ _this.indexOf = function(key) {
+ return _map[key];
+ };
+
+ _this.contains = function(key) {
+ return typeof _map[key] != 'undefined';
+ };
+
+ return _this;
+ };
+
+ return _this;
+ };
+
+ var createImgTag = function(width, height, getPixel, alt) {
+
+ var gif = gifImage(width, height);
+ for (var y = 0; y < height; y += 1) {
+ for (var x = 0; x < width; x += 1) {
+ gif.setPixel(x, y, getPixel(x, y) );
+ }
+ }
+
+ var b = byteArrayOutputStream();
+ gif.write(b);
+
+ var base64 = base64EncodeOutputStream();
+ var bytes = b.toByteArray();
+ for (var i = 0; i < bytes.length; i += 1) {
+ base64.writeByte(bytes[i]);
+ }
+ base64.flush();
+
+ var img = '';
+ img += '
![]()
';
+
+ return img;
+ };
+
+ //---------------------------------------------------------------------
+ // returns qrcode function.
+
+ return qrcode;
+}();
diff --git a/js/rfc1751.js b/js/rfc1751.js
new file mode 100644
index 0000000..8cc7405
--- /dev/null
+++ b/js/rfc1751.js
@@ -0,0 +1,348 @@
+/*
+ rfc1751.js : Converts between 128-bit strings and a human-readable
+ sequence of words, as defined in RFC1751: "A Convention for
+ Human-Readable 128-bit Keys", by Daniel L. McDonald.
+ Ported from rfc1751.py / Python Cryptography Toolkit (public domain).
+*/
+
+var rfc1751_wordlist = [ "A", "ABE", "ACE", "ACT", "AD", "ADA", "ADD",
+ "AGO", "AID", "AIM", "AIR", "ALL", "ALP", "AM", "AMY", "AN", "ANA",
+ "AND", "ANN", "ANT", "ANY", "APE", "APS", "APT", "ARC", "ARE", "ARK",
+ "ARM", "ART", "AS", "ASH", "ASK", "AT", "ATE", "AUG", "AUK", "AVE",
+ "AWE", "AWK", "AWL", "AWN", "AX", "AYE", "BAD", "BAG", "BAH", "BAM",
+ "BAN", "BAR", "BAT", "BAY", "BE", "BED", "BEE", "BEG", "BEN", "BET",
+ "BEY", "BIB", "BID", "BIG", "BIN", "BIT", "BOB", "BOG", "BON", "BOO",
+ "BOP", "BOW", "BOY", "BUB", "BUD", "BUG", "BUM", "BUN", "BUS", "BUT",
+ "BUY", "BY", "BYE", "CAB", "CAL", "CAM", "CAN", "CAP", "CAR", "CAT",
+ "CAW", "COD", "COG", "COL", "CON", "COO", "COP", "COT", "COW", "COY",
+ "CRY", "CUB", "CUE", "CUP", "CUR", "CUT", "DAB", "DAD", "DAM", "DAN",
+ "DAR", "DAY", "DEE", "DEL", "DEN", "DES", "DEW", "DID", "DIE", "DIG",
+ "DIN", "DIP", "DO", "DOE", "DOG", "DON", "DOT", "DOW", "DRY", "DUB",
+ "DUD", "DUE", "DUG", "DUN", "EAR", "EAT", "ED", "EEL", "EGG", "EGO",
+ "ELI", "ELK", "ELM", "ELY", "EM", "END", "EST", "ETC", "EVA", "EVE",
+ "EWE", "EYE", "FAD", "FAN", "FAR", "FAT", "FAY", "FED", "FEE", "FEW",
+ "FIB", "FIG", "FIN", "FIR", "FIT", "FLO", "FLY", "FOE", "FOG", "FOR",
+ "FRY", "FUM", "FUN", "FUR", "GAB", "GAD", "GAG", "GAL", "GAM", "GAP",
+ "GAS", "GAY", "GEE", "GEL", "GEM", "GET", "GIG", "GIL", "GIN", "GO",
+ "GOT", "GUM", "GUN", "GUS", "GUT", "GUY", "GYM", "GYP", "HA", "HAD",
+ "HAL", "HAM", "HAN", "HAP", "HAS", "HAT", "HAW", "HAY", "HE", "HEM",
+ "HEN", "HER", "HEW", "HEY", "HI", "HID", "HIM", "HIP", "HIS", "HIT",
+ "HO", "HOB", "HOC", "HOE", "HOG", "HOP", "HOT", "HOW", "HUB", "HUE",
+ "HUG", "HUH", "HUM", "HUT", "I", "ICY", "IDA", "IF", "IKE", "ILL",
+ "INK", "INN", "IO", "ION", "IQ", "IRA", "IRE", "IRK", "IS", "IT",
+ "ITS", "IVY", "JAB", "JAG", "JAM", "JAN", "JAR", "JAW", "JAY", "JET",
+ "JIG", "JIM", "JO", "JOB", "JOE", "JOG", "JOT", "JOY", "JUG", "JUT",
+ "KAY", "KEG", "KEN", "KEY", "KID", "KIM", "KIN", "KIT", "LA", "LAB",
+ "LAC", "LAD", "LAG", "LAM", "LAP", "LAW", "LAY", "LEA", "LED", "LEE",
+ "LEG", "LEN", "LEO", "LET", "LEW", "LID", "LIE", "LIN", "LIP", "LIT",
+ "LO", "LOB", "LOG", "LOP", "LOS", "LOT", "LOU", "LOW", "LOY", "LUG",
+ "LYE", "MA", "MAC", "MAD", "MAE", "MAN", "MAO", "MAP", "MAT", "MAW",
+ "MAY", "ME", "MEG", "MEL", "MEN", "MET", "MEW", "MID", "MIN", "MIT",
+ "MOB", "MOD", "MOE", "MOO", "MOP", "MOS", "MOT", "MOW", "MUD", "MUG",
+ "MUM", "MY", "NAB", "NAG", "NAN", "NAP", "NAT", "NAY", "NE", "NED",
+ "NEE", "NET", "NEW", "NIB", "NIL", "NIP", "NIT", "NO", "NOB", "NOD",
+ "NON", "NOR", "NOT", "NOV", "NOW", "NU", "NUN", "NUT", "O", "OAF",
+ "OAK", "OAR", "OAT", "ODD", "ODE", "OF", "OFF", "OFT", "OH", "OIL",
+ "OK", "OLD", "ON", "ONE", "OR", "ORB", "ORE", "ORR", "OS", "OTT",
+ "OUR", "OUT", "OVA", "OW", "OWE", "OWL", "OWN", "OX", "PA", "PAD",
+ "PAL", "PAM", "PAN", "PAP", "PAR", "PAT", "PAW", "PAY", "PEA", "PEG",
+ "PEN", "PEP", "PER", "PET", "PEW", "PHI", "PI", "PIE", "PIN", "PIT",
+ "PLY", "PO", "POD", "POE", "POP", "POT", "POW", "PRO", "PRY", "PUB",
+ "PUG", "PUN", "PUP", "PUT", "QUO", "RAG", "RAM", "RAN", "RAP", "RAT",
+ "RAW", "RAY", "REB", "RED", "REP", "RET", "RIB", "RID", "RIG", "RIM",
+ "RIO", "RIP", "ROB", "ROD", "ROE", "RON", "ROT", "ROW", "ROY", "RUB",
+ "RUE", "RUG", "RUM", "RUN", "RYE", "SAC", "SAD", "SAG", "SAL", "SAM",
+ "SAN", "SAP", "SAT", "SAW", "SAY", "SEA", "SEC", "SEE", "SEN", "SET",
+ "SEW", "SHE", "SHY", "SIN", "SIP", "SIR", "SIS", "SIT", "SKI", "SKY",
+ "SLY", "SO", "SOB", "SOD", "SON", "SOP", "SOW", "SOY", "SPA", "SPY",
+ "SUB", "SUD", "SUE", "SUM", "SUN", "SUP", "TAB", "TAD", "TAG", "TAN",
+ "TAP", "TAR", "TEA", "TED", "TEE", "TEN", "THE", "THY", "TIC", "TIE",
+ "TIM", "TIN", "TIP", "TO", "TOE", "TOG", "TOM", "TON", "TOO", "TOP",
+ "TOW", "TOY", "TRY", "TUB", "TUG", "TUM", "TUN", "TWO", "UN", "UP",
+ "US", "USE", "VAN", "VAT", "VET", "VIE", "WAD", "WAG", "WAR", "WAS",
+ "WAY", "WE", "WEB", "WED", "WEE", "WET", "WHO", "WHY", "WIN", "WIT",
+ "WOK", "WON", "WOO", "WOW", "WRY", "WU", "YAM", "YAP", "YAW", "YE",
+ "YEA", "YES", "YET", "YOU", "ABED", "ABEL", "ABET", "ABLE", "ABUT",
+ "ACHE", "ACID", "ACME", "ACRE", "ACTA", "ACTS", "ADAM", "ADDS",
+ "ADEN", "AFAR", "AFRO", "AGEE", "AHEM", "AHOY", "AIDA", "AIDE",
+ "AIDS", "AIRY", "AJAR", "AKIN", "ALAN", "ALEC", "ALGA", "ALIA",
+ "ALLY", "ALMA", "ALOE", "ALSO", "ALTO", "ALUM", "ALVA", "AMEN",
+ "AMES", "AMID", "AMMO", "AMOK", "AMOS", "AMRA", "ANDY", "ANEW",
+ "ANNA", "ANNE", "ANTE", "ANTI", "AQUA", "ARAB", "ARCH", "AREA",
+ "ARGO", "ARID", "ARMY", "ARTS", "ARTY", "ASIA", "ASKS", "ATOM",
+ "AUNT", "AURA", "AUTO", "AVER", "AVID", "AVIS", "AVON", "AVOW",
+ "AWAY", "AWRY", "BABE", "BABY", "BACH", "BACK", "BADE", "BAIL",
+ "BAIT", "BAKE", "BALD", "BALE", "BALI", "BALK", "BALL", "BALM",
+ "BAND", "BANE", "BANG", "BANK", "BARB", "BARD", "BARE", "BARK",
+ "BARN", "BARR", "BASE", "BASH", "BASK", "BASS", "BATE", "BATH",
+ "BAWD", "BAWL", "BEAD", "BEAK", "BEAM", "BEAN", "BEAR", "BEAT",
+ "BEAU", "BECK", "BEEF", "BEEN", "BEER",
+ "BEET", "BELA", "BELL", "BELT", "BEND", "BENT", "BERG", "BERN",
+ "BERT", "BESS", "BEST", "BETA", "BETH", "BHOY", "BIAS", "BIDE",
+ "BIEN", "BILE", "BILK", "BILL", "BIND", "BING", "BIRD", "BITE",
+ "BITS", "BLAB", "BLAT", "BLED", "BLEW", "BLOB", "BLOC", "BLOT",
+ "BLOW", "BLUE", "BLUM", "BLUR", "BOAR", "BOAT", "BOCA", "BOCK",
+ "BODE", "BODY", "BOGY", "BOHR", "BOIL", "BOLD", "BOLO", "BOLT",
+ "BOMB", "BONA", "BOND", "BONE", "BONG", "BONN", "BONY", "BOOK",
+ "BOOM", "BOON", "BOOT", "BORE", "BORG", "BORN", "BOSE", "BOSS",
+ "BOTH", "BOUT", "BOWL", "BOYD", "BRAD", "BRAE", "BRAG", "BRAN",
+ "BRAY", "BRED", "BREW", "BRIG", "BRIM", "BROW", "BUCK", "BUDD",
+ "BUFF", "BULB", "BULK", "BULL", "BUNK", "BUNT", "BUOY", "BURG",
+ "BURL", "BURN", "BURR", "BURT", "BURY", "BUSH", "BUSS", "BUST",
+ "BUSY", "BYTE", "CADY", "CAFE", "CAGE", "CAIN", "CAKE", "CALF",
+ "CALL", "CALM", "CAME", "CANE", "CANT", "CARD", "CARE", "CARL",
+ "CARR", "CART", "CASE", "CASH", "CASK", "CAST", "CAVE", "CEIL",
+ "CELL", "CENT", "CERN", "CHAD", "CHAR", "CHAT", "CHAW", "CHEF",
+ "CHEN", "CHEW", "CHIC", "CHIN", "CHOU", "CHOW", "CHUB", "CHUG",
+ "CHUM", "CITE", "CITY", "CLAD", "CLAM", "CLAN", "CLAW", "CLAY",
+ "CLOD", "CLOG", "CLOT", "CLUB", "CLUE", "COAL", "COAT", "COCA",
+ "COCK", "COCO", "CODA", "CODE", "CODY", "COED", "COIL", "COIN",
+ "COKE", "COLA", "COLD", "COLT", "COMA", "COMB", "COME", "COOK",
+ "COOL", "COON", "COOT", "CORD", "CORE", "CORK", "CORN", "COST",
+ "COVE", "COWL", "CRAB", "CRAG", "CRAM", "CRAY", "CREW", "CRIB",
+ "CROW", "CRUD", "CUBA", "CUBE", "CUFF", "CULL", "CULT", "CUNY",
+ "CURB", "CURD", "CURE", "CURL", "CURT", "CUTS", "DADE", "DALE",
+ "DAME", "DANA", "DANE", "DANG", "DANK", "DARE", "DARK", "DARN",
+ "DART", "DASH", "DATA", "DATE", "DAVE", "DAVY", "DAWN", "DAYS",
+ "DEAD", "DEAF", "DEAL", "DEAN", "DEAR", "DEBT", "DECK", "DEED",
+ "DEEM", "DEER", "DEFT", "DEFY", "DELL", "DENT", "DENY", "DESK",
+ "DIAL", "DICE", "DIED", "DIET", "DIME", "DINE", "DING", "DINT",
+ "DIRE", "DIRT", "DISC", "DISH", "DISK", "DIVE", "DOCK", "DOES",
+ "DOLE", "DOLL", "DOLT", "DOME", "DONE", "DOOM", "DOOR", "DORA",
+ "DOSE", "DOTE", "DOUG", "DOUR", "DOVE", "DOWN", "DRAB", "DRAG",
+ "DRAM", "DRAW", "DREW", "DRUB", "DRUG", "DRUM", "DUAL", "DUCK",
+ "DUCT", "DUEL", "DUET", "DUKE", "DULL", "DUMB", "DUNE", "DUNK",
+ "DUSK", "DUST", "DUTY", "EACH", "EARL", "EARN", "EASE", "EAST",
+ "EASY", "EBEN", "ECHO", "EDDY", "EDEN", "EDGE", "EDGY", "EDIT",
+ "EDNA", "EGAN", "ELAN", "ELBA", "ELLA", "ELSE", "EMIL", "EMIT",
+ "EMMA", "ENDS", "ERIC", "EROS", "EVEN", "EVER", "EVIL", "EYED",
+ "FACE", "FACT", "FADE", "FAIL", "FAIN", "FAIR", "FAKE", "FALL",
+ "FAME", "FANG", "FARM", "FAST", "FATE", "FAWN", "FEAR", "FEAT",
+ "FEED", "FEEL", "FEET", "FELL", "FELT", "FEND", "FERN", "FEST",
+ "FEUD", "FIEF", "FIGS", "FILE", "FILL", "FILM", "FIND", "FINE",
+ "FINK", "FIRE", "FIRM", "FISH", "FISK", "FIST", "FITS", "FIVE",
+ "FLAG", "FLAK", "FLAM", "FLAT", "FLAW", "FLEA", "FLED", "FLEW",
+ "FLIT", "FLOC", "FLOG", "FLOW", "FLUB", "FLUE", "FOAL", "FOAM",
+ "FOGY", "FOIL", "FOLD", "FOLK", "FOND", "FONT", "FOOD", "FOOL",
+ "FOOT", "FORD", "FORE", "FORK", "FORM", "FORT", "FOSS", "FOUL",
+ "FOUR", "FOWL", "FRAU", "FRAY", "FRED", "FREE", "FRET", "FREY",
+ "FROG", "FROM", "FUEL", "FULL", "FUME", "FUND", "FUNK", "FURY",
+ "FUSE", "FUSS", "GAFF", "GAGE", "GAIL", "GAIN", "GAIT", "GALA",
+ "GALE", "GALL", "GALT", "GAME", "GANG", "GARB", "GARY", "GASH",
+ "GATE", "GAUL", "GAUR", "GAVE", "GAWK", "GEAR", "GELD", "GENE",
+ "GENT", "GERM", "GETS", "GIBE", "GIFT", "GILD", "GILL", "GILT",
+ "GINA", "GIRD", "GIRL", "GIST", "GIVE", "GLAD", "GLEE", "GLEN",
+ "GLIB", "GLOB", "GLOM", "GLOW", "GLUE", "GLUM", "GLUT", "GOAD",
+ "GOAL", "GOAT", "GOER", "GOES", "GOLD", "GOLF", "GONE", "GONG",
+ "GOOD", "GOOF", "GORE", "GORY", "GOSH", "GOUT", "GOWN", "GRAB",
+ "GRAD", "GRAY", "GREG", "GREW", "GREY", "GRID", "GRIM", "GRIN",
+ "GRIT", "GROW", "GRUB", "GULF", "GULL", "GUNK", "GURU", "GUSH",
+ "GUST", "GWEN", "GWYN", "HAAG", "HAAS", "HACK", "HAIL", "HAIR",
+ "HALE", "HALF", "HALL", "HALO", "HALT", "HAND", "HANG", "HANK",
+ "HANS", "HARD", "HARK", "HARM", "HART", "HASH", "HAST", "HATE",
+ "HATH", "HAUL", "HAVE", "HAWK", "HAYS", "HEAD", "HEAL", "HEAR",
+ "HEAT", "HEBE", "HECK", "HEED", "HEEL", "HEFT", "HELD", "HELL",
+ "HELM", "HERB", "HERD", "HERE", "HERO", "HERS", "HESS", "HEWN",
+ "HICK", "HIDE", "HIGH", "HIKE", "HILL", "HILT", "HIND", "HINT",
+ "HIRE", "HISS", "HIVE", "HOBO", "HOCK", "HOFF", "HOLD", "HOLE",
+ "HOLM", "HOLT", "HOME", "HONE", "HONK", "HOOD", "HOOF", "HOOK",
+ "HOOT", "HORN", "HOSE", "HOST", "HOUR", "HOVE", "HOWE", "HOWL",
+ "HOYT", "HUCK", "HUED", "HUFF", "HUGE", "HUGH", "HUGO", "HULK",
+ "HULL", "HUNK", "HUNT", "HURD", "HURL", "HURT", "HUSH", "HYDE",
+ "HYMN", "IBIS", "ICON", "IDEA", "IDLE", "IFFY", "INCA", "INCH",
+ "INTO", "IONS", "IOTA", "IOWA", "IRIS", "IRMA", "IRON", "ISLE",
+ "ITCH", "ITEM", "IVAN", "JACK", "JADE", "JAIL", "JAKE", "JANE",
+ "JAVA", "JEAN", "JEFF", "JERK", "JESS", "JEST", "JIBE", "JILL",
+ "JILT", "JIVE", "JOAN", "JOBS", "JOCK", "JOEL", "JOEY", "JOHN",
+ "JOIN", "JOKE", "JOLT", "JOVE", "JUDD", "JUDE", "JUDO", "JUDY",
+ "JUJU", "JUKE", "JULY", "JUNE", "JUNK", "JUNO", "JURY", "JUST",
+ "JUTE", "KAHN", "KALE", "KANE", "KANT", "KARL", "KATE", "KEEL",
+ "KEEN", "KENO", "KENT", "KERN", "KERR", "KEYS", "KICK", "KILL",
+ "KIND", "KING", "KIRK", "KISS", "KITE", "KLAN", "KNEE", "KNEW",
+ "KNIT", "KNOB", "KNOT", "KNOW", "KOCH", "KONG", "KUDO", "KURD",
+ "KURT", "KYLE", "LACE", "LACK", "LACY", "LADY", "LAID", "LAIN",
+ "LAIR", "LAKE", "LAMB", "LAME", "LAND", "LANE", "LANG", "LARD",
+ "LARK", "LASS", "LAST", "LATE", "LAUD", "LAVA", "LAWN", "LAWS",
+ "LAYS", "LEAD", "LEAF", "LEAK", "LEAN", "LEAR", "LEEK", "LEER",
+ "LEFT", "LEND", "LENS", "LENT", "LEON", "LESK", "LESS", "LEST",
+ "LETS", "LIAR", "LICE", "LICK", "LIED", "LIEN", "LIES", "LIEU",
+ "LIFE", "LIFT", "LIKE", "LILA", "LILT", "LILY", "LIMA", "LIMB",
+ "LIME", "LIND", "LINE", "LINK", "LINT", "LION", "LISA", "LIST",
+ "LIVE", "LOAD", "LOAF", "LOAM", "LOAN", "LOCK", "LOFT", "LOGE",
+ "LOIS", "LOLA", "LONE", "LONG", "LOOK", "LOON", "LOOT", "LORD",
+ "LORE", "LOSE", "LOSS", "LOST", "LOUD", "LOVE", "LOWE", "LUCK",
+ "LUCY", "LUGE", "LUKE", "LULU", "LUND", "LUNG", "LURA", "LURE",
+ "LURK", "LUSH", "LUST", "LYLE", "LYNN", "LYON", "LYRA", "MACE",
+ "MADE", "MAGI", "MAID", "MAIL", "MAIN", "MAKE", "MALE", "MALI",
+ "MALL", "MALT", "MANA", "MANN", "MANY", "MARC", "MARE", "MARK",
+ "MARS", "MART", "MARY", "MASH", "MASK", "MASS", "MAST", "MATE",
+ "MATH", "MAUL", "MAYO", "MEAD", "MEAL", "MEAN", "MEAT", "MEEK",
+ "MEET", "MELD", "MELT", "MEMO", "MEND", "MENU", "MERT", "MESH",
+ "MESS", "MICE", "MIKE", "MILD", "MILE", "MILK", "MILL", "MILT",
+ "MIMI", "MIND", "MINE", "MINI", "MINK", "MINT", "MIRE", "MISS",
+ "MIST", "MITE", "MITT", "MOAN", "MOAT", "MOCK", "MODE", "MOLD",
+ "MOLE", "MOLL", "MOLT", "MONA", "MONK", "MONT", "MOOD", "MOON",
+ "MOOR", "MOOT", "MORE", "MORN", "MORT", "MOSS", "MOST", "MOTH",
+ "MOVE", "MUCH", "MUCK", "MUDD", "MUFF", "MULE", "MULL", "MURK",
+ "MUSH", "MUST", "MUTE", "MUTT", "MYRA", "MYTH", "NAGY", "NAIL",
+ "NAIR", "NAME", "NARY", "NASH", "NAVE", "NAVY", "NEAL", "NEAR",
+ "NEAT", "NECK", "NEED", "NEIL", "NELL", "NEON", "NERO", "NESS",
+ "NEST", "NEWS", "NEWT", "NIBS", "NICE", "NICK", "NILE", "NINA",
+ "NINE", "NOAH", "NODE", "NOEL", "NOLL", "NONE", "NOOK", "NOON",
+ "NORM", "NOSE", "NOTE", "NOUN", "NOVA", "NUDE", "NULL", "NUMB",
+ "OATH", "OBEY", "OBOE", "ODIN", "OHIO", "OILY", "OINT", "OKAY",
+ "OLAF", "OLDY", "OLGA", "OLIN", "OMAN", "OMEN", "OMIT", "ONCE",
+ "ONES", "ONLY", "ONTO", "ONUS", "ORAL", "ORGY", "OSLO", "OTIS",
+ "OTTO", "OUCH", "OUST", "OUTS", "OVAL", "OVEN", "OVER", "OWLY",
+ "OWNS", "QUAD", "QUIT", "QUOD", "RACE", "RACK", "RACY", "RAFT",
+ "RAGE", "RAID", "RAIL", "RAIN", "RAKE", "RANK", "RANT", "RARE",
+ "RASH", "RATE", "RAVE", "RAYS", "READ", "REAL", "REAM", "REAR",
+ "RECK", "REED", "REEF", "REEK", "REEL", "REID", "REIN", "RENA",
+ "REND", "RENT", "REST", "RICE", "RICH", "RICK", "RIDE", "RIFT",
+ "RILL", "RIME", "RING", "RINK", "RISE", "RISK", "RITE", "ROAD",
+ "ROAM", "ROAR", "ROBE", "ROCK", "RODE", "ROIL", "ROLL", "ROME",
+ "ROOD", "ROOF", "ROOK", "ROOM", "ROOT", "ROSA", "ROSE", "ROSS",
+ "ROSY", "ROTH", "ROUT", "ROVE", "ROWE", "ROWS", "RUBE", "RUBY",
+ "RUDE", "RUDY", "RUIN", "RULE", "RUNG", "RUNS", "RUNT", "RUSE",
+ "RUSH", "RUSK", "RUSS", "RUST", "RUTH", "SACK", "SAFE", "SAGE",
+ "SAID", "SAIL", "SALE", "SALK", "SALT", "SAME", "SAND", "SANE",
+ "SANG", "SANK", "SARA", "SAUL", "SAVE", "SAYS", "SCAN", "SCAR",
+ "SCAT", "SCOT", "SEAL", "SEAM", "SEAR", "SEAT", "SEED", "SEEK",
+ "SEEM", "SEEN", "SEES", "SELF", "SELL", "SEND", "SENT", "SETS",
+ "SEWN", "SHAG", "SHAM", "SHAW", "SHAY", "SHED", "SHIM", "SHIN",
+ "SHOD", "SHOE", "SHOT", "SHOW", "SHUN", "SHUT", "SICK", "SIDE",
+ "SIFT", "SIGH", "SIGN", "SILK", "SILL", "SILO", "SILT", "SINE",
+ "SING", "SINK", "SIRE", "SITE", "SITS", "SITU", "SKAT", "SKEW",
+ "SKID", "SKIM", "SKIN", "SKIT", "SLAB", "SLAM", "SLAT", "SLAY",
+ "SLED", "SLEW", "SLID", "SLIM", "SLIT", "SLOB", "SLOG", "SLOT",
+ "SLOW", "SLUG", "SLUM", "SLUR", "SMOG", "SMUG", "SNAG", "SNOB",
+ "SNOW", "SNUB", "SNUG", "SOAK", "SOAR", "SOCK", "SODA", "SOFA",
+ "SOFT", "SOIL", "SOLD", "SOME", "SONG", "SOON", "SOOT", "SORE",
+ "SORT", "SOUL", "SOUR", "SOWN", "STAB", "STAG", "STAN", "STAR",
+ "STAY", "STEM", "STEW", "STIR", "STOW", "STUB", "STUN", "SUCH",
+ "SUDS", "SUIT", "SULK", "SUMS", "SUNG", "SUNK", "SURE", "SURF",
+ "SWAB", "SWAG", "SWAM", "SWAN", "SWAT", "SWAY", "SWIM", "SWUM",
+ "TACK", "TACT", "TAIL", "TAKE", "TALE", "TALK", "TALL", "TANK",
+ "TASK", "TATE", "TAUT", "TEAL", "TEAM", "TEAR", "TECH", "TEEM",
+ "TEEN", "TEET", "TELL", "TEND", "TENT", "TERM", "TERN", "TESS",
+ "TEST", "THAN", "THAT", "THEE", "THEM", "THEN", "THEY", "THIN",
+ "THIS", "THUD", "THUG", "TICK", "TIDE", "TIDY", "TIED", "TIER",
+ "TILE", "TILL", "TILT", "TIME", "TINA", "TINE", "TINT", "TINY",
+ "TIRE", "TOAD", "TOGO", "TOIL", "TOLD", "TOLL", "TONE", "TONG",
+ "TONY", "TOOK", "TOOL", "TOOT", "TORE", "TORN", "TOTE", "TOUR",
+ "TOUT", "TOWN", "TRAG", "TRAM", "TRAY", "TREE", "TREK", "TRIG",
+ "TRIM", "TRIO", "TROD", "TROT", "TROY", "TRUE", "TUBA", "TUBE",
+ "TUCK", "TUFT", "TUNA", "TUNE", "TUNG", "TURF", "TURN", "TUSK",
+ "TWIG", "TWIN", "TWIT", "ULAN", "UNIT", "URGE", "USED", "USER",
+ "USES", "UTAH", "VAIL", "VAIN", "VALE", "VARY", "VASE", "VAST",
+ "VEAL", "VEDA", "VEIL", "VEIN", "VEND", "VENT", "VERB", "VERY",
+ "VETO", "VICE", "VIEW", "VINE", "VISE", "VOID", "VOLT", "VOTE",
+ "WACK", "WADE", "WAGE", "WAIL", "WAIT", "WAKE", "WALE", "WALK",
+ "WALL", "WALT", "WAND", "WANE", "WANG", "WANT", "WARD", "WARM",
+ "WARN", "WART", "WASH", "WAST", "WATS", "WATT", "WAVE", "WAVY",
+ "WAYS", "WEAK", "WEAL", "WEAN", "WEAR", "WEED", "WEEK", "WEIR",
+ "WELD", "WELL", "WELT", "WENT", "WERE", "WERT", "WEST", "WHAM",
+ "WHAT", "WHEE", "WHEN", "WHET", "WHOA", "WHOM", "WICK", "WIFE",
+ "WILD", "WILL", "WIND", "WINE", "WING", "WINK", "WINO", "WIRE",
+ "WISE", "WISH", "WITH", "WOLF", "WONT", "WOOD", "WOOL", "WORD",
+ "WORE", "WORK", "WORM", "WORN", "WOVE", "WRIT", "WYNN", "YALE",
+ "YANG", "YANK", "YARD", "YARN", "YAWL", "YAWN", "YEAH", "YEAR",
+ "YELL", "YOGA", "YOKE" ];
+
+var binary = ['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
+ '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111'];
+
+function _key2bin(key) {
+ res = ''
+ for (var i = 0; i < key.length; i++) {
+ res += binary[key[i] >> 4] + binary [key[i] & 0x0f];
+ }
+ return res;
+}
+
+function _extract(key, start, length) {
+ k = key.substring(start, start+length);
+ var acc = 0;
+ for (var i = 0; i < k.length; i++) {
+ acc = acc * 2 + k.charCodeAt(i) - 48;
+ }
+ return acc;
+}
+
+function key_to_english(key) {
+
+ //pad to 8 bytes
+ var padding = [];
+ for (var i = 0; i < (8 - (key.length % 8)) % 8; i++) {
+ padding.push(0);
+ }
+ key = padding.concat(key);
+
+ var english = [];
+ for (var index = 0; index < key.length; index += 8) {
+ var subkey = key.slice(index, index + 8);
+
+ //add parity
+ var skbin = _key2bin(subkey);
+ var p = 0;
+ for (var i = 0; i < 64; i += 2) {
+ p = p + _extract(skbin, i, 2);
+ }
+ subkey.push((p << 6) & 0xff);
+
+ skbin = _key2bin(subkey);
+ for (var i = 0; i < 64; i += 11) {
+ english.push(rfc1751_wordlist[_extract(skbin, i, 11)]);
+ }
+ }
+ return english.join(' ');
+}
+
+function english_to_key(str) {
+
+ var L = str.split(' ');
+ var key = [];
+
+ for (var index = 0; index < L.length; index += 6) {
+ var sublist = L.slice(index, index + 6);
+ var bits = 0;
+ var ch = [0,0,0,0,0,0,0,0,0];
+ for (var k = 0; k < sublist.length; k++) {
+ var word = sublist[k];
+ var idx = rfc1751_wordlist.indexOf(word);
+ var shift = (8 - (bits + 11) % 8) % 8;
+ var y = idx << shift;
+ var cl = y >> 16;
+ var cc = (y >> 8) & 0xff;
+ var cr = y & 0xff;
+ var t = Math.floor(bits / 8);
+ if (shift > 5) {
+ ch[t] = ch[t] | cl;
+ ch[t+1] = ch[t+1] | cc;
+ ch[t+2] = ch[t+2] | cr;
+ } else if (shift > -3) {
+ ch[t] = ch[t] | cc;
+ ch[t+1] = ch[t+1] | cr;
+ } else {
+ ch[t] = ch[t] | cr;
+ }
+ bits = bits + 11;
+ }
+ var subkey = ch.slice();
+
+ //check parity
+ var skbin = _key2bin(subkey);
+ var p = 0;
+ for (var i = 0; i < 64; i += 2) {
+ p = p + _extract(skbin, i, 2);
+ }
+ var cs0 = _extract(skbin, 64, 2);
+ var cs1 = p & 3;
+ if (cs0 != cs1) {
+ throw new Error("Parity error at " + word);
+ }
+
+ key = key.concat( subkey.slice(0,8) );
+ }
+ return key;
+}
diff --git a/js/secure-random.js b/js/secure-random.js
new file mode 100644
index 0000000..96a59d0
--- /dev/null
+++ b/js/secure-random.js
@@ -0,0 +1,78 @@
+!function(globals){
+'use strict'
+
+//*** UMD BEGIN
+if (typeof define !== 'undefined' && define.amd) { //require.js / AMD
+ define([], function() {
+ return secureRandom
+ })
+} else if (typeof module !== 'undefined' && module.exports) { //CommonJS
+ module.exports = secureRandom
+} else { //script / browser
+ globals.secureRandom = secureRandom
+}
+//*** UMD END
+
+//options.type is the only valid option
+function secureRandom(count, options) {
+ options = options || {type: 'Array'}
+ //we check for process.pid to prevent browserify from tricking us
+ if (typeof process != 'undefined' && typeof process.pid == 'number') {
+ return nodeRandom(count, options)
+ } else {
+ var crypto = window.crypto || window.msCrypto
+ if (!crypto) throw new Error("Your browser does not support window.crypto.")
+ return browserRandom(count, options)
+ }
+}
+
+function nodeRandom(count, options) {
+ var crypto = require('crypto')
+ var buf = crypto.randomBytes(count)
+
+ switch (options.type) {
+ case 'Array':
+ return [].slice.call(buf)
+ case 'Buffer':
+ return buf
+ case 'Uint8Array':
+ var arr = new Uint8Array(count)
+ for (var i = 0; i < count; ++i) { arr[i] = buf.readUInt8(i) }
+ return arr
+ default:
+ throw new Error(options.type + " is unsupported.")
+ }
+}
+
+function browserRandom(count, options) {
+ var nativeArr = new Uint8Array(count)
+ var crypto = window.crypto || window.msCrypto
+ crypto.getRandomValues(nativeArr)
+
+ switch (options.type) {
+ case 'Array':
+ return [].slice.call(nativeArr)
+ case 'Buffer':
+ try { var b = new Buffer(1) } catch(e) { throw new Error('Buffer not supported in this environment. Use Node.js or Browserify for browser support.')}
+ return new Buffer(nativeArr)
+ case 'Uint8Array':
+ return nativeArr
+ default:
+ throw new Error(options.type + " is unsupported.")
+ }
+}
+
+secureRandom.randomArray = function(byteCount) {
+ return secureRandom(byteCount, {type: 'Array'})
+}
+
+secureRandom.randomUint8Array = function(byteCount) {
+ return secureRandom(byteCount, {type: 'Uint8Array'})
+}
+
+secureRandom.randomBuffer = function(byteCount) {
+ return secureRandom(byteCount, {type: 'Buffer'})
+}
+
+
+}(this);
diff --git a/js/tx.js b/js/tx.js
new file mode 100644
index 0000000..b7c4c7e
--- /dev/null
+++ b/js/tx.js
@@ -0,0 +1,480 @@
+/*
+ tx.js - Bitcoin transactions for JavaScript (public domain)
+
+ Obtaining inputs:
+ 1) http://blockchain.info/unspent?address=
+ 2) http://blockexplorer.com/q/mytransactions/
+
+ Sending transactions:
+ 1) http://bitsend.rowit.co.uk
+ 2) http://www.blockchain.info/pushtx
+*/
+
+var TX = new function () {
+
+ var inputs = [];
+ var outputs = [];
+ var eckey = null;
+ var balance = BigInteger.ZERO;
+
+ this.init = function(_eckey) {
+ outputs = [];
+ eckey = _eckey;
+ }
+
+ this.addOutput = function(addr, fval) {
+ outputs.push({address: addr, value: fval});
+ }
+
+ this.removeOutputs = function() {
+ outputs = [];
+ }
+
+ this.getBalance = function() {
+ return balance;
+ }
+
+ this.getFee = function(sendTx) {
+ var out = BigInteger.ZERO;
+ for (var i in outputs) {
+ var fval = outputs[i].value;
+ value = new BigInteger('' + Math.round(fval*1e8), 10);
+ out = out.add(value);
+ }
+ return balance.subtract(out);
+ }
+
+ this.getAddress = function(addrtype) {
+ var addr = new Bitcoin.Address(eckey.getPubKeyHash());
+ addr.version = addrtype ? addrtype : 0;
+ return addr.toString();
+ }
+
+ this.parseInputs = function(text, address) {
+ try {
+ var res = tx_parseBCI(text, address);
+ } catch(err) {
+ var res = parseTxs(text, address);
+ }
+
+ balance = res.balance;
+ inputs = res.unspenttxs;
+ }
+
+ this.rebuild = function(sendTx, resign) {
+ if (!resign)
+ sendTx = new Bitcoin.Transaction();
+
+ var selectedOuts = [];
+ for (var hash in inputs) {
+ if (!inputs.hasOwnProperty(hash))
+ continue;
+ for (var index in inputs[hash]) {
+ if (!inputs[hash].hasOwnProperty(index))
+ continue;
+ var script = parseScript(inputs[hash][index].script);
+ var b64hash = Crypto.util.bytesToBase64(Crypto.util.hexToBytes(hash));
+ var txin = new Bitcoin.TransactionIn({outpoint: {hash: b64hash, index: index}, script: script, sequence: 4294967295});
+ selectedOuts.push(txin);
+ if (!resign)
+ sendTx.addInput(txin);
+ }
+ }
+
+ for (var i in outputs) {
+ var address = outputs[i].address;
+ var fval = outputs[i].value;
+ var value = new BigInteger('' + Math.round(fval * 1e8), 10);
+ if (!resign)
+ sendTx.addOutput(new Bitcoin.Address(address), value);
+ }
+
+ var hashType = 1;
+ for (var i = 0; i < sendTx.ins.length; i++) {
+ var connectedScript = selectedOuts[i].script;
+ var hash = sendTx.hashTransactionForSignature(connectedScript, i, hashType);
+ var pubKeyHash = connectedScript.simpleOutPubKeyHash();
+ var signature = eckey.sign(hash);
+ signature.push(parseInt(hashType, 10));
+ var pubKey = eckey.getPub();
+ var script = new Bitcoin.Script();
+ script.writeBytes(signature);
+ script.writeBytes(pubKey);
+ sendTx.ins[i].script = script;
+ }
+ return sendTx;
+ };
+
+ this.construct = function() {
+ return this.rebuild(null, false);
+ }
+
+ this.resign = function(sendTx) {
+ return this.rebuild(sendTx, true);
+ }
+
+ function uint(f, size) {
+ if (f.length < size)
+ return 0;
+ var bytes = f.slice(0, size);
+ var pos = 1;
+ var n = 0;
+ for (var i = 0; i < size; i++) {
+ var b = f.shift();
+ n += b * pos;
+ pos *= 256;
+ }
+ return size <= 4 ? n : bytes;
+ }
+
+ function u8(f) { return uint(f,1); }
+ function u16(f) { return uint(f,2); }
+ function u32(f) { return uint(f,4); }
+ function u64(f) { return uint(f,8); }
+
+ function errv(val) {
+ return (val instanceof BigInteger || val > 0xffff);
+ }
+
+ function readBuffer(f, size) {
+ var res = f.slice(0, size);
+ for (var i = 0; i < size; i++) f.shift();
+ return res;
+ }
+
+ function readString(f) {
+ var len = readVarInt(f);
+ if (errv(len)) return [];
+ return readBuffer(f, len);
+ }
+
+ function readVarInt(f) {
+ var t = u8(f);
+ if (t == 0xfd) return u16(f); else
+ if (t == 0xfe) return u32(f); else
+ if (t == 0xff) return u64(f); else
+ return t;
+ }
+
+ this.deserialize = function(bytes) {
+ var sendTx = new Bitcoin.Transaction();
+
+ var f = bytes.slice(0);
+ var tx_ver = u32(f);
+ var vin_sz = readVarInt(f);
+ if (errv(vin_sz))
+ return null;
+
+ for (var i = 0; i < vin_sz; i++) {
+ var op = readBuffer(f, 32);
+ var n = u32(f);
+ var script = readString(f);
+ var seq = u32(f);
+ var txin = new Bitcoin.TransactionIn({
+ outpoint: {
+ hash: Crypto.util.bytesToBase64(op),
+ index: n
+ },
+ script: new Bitcoin.Script(script),
+ sequence: seq
+ });
+ sendTx.addInput(txin);
+ }
+
+ var vout_sz = readVarInt(f);
+
+ if (errv(vout_sz))
+ return null;
+
+ for (var i = 0; i < vout_sz; i++) {
+ var value = u64(f);
+ var script = readString(f);
+
+ var txout = new Bitcoin.TransactionOut({
+ value: value,
+ script: new Bitcoin.Script(script)
+ });
+
+ sendTx.addOutput(txout);
+ }
+ var lock_time = u32(f);
+ sendTx.lock_time = lock_time;
+ return sendTx;
+ };
+
+ this.toBBE = function(sendTx) {
+ //serialize to Bitcoin Block Explorer format
+ var buf = sendTx.serialize();
+ var hash = Crypto.SHA256(Crypto.SHA256(buf, {asBytes: true}), {asBytes: true});
+
+ var r = {};
+ r['hash'] = Crypto.util.bytesToHex(hash.reverse());
+ r['ver'] = sendTx.version;
+ r['vin_sz'] = sendTx.ins.length;
+ r['vout_sz'] = sendTx.outs.length;
+ r['lock_time'] = sendTx.lock_time;
+ r['size'] = buf.length;
+ r['in'] = []
+ r['out'] = []
+
+ for (var i = 0; i < sendTx.ins.length; i++) {
+ var txin = sendTx.ins[i];
+ var hash = Crypto.util.base64ToBytes(txin.outpoint.hash);
+ var n = txin.outpoint.index;
+ var prev_out = {'hash': Crypto.util.bytesToHex(hash.reverse()), 'n': n};
+ var seq = txin.sequence;
+
+ if (n == 4294967295) {
+ var cb = Crypto.util.bytesToHex(txin.script.buffer);
+ r['in'].push({'prev_out': prev_out, 'coinbase' : cb, 'sequence':seq});
+ } else {
+ var ss = dumpScript(txin.script);
+ r['in'].push({'prev_out': prev_out, 'scriptSig' : ss, 'sequence':seq});
+ }
+ }
+
+ for (var i = 0; i < sendTx.outs.length; i++) {
+ var txout = sendTx.outs[i];
+ var bytes = txout.value.slice(0);
+ var fval = parseFloat(Bitcoin.Util.formatValue(bytes.reverse()));
+ var value = fval.toFixed(8);
+ var spk = dumpScript(txout.script);
+ r['out'].push({'value' : value, 'scriptPubKey': spk});
+ }
+
+ return JSON.stringify(r, null, 4);
+ };
+
+ this.fromBBE = function(text) {
+ //deserialize from Bitcoin Block Explorer format
+ var sendTx = new Bitcoin.Transaction();
+ var r = JSON.parse(text);
+ if (!r)
+ return sendTx;
+ var tx_ver = r['ver'];
+ var vin_sz = r['vin_sz'];
+
+ for (var i = 0; i < vin_sz; i++) {
+ var txi = r['in'][i];
+ var hash = Crypto.util.hexToBytes(txi['prev_out']['hash']);
+ var n = txi['prev_out']['n'];
+
+ if (txi['coinbase'])
+ var script = Crypto.util.hexToBytes(txi['coinbase']);
+ else
+ var script = parseScript(txi['scriptSig']);
+
+ var seq = txi['sequence'] === undefined ? 4294967295 : txi['sequence'];
+
+ var txin = new Bitcoin.TransactionIn({
+ outpoint: {
+ hash: Crypto.util.bytesToBase64(hash.reverse()),
+ index: n
+ },
+ script: new Bitcoin.Script(script),
+ sequence: seq
+ });
+ sendTx.addInput(txin);
+ }
+
+ var vout_sz = r['vout_sz'];
+
+ TX.removeOutputs();
+ for (var i = 0; i < vout_sz; i++) {
+ var txo = r['out'][i];
+ var fval = parseFloat(txo['value']);
+ var value = new BigInteger('' + Math.round(fval * 1e8), 10);
+ var script = parseScript(txo['scriptPubKey']);
+
+ if (value instanceof BigInteger) {
+ value = value.toByteArrayUnsigned().reverse();
+ while (value.length < 8) value.push(0);
+ }
+
+ var txout = new Bitcoin.TransactionOut({
+ value: value,
+ script: new Bitcoin.Script(script)
+ });
+
+ sendTx.addOutput(txout);
+ TX.addOutput(txo,fval);
+ }
+ sendTx.lock_time = r['lock_time'];
+ return sendTx;
+ };
+ return this;
+};
+
+function dumpScript(script) {
+ var out = [];
+ for (var i = 0; i < script.chunks.length; i++) {
+ var chunk = script.chunks[i];
+ var op = new Bitcoin.Opcode(chunk);
+ typeof chunk == 'number' ? out.push(op.toString()) :
+ out.push(Crypto.util.bytesToHex(chunk));
+ }
+ return out.join(' ');
+}
+
+// blockchain.info parser (adapted)
+// uses http://blockchain.info/unspent?active=
+function tx_parseBCI(data, address) {
+ var r = JSON.parse(data);
+ var txs = r.unspent_outputs;
+
+ if (!txs)
+ throw 'Not a BCI format';
+
+ delete unspenttxs;
+ var unspenttxs = {};
+ var balance = BigInteger.ZERO;
+ for (var i in txs) {
+ var o = txs[i];
+ var lilendHash = o.tx_hash;
+
+ //convert script back to BBE-compatible text
+ var script = dumpScript( new Bitcoin.Script(Crypto.util.hexToBytes(o.script)) );
+
+ var value = new BigInteger('' + o.value, 10);
+ if (!(lilendHash in unspenttxs))
+ unspenttxs[lilendHash] = {};
+ unspenttxs[lilendHash][o.tx_output_n] = {amount: value, script: script};
+ balance = balance.add(value);
+ }
+ return {balance:balance, unspenttxs:unspenttxs};
+}
+
+// blockexplorer parser (by BTCurious)
+// uses http://blockexplorer.com/q/mytransactions/
+// --->8---
+function parseTxs(data, address) {
+
+ var address = address.toString();
+ var tmp = JSON.parse(data);
+ var txs = [];
+ for (var a in tmp) {
+ if (!tmp.hasOwnProperty(a))
+ continue;
+ txs.push(tmp[a]);
+ }
+
+ // Sort chronologically
+ txs.sort(function(a,b) {
+ if (a.time > b.time) return 1;
+ else if (a.time < b.time) return -1;
+ return 0;
+ })
+
+ delete unspenttxs;
+ var unspenttxs = {}; // { "": {