/* * Copyright (c) 2013, Stefan Brand * 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("", "2", 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);"); }); } else if (db.version == "1.0") { // Upgrade DB Schema to Version 2 db.changeVersion("1.0", "2", 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;"); }); } } 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;"); for (var i=0; i < res.rows.length; i++) { mainPage.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); if (res.rows.item(i).fav) mainPage.setCoverOTP(res.rows.item(i).title, res.rows.item(i).secret, res.rows.item(i).type); } }); } // 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, }); } }); if (otpList.length > 0) { return(JSON.stringify({"app": "sailotp", "version": 1, "otplist": otpList})); } else { return("") } } // Read Values from JSON and put them into the DB function json2db(jsonString) { var json = JSON.parse(jsonString); if (json.version != "1" && json.app != "sailotp" ) { console.log("Unrecognized JSON format"); 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) { addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter); } } parentPage.refreshOTPList(); } else { console.log("File contains no Items"); return(false); } } } // Add a new OTP function addOTP(title, secret, type, counter) { 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]); 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) { if (checkOTP(title, secret)) { console.log("Token " + title + " is already in DB"); } else { tx.executeSql("UPDATE OTPStorage SET title=?, secret=?, type=?, counter=? WHERE title=? and secret=?;", [title, secret, type, counter, oldtitle, oldsecret]); 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; }