mirror of
https://github.com/seiichiro0185/sailotp.git
synced 2024-11-01 09:38:26 +00:00
236 lines
7.5 KiB
JavaScript
236 lines
7.5 KiB
JavaScript
/*
|
|
* Copyright (c) 2013, Stefan Brand <seiichiro@seiichiro0185.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or other
|
|
* materials provided with the distribution.
|
|
*
|
|
* 3. The names of the contributors may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
.import QtQuick.LocalStorage 2.0 as LS
|
|
|
|
// Get DB Connection, Initialize or Upgrade DB
|
|
function getDB() {
|
|
try {
|
|
var db = LS.LocalStorage.openDatabaseSync("harbour-sailotp", "", "SailOTP Config Storage", 1000000);
|
|
|
|
if (db.version == "") {
|
|
// Initialize an empty DB, Create the Table
|
|
db.changeVersion("", "3",
|
|
function(tx) {
|
|
tx.executeSql("CREATE TABLE IF NOT EXISTS OTPStorage(title TEXT, secret TEXT, type TEXT DEFAULT 'TOPT', counter INTEGER DEFAULT 0, fav INTEGER DEFAULT 0, sort INTEGER DEFAULT 0);");
|
|
});
|
|
} else if (db.version == "1.0") {
|
|
// Upgrade DB Schema to Version 3
|
|
db.changeVersion("1.0", "3",
|
|
function(tx) {
|
|
tx.executeSql("ALTER TABLE OTPStorage ADD COLUMN type TEXT DEFAULT 'TOTP';");
|
|
tx.executeSql("ALTER TABLE OTPStorage ADD COLUMN counter INTEGER DEFAULT 0;");
|
|
tx.executeSql("ALTER TABLE OTPStorage ADD COLUMN fav INTEGER DEFAULT 0;");
|
|
tx.executeSql("ALTER TABLE OTPStorage ADD COLUMN sort INTEGER DEFAULT 0;");
|
|
});
|
|
} else if (db.version == "2") {
|
|
// Upgrade DB Schema to Version 3
|
|
db.changeVersion("2", "3",
|
|
function(tx) {
|
|
tx.executeSql("ALTER TABLE OTPStorage ADD COLUMN sort INTEGER DEFAULT 0;");
|
|
});
|
|
}
|
|
} catch (e) {
|
|
// DB Failed to open
|
|
console.log("Could not open DB: " + e);
|
|
}
|
|
|
|
return db;
|
|
}
|
|
|
|
// Get all OTPs into the list model
|
|
function getOTP() {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
var res = tx.executeSql("select * from OTPStorage order by sort;");
|
|
for (var i=0; i < res.rows.length; i++) {
|
|
appWin.appendOTP(res.rows.item(i).title, res.rows.item(i).secret, res.rows.item(i).type, res.rows.item(i).counter, res.rows.item(i).fav, res.rows.item(i).sort);
|
|
if (res.rows.item(i).fav) appWin.setCover(i);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get all OTP Values and put them into a JSON-Object
|
|
function db2json() {
|
|
var db = getDB();
|
|
var otpList = [];
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
var res = tx.executeSql("select * from OTPStorage;");
|
|
for (var i=0; i < res.rows.length; i++) {
|
|
otpList.push({
|
|
"title": res.rows.item(i).title,
|
|
"secret": res.rows.item(i).secret,
|
|
"type": res.rows.item(i).type,
|
|
"counter": res.rows.item(i).counter,
|
|
"sort": res.rows.item(i).sort,
|
|
});
|
|
}
|
|
});
|
|
|
|
if (otpList.length > 0) {
|
|
return(JSON.stringify({"app": "sailotp", "version": 2, "otplist": otpList}));
|
|
} else {
|
|
return("")
|
|
}
|
|
}
|
|
|
|
// Read Values from JSON and put them into the DB
|
|
function json2db(jsonString, error) {
|
|
var json = JSON.parse(jsonString);
|
|
error = "";
|
|
|
|
if ((json.version != "1" || json.version != "2") && json.app != "sailotp" ) {
|
|
error = "Unrecognized format, file is not a SailOTP export";
|
|
return(false);
|
|
} else {
|
|
var otpList = [];
|
|
otpList = json.otplist;
|
|
if (otpList.length > 0) {
|
|
while(otpList.length > 0) {
|
|
var otpItem = otpList.shift();
|
|
if (otpItem.title != "" & otpItem.secret.length >= 16) {
|
|
if (json.version == "1") {
|
|
addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, 0);
|
|
} else {
|
|
addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort);
|
|
}
|
|
}
|
|
}
|
|
parentPage.refreshOTPList();
|
|
return(true);
|
|
} else {
|
|
error = "File contains no Tokens";
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add a new OTP
|
|
function addOTP(title, secret, type, counter, sort) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
if (checkOTP(title, secret)) {
|
|
console.log("Token " + title + " is already in DB");
|
|
} else {
|
|
tx.executeSql("INSERT INTO OTPStorage VALUES(?, ?, ?, ?, ?, ?);", [title, secret, type, counter, 0, sort]);
|
|
console.log("Token " + title + " added.");
|
|
}
|
|
});
|
|
}
|
|
|
|
// Check if an OTP Token already exists in the DB
|
|
function checkOTP(title, secret) {
|
|
var db = getDB();
|
|
var res
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
res = tx.executeSql("select title FROM OTPStorage WHERE title=? and secret=?;", [title, secret]);
|
|
});
|
|
|
|
return res.rows.length > 0 ? true : false
|
|
}
|
|
|
|
// Remove an existing OTP
|
|
function removeOTP(title, secret) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
tx.executeSql("DELETE FROM OTPStorage WHERE title=? and secret=?;", [title, secret]);
|
|
});
|
|
}
|
|
|
|
// Set OTP to favourite
|
|
function setFav(title, secret) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
tx.executeSql("UPDATE OTPStorage set fav = 0");
|
|
tx.executeSql("UPDATE OTPStorage set fav = 1 WHERE title=? and secret=?;", [title, secret]);
|
|
});
|
|
}
|
|
|
|
// Reset favourite Flag for OTP
|
|
function resetFav(title, secret) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
tx.executeSql("UPDATE OTPStorage set fav = 0");
|
|
});
|
|
}
|
|
|
|
// Change an existing OTP
|
|
function changeOTP(title, secret, type, counter, oldtitle, oldsecret) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
tx.executeSql("UPDATE OTPStorage SET title=?, secret=?, type=?, counter=? WHERE title=? and secret=?;", [title, secret, type, counter, oldtitle, oldsecret]);
|
|
console.log("Token " + title + " modified.");
|
|
}
|
|
);
|
|
}
|
|
|
|
function changeOTPSort(title, secret, sort) {
|
|
var db = getDB();
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
if (!checkOTP(title, secret)) {
|
|
console.log("Token " + title + " is not in DB");
|
|
} else {
|
|
tx.executeSql("UPDATE OTPStorage SET sort=? WHERE title=? and secret=?;", [sort, title, secret]);
|
|
console.log("Token " + title + " modified.");
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get the counter for a HOTP value, incerment the counter on request
|
|
function getCounter(title, secret, increment) {
|
|
var db = getDB();
|
|
|
|
var res = "";
|
|
|
|
db.transaction(
|
|
function(tx) {
|
|
res = tx.executeSql("SELECT counter FROM OTPStorage where title=? and secret=?;", [title, secret]);
|
|
if (increment) tx.executeSql("UPDATE OTPStorage set counter=counter+1 WHERE title=? and secret=?;", [title, secret]);
|
|
});
|
|
|
|
return res.rows.item(0).counter;
|
|
}
|