Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Code refactor

  • Loading branch information...
commit 0963700d24279fc686c83fdca08f00d8dd86b0b9 1 parent 716a262
Gerard Braad — 吉拉德 authored
186 code.js
View
@@ -1,22 +1,55 @@
+// A simple authentication application written in HTML
+// Copyright (C) 2012 Gerard Braad
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+StorageService = {}
+
+StorageService.setObject = function(key, value) {
+ localStorage.setItem(key, JSON.stringify(value));
+}
+StorageService.getObject = function(key) {
+ var value = localStorage.getItem(key);
+ return value && JSON.parse(value);
+}
+
+StorageService.isSupported = function() {
+ return typeof (Storage) !== "undefined";
+}
+
+
// Originally based on the JavaScript implementation as provided by Tin Isles:
// http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
-function dec2hex(s) {
+KeyUtilities = {}
+
+KeyUtilities.dec2hex = function(s) {
return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}
-
-function hex2dec(s) {
+KeyUtilities.hex2dec = function(s) {
return parseInt(s, 16);
}
-function base32tohex(base32) {
+KeyUtilities.base32tohex = function(base32) {
var base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
var bits = "";
var hex = "";
for (var i = 0; i < base32.length; i++) {
var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
- bits += leftpad(val.toString(2), 5, '0');
+ bits += KeyUtilities.leftpad(val.toString(2), 5, '0');
}
// leftpad bits with 0 until length is a multiple of 4
@@ -31,83 +64,138 @@ function base32tohex(base32) {
return hex;
}
-function leftpad(str, len, pad) {
+KeyUtilities.leftpad = function(str, len, pad) {
if (len + 1 >= str.length) {
str = Array(len + 1 - str.length).join(pad) + str;
}
return str;
}
-function updateOtp(secret) {
- var key = base32tohex(secret);
+KeyUtilities.generate = function(secret) {
+ var key = KeyUtilities.base32tohex(secret);
var epoch = Math.round(new Date().getTime() / 1000.0);
- var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
+ var time = KeyUtilities.leftpad(KeyUtilities.dec2hex(Math.floor(epoch / 30)), 16, '0');
var hmacObj = new jsSHA(time, "HEX");
var hmac = hmacObj.getHMAC(key, "HEX", "SHA-1", "HEX");
if (hmac != 'KEY MUST BE IN BYTE INCREMENTS') {
- var offset = hex2dec(hmac.substring(hmac.length - 1));
+ var offset = KeyUtilities.hex2dec(hmac.substring(hmac.length - 1));
// Debug
//var part1 = hmac.substr(0, offset * 2);
//var part2 = hmac.substr(offset * 2, 8);
//var part3 = hmac.substr(offset * 2 + 8, hmac.length - offset);
}
- var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
+ var otp = (KeyUtilities.hex2dec(hmac.substr(offset * 2, 8)) & KeyUtilities.hex2dec('7fffffff')) + '';
return (otp).substr(otp.length - 6, 6).toString();
}
-function timerTick() {
+
+KeysController = {}
+
+KeysController.init = function() {
+ // Check if local storage is supported
+ if (StorageService.isSupported()) {
+ if (!StorageService.getObject('accounts')) {
+ KeysController.addAccount('alice@google.com', 'JBSWY3DPEHPK3PXP');
+ }
+
+ KeysController.updateKeys();
+ setInterval(KeysController.timerTick, 1000);
+ } else {
+ // No support for localStorage
+ $('#updatingIn').text("x");
+ $('#accountsHeader').text("No Storage support");
+ }
+
+ // Bind to keypress event for the input
+ $('#add').click(function () {
+ var name = $('#keyAccount').val();
+ var secret = $('#keySecret').val();
+ if(secret != '') {
+ KeysController.addAccount(name, secret);
+ }
+ });
+}
+
+KeysController.timerTick = function() {
var epoch = Math.round(new Date().getTime() / 1000.0);
var countDown = 30 - (epoch % 30);
if (epoch % 30 == 0) {
- updateKeys();
+ KeysController.updateKeys();
}
$('#updatingIn').text(countDown);
}
-function updateKeys() {
+KeysController.updateKeys = function() {
var accountList = $('#accounts');
// Remove all except the first line
accountList.find("li:gt(0)").remove();
- $.each(getObject('accounts'), function (index, account) {
- var key = updateOtp(account.secret);
+ $.each(StorageService.getObject('accounts'), function (index, account) {
+ var key = KeyUtilities.generate(account.secret);
+
+ // Construct HTML
var delLink = $('<a href="#"></a>');
delLink.click(function () {
- deleteAccount(index)
+ KeysController.deleteAccount(index)
});
var detLink = $('<a href="#"><h3>' + key + '</h3><p>' + account.name + '</p></a>');
var accElem = $('<li>').append(detLink).append(delLink);
-
+ // Add HTML element
accountList.append(accElem);
});
accountList.listview('refresh');
}
-function deleteAccount(index) {
- var accounts = getObject('accounts');
+KeysController.deleteAccount = function(index) {
+ // Retrieve current objects
+ var accounts = StorageService.getObject('accounts');
accounts.splice(index, 1);
+
// Persist in localstorage
- setObject('accounts', accounts);
+ StorageService.setObject('accounts', accounts);
- updateKeys();
+ KeysController.updateKeys();
}
-function setObject(key, value) {
- localStorage.setItem(key, JSON.stringify(value));
-}
+KeysController.addAccount = function(name, secret) {
+ if(secret == '') {
+ // Bailout
+ return false;
+ }
-function getObject(key) {
- var value = localStorage.getItem(key);
- return value && JSON.parse(value);
+ // Construct JSON object
+ var account = {
+ 'name': name,
+ 'secret': secret
+ };
+
+ // Get existing list of objects
+ var accounts = StorageService.getObject('accounts');
+ if (!accounts) {
+ accounts = [];
+ }
+
+ // Add to list
+ accounts.push(account);
+
+ // Empty fields
+ $('#keyAccount').val('');
+ $('#keySecret').val('');
+
+ // Persist in localstorage
+ StorageService.setObject('accounts', accounts);
+
+ KeysController.updateKeys();
+
+ return true;
}
+
// Main function
$(document).bind('pagecreate', function() {
- //new GAuth.Controller();
-
// Background styling for dialogs
$('div[data-role="dialog"]').live('pagebeforeshow', function(e, ui) {
ui.prevPage.addClass("ui-dialog-background");
@@ -117,41 +205,5 @@ $(document).bind('pagecreate', function() {
$(".ui-dialog-background ").removeClass("ui-dialog-background");
});
- // Check if local storage is supported
- if (typeof (Storage) !== "undefined") {
- if (!getObject('accounts')) {
- // Default information
- var account = [{
- 'name': 'alice@google.com',
- 'secret': 'JBSWY3DPEHPK3PXP'
- }, ];
- setObject('accounts', account);
- }
-
- updateKeys();
- setInterval(timerTick, 1000);
- } else {
- // No support for localStorage
- $('#updatingIn').text("x");
- $('#account').text("No Storage support");
- }
-
- $('#save').click(function () {
- // Save in local storage
- var account = {
- 'name': $('#keyAccount').val(),
- 'secret': $('#keySecret').val()
- };
- var accounts = getObject('accounts');
- accounts.push(account);
-
- // Empty fields
- $('#keyAccount').val('');
- $('#keySecret').val('');
-
- // Persist in localstorage
- setObject('accounts', accounts);
-
- updateKeys();
- });
+ KeysController.init();
});
BIN  favicon.ico
View
Binary file not shown
BIN  images/icon-48.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 index.html
View
@@ -1,6 +1,8 @@
<html>
<head>
<title>GAuth Authenticator</title>
+ <meta name="HandheldFriendly" content="True">
+ <meta http-equiv="cleartype" content="on">
<script src="jquery-1.7.2.min.js"></script>
<script src="init.js"></script>
<script src="jquery.mobile-1.1.0.min.js"></script>
@@ -8,6 +10,8 @@
<script src="code.js"></script>
<link rel="stylesheet" href="jquery.mobile-1.1.0.min.css" />
<link rel="stylesheet" href="styling.css" />
+ <link rel="shortcut icon" href="./favicon.ico" />
+ <link rel="apple-touch-icon" href="./images/icon-48.png" />
</head>
<body>
<div data-role="page" id="main">
@@ -18,11 +22,16 @@
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="g" data-split-theme="d" data-split-icon="delete" id="accounts">
- <li data-role="list-divider">One-time passwords<span class="ui-li-count" id='updatingIn'>..</span></li>
+ <li id="accountsHeader" data-role="list-divider">One-time passwords<span class="ui-li-count" id='updatingIn'>..</span></li>
</ul>
+
+ <a href="#settings" data-role="button" data-rel="dialog">Settings</a>
+ </div>
+
+ <div data-role="footer">
+ <h1>@gbraad</h1>
</div>
- <a href="#settings" data-role="button" data-rel="dialog">Settings</a>
</div>
<div data-role="page" id="settings">
@@ -39,7 +48,7 @@
</form>
</p>
<p>
- <a href="#main" data-role="button" data-rel="back" data-theme="b" id="save">Add</a>
+ <a href="#main" data-role="button" data-rel="back" data-theme="b" id="add">Add</a>
<a href="#main" data-role="button" data-rel="back" data-theme="c">Cancel</a>
</p>
</div>
19 styling.css
View
@@ -13,3 +13,22 @@
min-height: 100% !important;
background: transparent !important;
}
+
+div[data-role="header"], div[data-role="footer"] {
+ width: 100%;
+}
+
+div[data-role="header"] {
+ top: 0px;
+}
+
+div[data-role="footer"] {
+ position: absolute;
+ bottom: 0px;
+ display: none;
+}
+
+div[data-role="content"] {
+ height: 100%;
+ margin: 0 auto 0 auto;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.