summaryrefslogtreecommitdiff
path: root/wxgui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wxgui.cpp')
-rw-r--r--wxgui.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/wxgui.cpp b/wxgui.cpp
new file mode 100644
index 0000000..6a6873a
--- /dev/null
+++ b/wxgui.cpp
@@ -0,0 +1,216 @@
+#include "totpgen.h"
+
+#ifdef _WIN32
+static const std::string path_separator = "\\";
+static const std::string config_dir_name = "TOTPGen";
+#else
+static const std::string path_separator = "/";
+static const std::string config_dir_name = ".totpgen";
+#endif
+
+IMPLEMENT_APP(TOTPGenGUI)
+
+bool TOTPGenGUI::OnInit()
+{
+ TOTPGen *MainAppFrame = new TOTPGen();
+ MainAppFrame->Show(true);
+ return true;
+}
+
+TOTPGen::TOTPGen() : wxFrame(nullptr, wxID_ANY, wxT("TOTP Generator"),
+ wxDefaultPosition, wxSize(320,240),
+ wxDEFAULT_FRAME_STYLE | wxRESIZE_BORDER)
+{
+ MainWindow = new wxPanel(this, wxID_ANY);
+ MainSizer = new wxBoxSizer(wxVERTICAL);
+
+ Locked = true;
+
+ wxString UserConfigDir = wxStandardPaths::Get().GetUserConfigDir();
+
+ wxString AppConfigDir = UserConfigDir + path_separator + config_dir_name;
+ if (!wxDirExists(AppConfigDir)) {
+ wxMkdir(AppConfigDir);
+ }
+
+ SecretFile = AppConfigDir + path_separator + "secret.dat";
+
+ TOTPField = new wxStaticText(MainWindow, wxID_ANY,
+ wxEmptyString, wxDefaultPosition,
+ wxDefaultSize, wxTE_CENTER);
+ wxFont LabelFont(48, wxFONTFAMILY_TELETYPE,
+ wxFONTSTYLE_NORMAL,
+ wxFONTWEIGHT_NORMAL);
+ TOTPField->SetFont(LabelFont);
+ TOTPField->SetLabel(" ");
+
+ TextSizer = new wxBoxSizer(wxHORIZONTAL);
+ TextSizer->Add(TOTPField, 2, wxCENTER);
+
+ CountdownGauge = new wxGauge(MainWindow, wxID_ANY, 30, wxPoint(50, 50));
+ CountdownTimer = new wxTimer(MainWindow, wxID_ANY);
+ CountdownTimer->Start(1000);
+
+ UpdateSecretButton = new wxButton(MainWindow, wxID_OK, wxT("Set Key"));
+ UpdateSecretButton->Bind(wxEVT_BUTTON, &TOTPGen::UpdateSecret, this);
+
+ UnlockButton = new wxButton(MainWindow, wxID_CLEAR, wxT("Unlock"));
+ UnlockButton->Bind(wxEVT_BUTTON, &TOTPGen::Unlock, this);
+ if (!wxFileExists(SecretFile)) {
+ UnlockButton->Enable(false);
+ }
+
+ ButtonSizer_Upper = new wxBoxSizer(wxHORIZONTAL);
+ ButtonSizer_Upper->Add(UpdateSecretButton, 2, wxEXPAND | wxALL);
+ ButtonSizer_Upper->Add(UnlockButton, 2, wxEXPAND | wxALL);
+
+ CopyButton = new wxButton(MainWindow, wxID_COPY, wxT("Copy"));
+ CopyButton->Bind(wxEVT_BUTTON, &TOTPGen::CopyText, this);
+ if (Locked) {
+ CopyButton->Enable(false);
+ }
+
+ QuitButton = new wxButton(MainWindow, wxID_EXIT, wxT("Exit"));
+ QuitButton->Bind(wxEVT_BUTTON, &TOTPGen::OnExit, this);
+
+ ButtonSizer_Lower = new wxBoxSizer(wxHORIZONTAL);
+ ButtonSizer_Lower->Add(CopyButton, 2, wxEXPAND | wxALL);
+ ButtonSizer_Lower->Add(QuitButton, 2, wxEXPAND | wxALL);
+
+ MainSizer->Add(TextSizer, 2, wxCENTER | wxALIGN_CENTER);
+ MainSizer->Add(CountdownGauge, 2, wxEXPAND | wxALL);
+ MainSizer->Add(ButtonSizer_Upper, 2, wxEXPAND | wxALL);
+ MainSizer->Add(ButtonSizer_Lower, 2, wxEXPAND | wxALL);
+
+ MainWindow->SetSizer(MainSizer);
+}
+
+void TOTPGen::OnExit(wxCommandEvent& WXUNUSED(event))
+{
+ Close(true);
+}
+
+bool TOTPGen::IsBase32(std::string& str)
+{
+ std::unordered_set<char> Base32Chars(base32.begin(), base32.end());
+
+ for (char c: str) {
+ if (Base32Chars.find(c) == Base32Chars.end()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TOTPGen::UpdateSecret(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryDialog SecretPrompt(this, wxT("Please enter the base 32 token."),
+ wxT("Secret Entry"), wxEmptyString);
+
+ std::string Secret_New;
+ if (SecretPrompt.ShowModal() == wxID_OK) {
+ Secret_New = SecretPrompt.GetValue().MakeUpper().ToStdString();
+ if (!IsBase32(Secret_New)) {
+ wxMessageBox(wxT("Base 32 token contains invalid characters.\n"
+ "Only the following are permissible: \n" + base32),
+ wxT("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+ }
+
+ wxPasswordEntryDialog PasswordPrompt(this, wxT("Please enter a new passphrase\n"
+ "to encrypt the secret token."),
+ wxT("Passphrase Entry"), wxEmptyString);
+
+ wxPasswordEntryDialog ConfirmPrompt(this, wxT("Please confirm the passphrase."),
+ wxT("Passphrase Entry"), wxEmptyString);
+
+
+ if ((PasswordPrompt.ShowModal() == wxID_OK)
+ && (ConfirmPrompt.ShowModal() == wxID_OK)) {
+ if (PasswordPrompt.GetValue() == ConfirmPrompt.GetValue()) {
+ Passphrase = PasswordPrompt.GetValue();
+ }
+ else {
+ wxMessageBox(wxT("Passphrases did not match - try again"),
+ wxT("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+ }
+ else {
+ return;
+ }
+
+
+ if (!GenTOTP(Secret_New)) {
+ wxMessageBox(wxT("Could not generate TOTP - bad token?"),
+ wxT("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+
+ Secret = Secret_New;
+ EncryptSecret(Secret);
+
+ if (Locked) {
+ Locked = false;
+
+ MainWindow->Connect(CountdownTimer->GetId(), wxEVT_TIMER,
+ wxTimerEventHandler(TOTPGen::UpdateStatus),
+ NULL, this);
+
+ CopyButton->Enable(true);
+ UnlockButton->Enable(false);
+ }
+
+ return;
+}
+
+void TOTPGen::Unlock(wxCommandEvent& WXUNUSED(event))
+{
+ wxPasswordEntryDialog PasswordPrompt(this, wxT("Please enter your passphrase."),
+ wxT("Passphrase Entry"), wxEmptyString);
+
+ if (PasswordPrompt.ShowModal() == wxID_OK) {
+ Passphrase = PasswordPrompt.GetValue();
+ }
+
+ if (!DecryptSecret()) {
+ wxMessageBox(wxT("Could not unlock base 32 token,\n"
+ "bad passphrase or corrupt file?"),
+ wxT("Error"), wxOK | wxICON_ERROR);
+ return;
+ }
+
+ MainWindow->Connect(CountdownTimer->GetId(), wxEVT_TIMER,
+ wxTimerEventHandler(TOTPGen::UpdateStatus),
+ NULL, this);
+
+ Locked = false;
+
+ CopyButton->Enable(true);
+ UnlockButton->Enable(false);
+
+ GenTOTP(Secret);
+}
+
+void TOTPGen::UpdateStatus(wxTimerEvent& WXUNUSED(event))
+{
+ unsigned char CounterValue = 29 - ((time(NULL) - 1) % 30);
+
+ CountdownGauge->SetValue(CounterValue);
+
+ if (CounterValue == 0) {
+ GenTOTP(Secret);
+ }
+}
+
+void TOTPGen::CopyText(wxCommandEvent& WXUNUSED(event))
+{
+ wxString ToCopy = TOTPField->GetLabel();
+
+ if (wxTheClipboard->Open() && !Locked) {
+ wxTheClipboard->SetData(new wxTextDataObject(ToCopy));
+ wxTheClipboard->Close();
+ }
+} \ No newline at end of file