Commit 96653498 authored by Jonah Brüchert's avatar Jonah Brüchert 🌳

Add OTP token support

parent ff2a2b71
......@@ -5,6 +5,7 @@
#include <QDateTime>
#include <QDir>
#include <QCryptographicHash>
#include <QUrlQuery>
#include <KLocalizedString>
#include <KContacts/Addressee>
......@@ -31,6 +32,31 @@ bool Qrca::isVCard(const QString &text) {
return (text.startsWith("BEGIN:VCARD") && text.trimmed().endsWith("END:VCARD"));
}
bool Qrca::isOtpToken(const QString &text)
{
if (text.startsWith("otpauth")) {
QUrl uri(text);
if (uri.isValid() && (uri.host() == "totp" || uri.host() == "hotp")) {
QUrlQuery query(uri.query());
return query.hasQueryItem("secret");
}
}
return false;
}
Qrca::ContentType Qrca::identifyContentType(const QString &text)
{
if (isUrl(text))
return ContentType::Url;
else if (isVCard(text))
return ContentType::VCard;
else if (isOtpToken(text))
return ContentType::OtpToken;
return ContentType::Text;
}
void Qrca::saveVCard(const QString &text) {
QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ ("/kpeoplevcard");
......
......@@ -6,20 +6,36 @@
class Qrca : public QObject
{
Q_OBJECT
Q_OBJECT
public:
enum ContentType {
Url,
VCard,
OtpToken,
Text
};
Q_ENUM(ContentType)
Qrca();
Q_INVOKABLE bool isUrl(const QString &text);
Q_INVOKABLE bool isVCard(const QString &text);
static Q_INVOKABLE ContentType identifyContentType(const QString &text);
Q_INVOKABLE QImage encode(const QString &text, const int &width);
Q_INVOKABLE QString save(const QImage &image);
Q_INVOKABLE void saveVCard(const QString &text);
Q_INVOKABLE QString getVCardName(const QString &text);
static Q_INVOKABLE QString save(const QImage &image);
static Q_INVOKABLE void saveVCard(const QString &text);
static Q_INVOKABLE QString getVCardName(const QString &text);
signals:
/**
* Show passive notification
*/
void passiveNotificationRequested(QString text);
private:
static bool isUrl(const QString &text);
static bool isVCard(const QString &text);
static bool isOtpToken(const QString &text);
};
#endif // QRCA_H
......@@ -52,8 +52,7 @@ Kirigami.Page {
id: resultSheet
property string tag
property bool isLink: false
property bool isVCard: false
property int contentType
ColumnLayout {
Kirigami.Heading {
......@@ -63,19 +62,23 @@ Kirigami.Page {
Controls.Label {
text: {
if (resultSheet.isLink)
i18n("The following tag has been found. Do you want to open the url?")
else if (resultSheet.isVCard)
i18n("A contact has been found, do you want to save it?")
else
i18n("The following tag has been found.")
switch (resultSheet.contentType) {
case Qrca.Url:
return i18n("The following tag has been found. Do you want to open the url?");
case Qrca.VCard:
return i18n("A contact has been found, do you want to save it?");
case Qrca.OtpToken:
return i18n("An OTP URI has been found. Do you want to open your OTP client?");
default:
return i18n("The following tag has been found.");
}
}
wrapMode: Text.WordWrap
elide: Text.ElideRight
Layout.fillWidth: true
}
Controls.TextArea {
visible: !resultSheet.isLink && !resultSheet.isVCard
visible: !resultSheet.contentType === Qrca.Url && !resultSheet.contentType === Qrca.VCard
text: resultSheet.tag
wrapMode: Text.WordWrap
Layout.fillWidth: true
......@@ -83,21 +86,25 @@ Kirigami.Page {
selectByMouse: true
}
Controls.Label {
visible: resultSheet.isLink
visible: resultSheet.contentType === Qrca.Url
text: asLink(resultSheet.tag)
Layout.fillWidth: true
}
Controls.Label {
visible: resultSheet.isVCard
visible: resultSheet.contentType === Qrca.VCard
text: i18n("Name: ") + Qrca.getVCardName(resultSheet.tag)
}
RowLayout {
Controls.Button {
text: resultSheet.isVCard ? i18n("Save contact") : i18n("Open")
enabled: resultSheet.isLink || resultSheet.isVCard
text: resultSheet.contentType === Qrca.VCard ? i18n("Save contact") : i18n("Open")
enabled: {
resultSheet.contentType === Qrca.Url
|| resultSheet.contentType === Qrca.VCard
|| resultSheet.contentType === Qrca.OtpToken
}
onClicked: {
if (resultSheet.isVCard)
if (resultSheet.contentType === Qrca.VCard)
Qrca.saveVCard(resultSheet.tag)
else
Qt.openUrlExternally(resultSheet.tag)
......@@ -127,8 +134,7 @@ Kirigami.Page {
id: scannerFilter
onScanningSucceeded: {
resultSheet.tag = result
resultSheet.isLink = Qrca.isUrl(result)
resultSheet.isVCard = Qrca.isVCard(result)
resultSheet.contentType = Qrca.identifyContentType(result)
if (!resultSheet.sheetOpen)
resultSheet.open()
}
......
......@@ -59,7 +59,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
engine.rootContext()->setContextProperty("encodeText", parser.value("encode"));
engine.rootContext()->setContextProperty(QStringLiteral("qrcaAboutData"), QVariant::fromValue(KAboutData::applicationData()));
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
if (engine.rootObjects().isEmpty()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment