diff --git a/.gitignore b/.gitignore index 88f42f3..9a93b79 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,12 @@ *.pro.user *.pro.user.* *.autosave +*.o +moc_* +documentation.list +harbour-sailotp +RPMS +Makefile rpm/harbour-sailotp.spec rpm/harbour-sailotp.spec.* translations/*.qm diff --git a/qml/cover/CoverPage.qml b/qml/cover/CoverPage.qml index ba7d9a0..09a6bff 100644 --- a/qml/cover/CoverPage.qml +++ b/qml/cover/CoverPage.qml @@ -45,7 +45,7 @@ CoverBackground { var seconds = (curDate.getSeconds() + appWin.coverDiff) % 30 if (lOTP.text == "------" || seconds == 0 || (curDate.getTime() - lastUpdated > 2000)) { - appWin.coverOTP = OTP.calcOTP(appWin.coverSecret, appWin.coverType, appWin.coverLen, appWin.coverDiff, 0); + appWin.coverOTP = OTP.calcOTP(appWin.coverSecret, appWin.coverType, appWin.coverLen, appWin.coverDiff, 0, appWin.coverPeriod); } // Change color of the OTP to red if less than 5 seconds left diff --git a/qml/harbour-sailotp.qml b/qml/harbour-sailotp.qml index 4e7f960..90585a2 100644 --- a/qml/harbour-sailotp.qml +++ b/qml/harbour-sailotp.qml @@ -45,6 +45,7 @@ ApplicationWindow property string coverOTP: "------" property int coverLen: 6 property int coverDiff: 0 + property int coverPeriod: 30 property int coverIndex: 0 // Global Listmodel for Tokens @@ -64,8 +65,8 @@ ApplicationWindow } // Add an entry to the list - function appendOTP(title, secret, type, counter, fav, len, diff) { - listModel.append({"secret": secret, "title": title, "fav": fav, "type": type, "counter": counter, "len": len, "diff": diff, "otp": "------", "itemVisible": true}); + function appendOTP(title, secret, type, counter, fav, len, diff, period) { + listModel.append({"secret": secret, "title": title, "fav": fav, "type": type, "counter": counter, "len": len, "diff": diff, "period": period, "otp": "------", "itemVisible": true}); } // Set the OTP shown on the Cover @@ -76,6 +77,7 @@ ApplicationWindow coverType = listModel.get(index).type; coverLen = listModel.get(index).len; coverDiff = listModel.get(index).diff; + coverPeriod = listModel.get(index).period; coverIndex = index; if (coverType == "TOTP") { coverOTP = "------"; } else { coverOTP = listModel.get(index).otp; } for (var i=0; i 0) { - return(JSON.stringify({"app": "sailotp", "version": 3, "otplist": otpList})); + return(JSON.stringify({"app": "sailotp", "version": 4, "otplist": otpList})); } else { return("") } @@ -122,7 +132,7 @@ function json2db(jsonString, error) { var json = JSON.parse(jsonString); error = ""; - if ((json.version != "1" || json.version != "2" || json.version != "3") && json.app != "sailotp" ) { + if ((json.version != "1" || json.version != "2" || json.version != "3" || json.version != "4") && json.app != "sailotp" ) { error = "Unrecognized format, file is not a SailOTP export"; return(false); } else { @@ -133,13 +143,15 @@ function json2db(jsonString, error) { 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, 6, 0); + addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, 0, 6, 0, 30); } else if (json.version == "2") { - addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort, 6, 0); - } else { - addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort, otpItem.len, otpItem.diff); + addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort, 6, 0, 30); + } else if (json.version == "3") { + addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort, otpItem.len, otpItem.diff, 30); + } else { + addOTP(otpItem.title, otpItem.secret, otpItem.type, otpItem.counter, otpItem.sort, otpItem.len, otpItem.diff, otpItem.period); } - } + } } parentPage.refreshOTPList(); return(true); @@ -151,7 +163,7 @@ function json2db(jsonString, error) { } // Add a new OTP -function addOTP(title, secret, type, counter, sort, len, diff) { +function addOTP(title, secret, type, counter, sort, len, diff, period) { var db = getDB(); db.transaction( @@ -159,7 +171,7 @@ function addOTP(title, secret, type, counter, sort, len, diff) { 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, len, diff]); + tx.executeSql("INSERT INTO OTPStorage VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?);", [title, secret, type, counter, 0, sort, len, diff, period]); console.log("Token " + title + " added."); } }); @@ -210,12 +222,12 @@ function resetFav(title, secret) { } // Change an existing OTP -function changeOTP(title, secret, type, counter, len, diff, oldtitle, oldsecret) { +function changeOTP(title, secret, type, counter, len, diff, period, oldtitle, oldsecret) { var db = getDB(); db.transaction( function(tx) { - tx.executeSql("UPDATE OTPStorage SET title=?, secret=?, type=?, counter=?, len=?, diff=? WHERE title=? and secret=?;", [title, secret, type, counter, len, diff, oldtitle, oldsecret]); + tx.executeSql("UPDATE OTPStorage SET title=?, secret=?, type=?, counter=?, len=?, diff=?, period=? WHERE title=? and secret=?;", [title, secret, type, counter, len, diff, period, oldtitle, oldsecret]); console.log("Token " + title + " modified."); } ); diff --git a/qml/pages/AddOTP.qml b/qml/pages/AddOTP.qml index f844708..f064ade 100644 --- a/qml/pages/AddOTP.qml +++ b/qml/pages/AddOTP.qml @@ -48,6 +48,7 @@ Dialog { property int paramLen: 6 property int paramDiff: 0 property int paramCounter: 1 // New Counters start at 1 + property int paramPeriod: 30 property bool paramNew: false function checkQR() { @@ -163,6 +164,20 @@ Dialog { EnterKey.iconSource: "image://theme/icon-m-enter-accept" EnterKey.onClicked: addOTP.accept() } + TextField { + id: otpPeriod + width: parent.width + visible: paramType == "TOTP" ? true : false + label: qsTr("Period (Seconds)") + text: paramPeriod + placeholderText: qsTr("Period (Seconds)") + focus: true + horizontalAlignment: TextInput.AlignLeft + validator: IntValidator {} + + EnterKey.iconSource: "image://theme/icon-m-enter-accept" + EnterKey.onClicked: addOTP.accept() + } TextField { id: otpCounter width: parent.width @@ -182,7 +197,7 @@ Dialog { } // Check if we can Save - canAccept: otpLabel.text.length > 0 && otpSecret.text.length >= 16 && otpSecret.acceptableInput && otpLen.text >= 1 && ((paramType == "TOTP" && otpDiff.text != "") || paramType == "TOTP_STEAM" || otpCounter.text.length > 0) ? true : false + canAccept: otpLabel.text.length > 0 && otpSecret.text.length >= 16 && otpSecret.acceptableInput && otpLen.text >= 1 && ((paramType == "TOTP" && otpDiff.text != "" && otpPeriod.text > 0) || paramType == "TOTP_STEAM" || otpCounter.text.length > 0) ? true : false // Save if page is Left with Add onDone: { @@ -190,10 +205,10 @@ Dialog { // Save the entry to the Config DB if (paramLabel != "" && paramKey != "" && !paramNew) { // Parameters where filled -> Change existing entry - DB.changeOTP(otpLabel.text, otpSecret.text, paramType, otpCounter.text, otpLen.text, otpDiff.text, paramLabel, paramKey) + DB.changeOTP(otpLabel.text, otpSecret.text, paramType, otpCounter.text, otpLen.text, otpDiff.text, otpPeriod.text, paramLabel, paramKey) } else { // There were no parameters -> Add new entry - DB.addOTP(otpLabel.text, otpSecret.text, paramType, otpCounter.text, appWin.listModel.count, otpLen.text, otpDiff.text); + DB.addOTP(otpLabel.text, otpSecret.text, paramType, otpCounter.text, appWin.listModel.count, otpLen.text, otpDiff.text, otpPeriod.text); } // Refresh the main Page diff --git a/qml/pages/MainView.qml b/qml/pages/MainView.qml index 9bac121..0f3f9b9 100644 --- a/qml/pages/MainView.qml +++ b/qml/pages/MainView.qml @@ -64,10 +64,10 @@ Page { for (var i=0; i 2000)) { - var curOTP = OTP.calcOTP(appWin.listModel.get(i).secret, appWin.listModel.get(i).type, appWin.listModel.get(i).len, appWin.listModel.get(i).diff, 0); + var curOTP = OTP.calcOTP(appWin.listModel.get(i).secret, appWin.listModel.get(i).type, appWin.listModel.get(i).len, appWin.listModel.get(i).diff, 0, appWin.listModel.get(i).period); appWin.listModel.setProperty(i, "otp", curOTP); } else if (appWin.coverType === "HOTP" && (curDate.getTime() - lastUpdated > 2000) && appWin.listModel.get(i).fav === 1) { // If we are coming back from the CoverPage update OTP value if current favourite is HOTP @@ -311,7 +311,7 @@ Page { MenuItem { text: qsTr("Edit") onClicked: { - pageStack.push(Qt.resolvedUrl("AddOTP.qml"), {parentPage: mainPage, paramLabel: title, paramKey: secret, paramType: type, paramLen: len, paramDiff: diff, paramCounter: DB.getCounter(title, secret, false)}) + pageStack.push(Qt.resolvedUrl("AddOTP.qml"), {parentPage: mainPage, paramLabel: title, paramKey: secret, paramType: type, paramLen: len, paramDiff: diff, paramCounter: DB.getCounter(title, secret, false), paramPeriod: period}) } } MenuItem {