using Microsoft.Win32; using SimPas2_Windows.Managers; using System.Diagnostics; using System.Globalization; using System.Net; using System.Xml.Linq; using static System.Net.WebRequestMethods; namespace SimPas2_Windows { public partial class SimPas2 : Form { private readonly PasswordManager mPassMan; private readonly GeneratorManager mGenMan; private readonly OtpManager mOtpMan; private readonly PinManager mPinMan; private readonly NoteManager mNoteMan; private readonly QaManager mQaMan; private readonly CreditcardManager mCcMan; private readonly CryptoManager mCryptoMan; private readonly CultureInfo cultureInfo; private static readonly string mAppDataPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "076Soft", "SimPas"); private static readonly string mDatabasePath = Path.Combine(mAppDataPath, "SimPas.db"); private readonly byte[] mEncryptionKey; private System.Windows.Forms.Timer otpTimer; private string mPwKeyword; private string mOtpKeyword; private string mPinKeyword; private string mNoteKeyword; private string mQaKeyword; private string mCcKeyword; private string mCryptoKeyword; private string mJpLang; public SimPas2() { using (MasterPasswordForm masterForm = new MasterPasswordForm(mDatabasePath)) { if (masterForm.ShowDialog() != DialogResult.OK) { Environment.Exit(0); } mEncryptionKey = masterForm.EncryptionKey; } cultureInfo = Thread.CurrentThread.CurrentUICulture; InitializeComponent(); mPassMan = new PasswordManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mGenMan = new GeneratorManager(); mOtpMan = new OtpManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mPinMan = new PinManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mNoteMan = new NoteManager(mDatabasePath, cultureInfo.Name); mQaMan = new QaManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mCcMan = new CreditcardManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mCryptoMan = new CryptoManager(mDatabasePath, mEncryptionKey, cultureInfo.Name); mPwKeyword = ""; mOtpKeyword = ""; mPinKeyword = ""; mNoteKeyword = ""; mQaKeyword = ""; mCcKeyword = ""; mCryptoKeyword = ""; mJpLang = "ja-JP"; InitializeUI(); ApplySystemTheme(); LoadPasswords(mPwKeyword); LoadOtps(mOtpKeyword); LoadPins(mPinKeyword); LoadNotes(mNoteKeyword); LoadQas(mQaKeyword); LoadCcs(mCcKeyword); LoadCryptos(mCryptoKeyword); otpTimer = new System.Windows.Forms.Timer { Interval = 1000 }; otpTimer.Tick += OtpTimer_Tick; otpTimer.Start(); } private void InitializeUI() { // Window this.FormBorderStyle = FormBorderStyle.FixedSingle; this.MaximizeBox = false; // Password tab tab order pwListbox.TabIndex = 0; pwWebsiteTextbox.TabIndex = 1; pwUsernameTextbox.TabIndex = 2; pwPasswordTextbox.TabIndex = 3; pwNotesTextbox.TabIndex = 4; pwAddButton.TabIndex = 5; pwDeleteButton.TabIndex = 6; pwEditButton.TabIndex = 7; pwShowButton.TabIndex = 8; pwDoneButton.TabIndex = 9; pwCopyUsernameButton.TabIndex = 10; pwCopyPasswordButton.TabIndex = 11; // OTP tab tab order (otpAddNew) otpWebsiteTextbox1.TabIndex = 0; otpSecretTextbox.TabIndex = 1; otpIssuerTextbox.TabIndex = 2; otpAlgorithmCombobox.TabIndex = 3; otpDigitsNumeric.TabIndex = 4; otpDurationNumeric.TabIndex = 5; otpAddButton.TabIndex = 6; otpEditButton.TabIndex = 7; otpDoneButton.TabIndex = 8; // OTP tab tab order (otpAddOld) otpWebsiteTextbox2.TabIndex = 0; otpAuthTextbox.TabIndex = 1; otpAddLegacyButton.TabIndex = 2; // OTP tab main controls otpDeleteButton.TabIndex = 8; otpCopyButton.TabIndex = 9; otpListbox.TabIndex = 10; // PIN Codes tab tab order pinListbox.TabIndex = 0; pinWebsiteTextbox.TabIndex = 1; pinCodeTextbox.TabIndex = 2; pinNoteTextbox.TabIndex = 3; pinAddButton.TabIndex = 4; pinEditButton.TabIndex = 5; pinDeleteButton.TabIndex = 6; pinCopyButton.TabIndex = 7; pinShowButton.TabIndex = 8; pinDoneButton.TabIndex = 9; // Creditcard tab tab order ccListbox.TabIndex = 0; ccBrandCombobox.TabIndex = 1; ccNumberTextbox.TabIndex = 2; ccHolderTextbox.TabIndex = 3; ccExpirationTextbox.TabIndex = 4; ccCvcTextbox.TabIndex = 5; ccNotesTextbox.TabIndex = 6; ccAddButton.TabIndex = 7; ccEditButton.TabIndex = 8; ccDeleteButton.TabIndex = 9; ccShowButton.TabIndex = 10; ccDoneButton.TabIndex = 11; // Crypto tab tab order cryptoListbox.TabIndex = 0; cryptoCurrencyCombobox.TabIndex = 1; cryptoAddressTextbox.TabIndex = 2; cryptoSeedTextbox.TabIndex = 3; cryptoViewkeyTextbox.TabIndex = 4; cryptoSpendkeyTextbox.TabIndex = 5; cryptoHeightTextbox.TabIndex = 6; cryptoPasswordTextbox.TabIndex = 7; cryptoNotesTextbox.TabIndex = 8; cryptoAddButton.TabIndex = 9; cryptoEditButton.TabIndex = 10; cryptoDeleteButton.TabIndex = 11; cryptoShowButton.TabIndex = 12; cryptoDoneButton.TabIndex = 13; // Set initial button states genCopyButton.Enabled = false; pwAddButton.Enabled = true; pwEditButton.Enabled = false; pwDeleteButton.Enabled = false; pwCopyUsernameButton.Enabled = false; pwCopyPasswordButton.Enabled = false; pwShowButton.Enabled = false; pwDoneButton.Enabled = false; otpAddButton.Enabled = true; otpAddLegacyButton.Enabled = true; otpEditButton.Enabled = false; otpDeleteButton.Enabled = false; otpCopyButton.Enabled = false; otpDoneButton.Enabled = false; pinAddButton.Enabled = true; pinEditButton.Enabled = false; pinDeleteButton.Enabled = false; pinCopyButton.Enabled = false; pinShowButton.Enabled = false; pinDoneButton.Enabled = false; noteAddEditButton.Enabled = true; noteAddEditButton.Text = cultureInfo.Name == mJpLang ? "追加" : "Add"; noteTextbox.Enabled = false; noteDeleteButton.Enabled = false; noteSaveButton.Enabled = false; noteDoneButton.Enabled = false; qaAddButton.Enabled = true; qaDeleteButton.Enabled = false; qaEditButton.Enabled = false; qaCopyButton.Enabled = false; qaShowButton.Enabled = false; qaDoneButton.Enabled = false; ccAddButton.Enabled = true; ccDeleteButton.Enabled = false; ccEditButton.Enabled = false; ccShowButton.Enabled = false; ccDoneButton.Enabled = false; cryptoAddButton.Enabled = true; cryptoDeleteButton.Enabled = false; cryptoEditButton.Enabled = false; cryptoShowButton.Enabled = false; cryptoDoneButton.Enabled = false; // Initialize ComboBox and NumericUpDown otpAlgorithmCombobox.SelectedIndex = 0; // SHA1 otpDigitsNumeric.Value = 6; otpDurationNumeric.Value = 30; } private void ApplySystemTheme() { bool isDarkMode = Registry.GetValue( @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", 1)?.ToString() == "0"; Color backColor = isDarkMode ? Color.FromArgb(0x12, 0x0f, 0x12) : Color.FromArgb(0xfc, 0xfc, 0xfc); Color disableColor = isDarkMode ? Color.FromArgb(0xbd, 0xb4, 0xbd) : Color.FromArgb(0x74, 0x6c, 0x75); Color foreColor = isDarkMode ? Color.FromArgb(0xfc, 0xfc, 0xfc) : Color.FromArgb(0x23, 0x20, 0x23); Color tabBackColor = isDarkMode ? Color.FromArgb(0x23, 0x20, 0x23) : Color.FromArgb(0xf6, 0xf6, 0xf6); Color tabForeColor = isDarkMode ? Color.FromArgb(0xf6, 0xf6, 0xf6) : Color.FromArgb(0x23, 0x20, 0x23); Color elementBackColor = isDarkMode ? Color.FromArgb(0x44, 0x3b, 0x44) : Color.FromArgb(0xcf, 0xcb, 0xcf); Color elementForeColor = isDarkMode ? Color.FromArgb(0xcf, 0xcb, 0xcf) : Color.FromArgb(0x44, 0x3b, 0x44); this.BackColor = backColor; this.ForeColor = foreColor; foreach (Control control in this.Controls) { control.BackColor = elementBackColor; control.ForeColor = elementForeColor; if (control is TabControl tabControl) { tabControl.DrawMode = TabDrawMode.OwnerDrawFixed; tabControl.DrawItem += (sender, e) => { var tab = tabControl.TabPages[e.Index]; var g = e.Graphics; using (SolidBrush brush = new SolidBrush(tabBackColor)) { g.FillRectangle(brush, e.Bounds); } using (SolidBrush brush = new SolidBrush(tabForeColor)) { g.DrawString(tab.Text, tabControl.Font, brush, e.Bounds.Left + 5, e.Bounds.Top + 5); } if (e.State == DrawItemState.Selected) { using (Pen pen = new Pen(tabForeColor)) { g.DrawRectangle(pen, e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width - 4, e.Bounds.Height - 4); } } }; foreach (TabPage tabPage in tabControl.TabPages) { tabPage.BackColor = backColor; tabPage.ForeColor = foreColor; ApplyThemeToControls(tabPage.Controls, tabBackColor, disableColor, tabForeColor); } } } } private void ApplyThemeToControls(Control.ControlCollection controls, Color backColor, Color disableColor, Color foreColor) { foreach (Control control in controls) { if (!(control is Label)) { control.BackColor = backColor; } control.ForeColor = foreColor; if (control is Button button) { button.FlatStyle = FlatStyle.Flat; button.FlatAppearance.BorderSize = 1; button.Paint += (sender, e) => { Button btn = (Button)sender; e.Graphics.Clear(btn.BackColor); TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; Color textColor = btn.Enabled ? foreColor : disableColor; TextRenderer.DrawText(e.Graphics, btn.Text, btn.Font, btn.ClientRectangle, textColor, flags); }; } if (control.HasChildren) { ApplyThemeToControls(control.Controls, backColor, disableColor, foreColor); } } } private void genGenerateButton_Click(object sender, EventArgs e) { genPasswordTextbox.Text = mGenMan.GeneratePassword(genSecureCheckbox.Checked, (int)genNumeric.Value); genCopyButton.Enabled = true; } private async void genCopyButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(genPasswordTextbox.Text)) { try { Clipboard.SetText(genPasswordTextbox.Text); await Task.Delay(45000); // 45秒 if (Clipboard.GetText() == genPasswordTextbox.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"パスワードのコピーに失敗:{ex.Message}" : $"Failed to copy password: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "コピー出来るパスワードではありません。" : "No password to copy."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void pwListbox_SelectedIndexChanged(object sender, EventArgs e) { if (pwListbox.SelectedItem is Item selected) { var passwords = mPassMan.GetAll(); var password = passwords.FirstOrDefault(p => p.Id == selected.Id); if (password != default) { pwWebsiteTextbox.Text = password.Website; pwUsernameTextbox.Text = password.Username; pwPasswordTextbox.Text = password.Password; pwNotesTextbox.Text = password.Note; pwAddButton.Enabled = false; pwEditButton.Enabled = true; pwDeleteButton.Enabled = true; pwCopyUsernameButton.Enabled = true; pwCopyPasswordButton.Enabled = true; pwShowButton.Enabled = true; pwDoneButton.Enabled = true; } else { ClearPasswordFields(); } } } private void pwAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(pwWebsiteTextbox.Text) || string.IsNullOrWhiteSpace(pwUsernameTextbox.Text) || string.IsNullOrWhiteSpace(pwPasswordTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト、ユーザー名及び、パスワードを御入力下さい。" : "Please fill in the website, user/email, and password."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mPassMan.AddPassword(pwWebsiteTextbox.Text, pwUsernameTextbox.Text, pwPasswordTextbox.Text, pwNotesTextbox.Text); LoadPasswords(mPwKeyword); ClearPasswordFields(); Debug.WriteLine(cultureInfo.Name); string mes = cultureInfo.Name == mJpLang ? "パスワードを追加しました。" : "Password added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"パスワードの追加に失敗:{ex.Message}" : $"Failed to add password: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void pwDeleteButton_Click(object sender, EventArgs e) { if (pwListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} のパスワードを削除しますか?" : $"Are you sure you want to delete the password for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mPassMan.DeletePassword(selected.Id)) { LoadPasswords(mPwKeyword); ClearPasswordFields(); } else { mes = cultureInfo.Name == mJpLang ? "パスワードの削除に失敗。" : "Failed to delete password"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private void pwEditButton_Click(object sender, EventArgs e) { if (pwListbox.SelectedItem is Item selected) { try { if (mPassMan.EditPassword(selected.Id, pwWebsiteTextbox.Text, pwUsernameTextbox.Text, pwPasswordTextbox.Text, pwNotesTextbox.Text)) { LoadPasswords(mPwKeyword); ClearPasswordFields(); string mes = cultureInfo.Name == mJpLang ? "パスワードの変更に成功。" : "Password changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? "パスワードの変更に失敗。" : "Failed to change password."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"パスワードの変更に失敗:{ex.Message}" : $"Failed to change password: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private async void pwCopyUsernameButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(pwUsernameTextbox.Text)) { try { Clipboard.SetText(pwUsernameTextbox.Text); await Task.Delay(45000); // 45秒 if (Clipboard.GetText() == pwUsernameTextbox.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"ユーザー名のコピーに失敗:{ex.Message}" : $"Failed to copy user/email: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "コピー出来るユーザー名ではありません。" : "No user/email to copy."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private async void pwCopyPasswordButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(pwPasswordTextbox.Text)) { try { Clipboard.SetText(pwPasswordTextbox.Text); await Task.Delay(45000); // 45秒 if (Clipboard.GetText() == pwPasswordTextbox.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"パスワードのコピーに失敗:{ex.Message}" : $"Failed to copy password: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "コピー出来るパスワードではありません。" : "No password to copy."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void pwShowButton_Click(object sender, EventArgs e) { pwPasswordTextbox.UseSystemPasswordChar = !pwPasswordTextbox.UseSystemPasswordChar; } private void pwDoneButton_Click(object sender, EventArgs e) { LoadPasswords(mPwKeyword); ClearPasswordFields(); } private void pwSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mPwKeyword = pwSearchTextbox.Text; LoadPasswords(pwSearchTextbox.Text); ClearPasswordFields(); e.Handled = true; } } private void otpAddLegacyButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(otpWebsiteTextbox2.Text) || string.IsNullOrWhiteSpace(otpAuthTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト及びOTP Authを御入力下さい。" : "Please fill in the website and OTP Auth."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { var (secret, issuer, algorithm, duration, digits) = mOtpMan.ParseOtpAuthUrl(otpAuthTextbox.Text); mOtpMan.AddOtp(otpWebsiteTextbox2.Text, secret, issuer, algorithm, duration, digits, ""); LoadOtps(mOtpKeyword); ClearOtpFields(); string mes = cultureInfo.Name == mJpLang ? "OTPの追加に成功。" : "OTP added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"OTPの追加に失敗:{ex.Message}" : $"Failed to add OTP: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void otpAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(otpWebsiteTextbox1.Text) || string.IsNullOrWhiteSpace(otpSecretTextbox.Text) || string.IsNullOrWhiteSpace(otpIssuerTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト、秘密鍵及び、発行者を御入力下さい。" : "Please fill in the website, secret, and issuer."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mOtpMan.AddOtp( otpWebsiteTextbox1.Text, otpSecretTextbox.Text, otpIssuerTextbox.Text, otpAlgorithmCombobox.Text, (int)otpDurationNumeric.Value, (int)otpDigitsNumeric.Value, "" ); LoadOtps(mOtpKeyword); ClearOtpFields(); string mes = cultureInfo.Name == mJpLang ? "OTPの追加に成功。" : "OTP added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"OTPの追加に失敗:{ex.Message}" : $"Failed to add OTP: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void otpEditButton_Click(object sender, EventArgs e) { if (otpListbox.SelectedItem is Item selected) { if (string.IsNullOrWhiteSpace(otpWebsiteTextbox1.Text) || string.IsNullOrWhiteSpace(otpSecretTextbox.Text) || string.IsNullOrWhiteSpace(otpIssuerTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト、秘密鍵及び、発行者を御入力下さい。" : "Please fill in the website, secret, and issuer."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { if (mOtpMan.EditOtp( selected.Id, otpWebsiteTextbox1.Text, otpSecretTextbox.Text, otpIssuerTextbox.Text, otpAlgorithmCombobox.Text, (int)otpDurationNumeric.Value, (int)otpDigitsNumeric.Value, "" )) { LoadOtps(mOtpKeyword); ClearOtpFields(); string mes = cultureInfo.Name == mJpLang ? "OTPの変更に成功。" : "OTP changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? "OTPの更新に失敗。" : "Failed to change OTP."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"OTPの更新に失敗:{ex.Message}" : $"Failed to change OTP: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void otpDeleteButton_Click(object sender, EventArgs e) { if (otpListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} のOTPを削除しますか?" : $"Are you sure you want to delete the OTP for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mOtpMan.DeleteOtp(selected.Id)) { LoadOtps(mOtpKeyword); ClearOtpFields(); } else { mes = cultureInfo.Name == mJpLang ? "OTPの削除に失敗。" : "Failed to delete OTP."; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private async void otpCopyButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(otpCodeLabel.Text)) { try { Clipboard.SetText(otpCodeLabel.Text); await Task.Delay(30000); // 30秒 if (Clipboard.GetText() == otpCodeLabel.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"OTPのコピーに失敗:{ex.Message}" : $"Failed to copy OTP: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show($"Failed to copy OTP: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "コピー出来るOTPではありません。" : "No OTP to copy."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void otpDoneButton_Click(object sender, EventArgs e) { LoadOtps(mOtpKeyword); ClearOtpFields(); } private void otpSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mOtpKeyword = otpSearchTextbox.Text; LoadOtps(otpSearchTextbox.Text); ClearOtpFields(); e.Handled = true; } } private void otpListbox_SelectedIndexChanged(object sender, EventArgs e) { if (otpListbox.SelectedItem is Item selected) { var otps = mOtpMan.GetAll(); var otp = otps.FirstOrDefault(o => o.Id == selected.Id); if (otp != default) { UpdateOtpCode(otp); otpWebsiteTextbox1.Text = otp.Website; otpIssuerTextbox.Text = otp.Issuer; otpSecretTextbox.Text = otp.Secret; otpDigitsNumeric.Value = otp.Digits; otpDurationNumeric.Value = otp.Duration; otpAlgorithmCombobox.SelectedItem = otp.Algorithm ?? "SHA1"; otpAddButton.Enabled = false; otpAddLegacyButton.Enabled = false; otpEditButton.Enabled = true; otpDeleteButton.Enabled = true; otpCopyButton.Enabled = true; otpDoneButton.Enabled = true; } else { ClearOtpFields(); string mes = cultureInfo.Name == mJpLang ? "ID {selected.Id} を持つOTPをデータベースに見つけられませんでした。" : "OTP with ID {selected.Id} not found in database."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { ClearOtpFields(); } } private void pinAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(pinWebsiteTextbox.Text) || string.IsNullOrWhiteSpace(pinCodeTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト及び暗証番号を御入力下さい。" : "Please fill in the website and pincode."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mPinMan.AddPin(pinWebsiteTextbox.Text, pinCodeTextbox.Text, pinNoteTextbox.Text); LoadPins(mPinKeyword); ClearPinFields(); string mes = cultureInfo.Name == mJpLang ? "暗証番号の追加に成功。" : "Pincode added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"暗証番号の追加に失敗:{ex.Message}" : $"Failed to add pincode: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void pinEditButton_Click(object sender, EventArgs e) { if (pinListbox.SelectedItem is Item selected) { if (mPinMan.EditPin(selected.Id, pinWebsiteTextbox.Text, pinCodeTextbox.Text, pinNoteTextbox.Text)) { LoadPins(mPinKeyword); ClearPinFields(); string mes = cultureInfo.Name == mJpLang ? "暗証番号の変更に成功。" : "Pincode changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? $"暗証番号の変更に失敗。" : $"Failed to change pincode."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void pinDeleteButton_Click(object sender, EventArgs e) { if (pinListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} の暗証番号を削除しますか?" : $"Are you sure you want to delete the pincode for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mPinMan.DeletePin(selected.Id)) { LoadPins(mPinKeyword); ClearPinFields(); } else { mes = cultureInfo.Name == mJpLang ? "暗証番号の削除に失敗。" : "Failed to delete pincode"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private async void pinCopyButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(pinCodeTextbox.Text)) { try { Clipboard.SetText(pinCodeTextbox.Text); await Task.Delay(45000); // 45秒 if (Clipboard.GetText() == pinCodeTextbox.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"暗証番号のコピーに失敗:{ex.Message}" : $"Failed to copy pincode: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "ID {selected.Id} を持つ暗証番号をデータベースに見つけられませんでした。" : "Pincode with ID {selected.Id} not found in database."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void pinShowButton_Click(object sender, EventArgs e) { pinCodeTextbox.UseSystemPasswordChar = !pinCodeTextbox.UseSystemPasswordChar; } private void pinDoneButton_Click(object sender, EventArgs e) { LoadPins(mPinKeyword); ClearPinFields(); } private void pinListbox_SelectedIndexChanged(object sender, EventArgs e) { if (pinListbox.SelectedItem is Item selected) { var pins = mPinMan.GetAll(); var pin = pins.FirstOrDefault(o => o.Id == selected.Id); if (pin != default) { pinWebsiteTextbox.Text = pin.Website; pinCodeTextbox.Text = pin.Pincode; pinNoteTextbox.Text = pin.Note; pinAddButton.Enabled = false; pinEditButton.Enabled = true; pinDeleteButton.Enabled = true; pinCopyButton.Enabled = true; pinShowButton.Enabled = true; pinDoneButton.Enabled = true; } else { ClearPinFields(); string mes = cultureInfo.Name == mJpLang ? $"ID {selected.Id} を持つ暗証番号をデータベースに見つけられませんでした。" : $"Pincode with ID {selected.Id} not found in database."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { ClearPinFields(); } } private void pinSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mPinKeyword = pinSearchTextbox.Text; LoadPins(pinSearchTextbox.Text); ClearPinFields(); e.Handled = true; } } private void noteAddEditButton_Click(object sender, EventArgs e) { if (noteListbox.SelectedItem is Item selected) { try { mNoteMan.EditNote(selected.Id, noteTitleTextbox.Text); LoadNotes(mNoteKeyword); ClearNoteFields(); string mes = cultureInfo.Name == mJpLang ? "メモの変更に成功。" : "Note changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"メモの変更に失敗:{ex.Message}" : $"Failed to change note: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { try { mNoteMan.AddNote(noteTitleTextbox.Text); LoadNotes(mNoteKeyword); ClearNoteFields(); string mes = cultureInfo.Name == mJpLang ? "メモの追加に成功。" : "Note added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"メモの追加に失敗:{ex.Message}" : $"Failed to add note: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void noteListbox_SelectedIndexChanged(object sender, EventArgs e) { if (noteListbox.SelectedItem is Item selected) { var notes = mNoteMan.GetAll(); var note = notes.FirstOrDefault(o => o.Id == selected.Id); if (note != default) { noteTitleTextbox.Text = note.Name; noteTextbox.Text = note.Text; noteTextbox.Enabled = true; noteAddEditButton.Text = cultureInfo.Name == mJpLang ? "編集" : "Edit"; noteDeleteButton.Enabled = true; noteDoneButton.Enabled = true; noteSaveButton.Enabled = true; } else { ClearNoteFields(); string mes = cultureInfo.Name == mJpLang ? $"ID {selected.Id} を持つメモをデータベースに見つけられませんでした。" : $"Note with ID {selected.Id} not found in database."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { ClearNoteFields(); } } private void noteDeleteButton_Click(object sender, EventArgs e) { if (noteListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} のメモを削除しますか?" : $"Are you sure you want to delete the note for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mNoteMan.DeleteNote(selected.Id)) { LoadNotes(mNoteKeyword); ClearNoteFields(); } else { mes = cultureInfo.Name == mJpLang ? "メモの削除に失敗。" : "Failed to delete note"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private void NoteSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mNoteKeyword = noteSearchTextbox.Text; LoadNotes(noteSearchTextbox.Text); ClearNoteFields(); e.Handled = true; } } private void noteSaveButton_Click(object sender, EventArgs e) { if (noteListbox.SelectedItem is Item selected) { try { mNoteMan.SaveNote(selected.Id, noteTextbox.Text); LoadNotes(mNoteKeyword); string mes = cultureInfo.Name == mJpLang ? "メモの保存に成功。" : "Note saved successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"メモの保存に失敗:{ex.Message}" : $"Failed to save note: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void noteDoneButton_Click(object sender, EventArgs e) { LoadNotes(mNoteKeyword); ClearNoteFields(); } private void qaAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(qaWebsiteTextbox.Text) || string.IsNullOrWhiteSpace(qaQuestionTextbox.Text) || string.IsNullOrWhiteSpace(qaAnswerTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ウェブサイト、質問及び、回答を御入力下さい。" : "Please fill in the website, question, and answer."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mQaMan.AddQa(qaWebsiteTextbox.Text, qaQuestionTextbox.Text, qaAnswerTextbox.Text, qaNoteTextbox.Text); LoadQas(mQaKeyword); ClearQaFields(); string mes = cultureInfo.Name == mJpLang ? "秘密質問を追加しました。" : "Secret question added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"秘密質問の追加に失敗:{ex.Message}" : $"Failed to add secret question: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void qaDeleteButton_Click(object sender, EventArgs e) { if (qaListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} の秘密質問を削除しますか?" : $"Are you sure you want to delete the secret question for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mQaMan.DeleteQa(selected.Id)) { LoadQas(mQaKeyword); ClearQaFields(); } else { mes = cultureInfo.Name == mJpLang ? "秘密質問の削除に失敗。" : "Failed to delete secret question"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private void qaEditButton_Click(object sender, EventArgs e) { if (qaListbox.SelectedItem is Item selected) { if (mQaMan.EditQa(selected.Id, qaWebsiteTextbox.Text, qaQuestionTextbox.Text, qaAnswerTextbox.Text, qaNoteTextbox.Text)) { LoadQas(mQaKeyword); ClearQaFields(); string mes = cultureInfo.Name == mJpLang ? "秘密質問の変更に成功。" : "Secret question changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? "秘密質問の変更に失敗。" : "Failed to change secret question."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private async void qaCopyButton_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(qaAnswerTextbox.Text)) { try { Clipboard.SetText(qaAnswerTextbox.Text); await Task.Delay(45000); // 45秒 if (Clipboard.GetText() == qaAnswerTextbox.Text) { Clipboard.Clear(); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"秘密質問のコピーに失敗:{ex.Message}" : $"Failed to copy secret question: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { string mes = cultureInfo.Name == mJpLang ? "コピー出来る秘密質問ではありません。" : "No secret question to copy."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void qaShowButton_Click(object sender, EventArgs e) { qaAnswerTextbox.UseSystemPasswordChar = !qaAnswerTextbox.UseSystemPasswordChar; } private void qaDoneButton_Click(object sender, EventArgs e) { LoadQas(mQaKeyword); ClearQaFields(); } private void qaListbox_SelectedIndexChanged(object sender, EventArgs e) { if (qaListbox.SelectedItem is Item selected) { var qas = mQaMan.GetAll(); var qa = qas.FirstOrDefault(p => p.Id == selected.Id); if (qa != default) { qaWebsiteTextbox.Text = qa.Website; qaQuestionTextbox.Text = qa.Question; qaAnswerTextbox.Text = qa.Answer; qaNoteTextbox.Text = qa.Note; qaAddButton.Enabled = false; qaEditButton.Enabled = true; qaDeleteButton.Enabled = true; qaCopyButton.Enabled = true; qaShowButton.Enabled = true; qaDoneButton.Enabled = true; } else { ClearQaFields(); } } } private void qaSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mQaKeyword = qaSearchTextbox.Text; LoadNotes(qaSearchTextbox.Text); ClearQaFields(); e.Handled = true; } } private void ccListbox_SelectedIndexChanged(object sender, EventArgs e) { if (ccListbox.SelectedItem is Item selected) { var ccs = mCcMan.GetAll(); var cc = ccs.FirstOrDefault(p => p.Id == selected.Id); if (cc != default) { ccBrandCombobox.SelectedItem = cc.Brand ?? "Mastercard"; ccNumberTextbox.Text = cc.Cardnumber; ccHolderTextbox.Text = cc.Holdername; ccExpirationTextbox.Text = cc.Expiration; ccCvcTextbox.Text = cc.Cvc; ccNotesTextbox.Text = cc.Note; ccAddButton.Enabled = false; ccEditButton.Enabled = true; ccDeleteButton.Enabled = true; ccShowButton.Enabled = true; ccDoneButton.Enabled = true; } else { ClearCcFields(); } } } private void ccSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mCcKeyword = ccSearchTextbox.Text; LoadCcs(ccSearchTextbox.Text); ClearCcFields(); e.Handled = true; } } private void ccAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(ccBrandCombobox.Text) || string.IsNullOrWhiteSpace(ccNumberTextbox.Text) || string.IsNullOrWhiteSpace(ccExpirationTextbox.Text) || string.IsNullOrWhiteSpace(ccCvcTextbox.Text) || string.IsNullOrWhiteSpace(ccHolderTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "ブランド、カード番号、氏名、有効期限及び、CVCを御入力下さい。" : "Please fill in the brand, card number, full name, expiration, and CVC."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mCcMan.AddCc(ccBrandCombobox.Text, ccNumberTextbox.Text, ccExpirationTextbox.Text, ccCvcTextbox.Text, ccHolderTextbox.Text, ccNotesTextbox.Text); LoadCcs(mCcKeyword); ClearCcFields(); string mes = cultureInfo.Name == mJpLang ? "クレジットカードを追加しました。" : "Creditcard added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"クレジットカードの追加に失敗:{ex.Message}" : $"Failed to add creditcard: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void ccDeleteButton_Click(object sender, EventArgs e) { if (ccListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} のクレジットカードを削除しますか?" : $"Are you sure you want to delete the creditcard for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mCcMan.DeleteCc(selected.Id)) { LoadCcs(mCcKeyword); ClearCcFields(); } else { mes = cultureInfo.Name == mJpLang ? "クレジットカードの削除に失敗。" : "Failed to delete creditcard"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private void ccEditButton_Click(object sender, EventArgs e) { if (ccListbox.SelectedItem is Item selected) { if (mCcMan.EditCc(selected.Id, ccBrandCombobox.Text, ccNumberTextbox.Text, ccExpirationTextbox.Text, ccCvcTextbox.Text, ccHolderTextbox.Text, ccNotesTextbox.Text)) { LoadCcs(mCcKeyword); ClearCcFields(); string mes = cultureInfo.Name == mJpLang ? "クレジットカードの変更に成功。" : "Creditcard changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? "クレジットカードの変更に失敗。" : "Failed to change creditcard."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void ccShowButton_Click(object sender, EventArgs e) { ccNumberTextbox.UseSystemPasswordChar = !ccNumberTextbox.UseSystemPasswordChar; ccCvcTextbox.UseSystemPasswordChar = !ccCvcTextbox.UseSystemPasswordChar; } private void ccDoneButton_Click(object sender, EventArgs e) { LoadCcs(mCcKeyword); ClearCcFields(); } private void cryptoListbox_SelectedIndexChanged(object sender, EventArgs e) { if (cryptoListbox.SelectedItem is Item selected) { var cryptos = mCryptoMan.GetAll(); var crypto = cryptos.FirstOrDefault(p => p.Id == selected.Id); if (crypto != default) { cryptoCurrencyCombobox.SelectedItem = crypto.Currency ?? "XMR"; cryptoNameTextbox.Text = crypto.Name; cryptoAddressTextbox.Text = crypto.Address; cryptoSeedTextbox.Text = crypto.Seed; cryptoViewkeyTextbox.Text = crypto.Viewkey; cryptoSpendkeyTextbox.Text = crypto.Spendkey; cryptoHeightTextbox.Text = crypto.Height; cryptoPasswordTextbox.Text = crypto.Password; cryptoNotesTextbox.Text = crypto.Note; cryptoAddButton.Enabled = false; cryptoEditButton.Enabled = true; cryptoDeleteButton.Enabled = true; cryptoShowButton.Enabled = true; cryptoDoneButton.Enabled = true; } else { ClearCryptoFields(); } } } private void cryptoSearchTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) { mCryptoKeyword = cryptoSearchTextbox.Text; LoadCryptos(cryptoSearchTextbox.Text); ClearCryptoFields(); e.Handled = true; } } private void cryptoAddButton_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(cryptoCurrencyCombobox.Text) || string.IsNullOrWhiteSpace(cryptoNameTextbox.Text) || string.IsNullOrWhiteSpace(cryptoAddressTextbox.Text)) { string mes = cultureInfo.Name == mJpLang ? "通貨、ウォレット名及び、住所を御入力下さい。" : "Please fill in the currency, wallet name, and address."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { mCryptoMan.AddCrypto(cryptoCurrencyCombobox.Text, cryptoNameTextbox.Text, cryptoAddressTextbox.Text, cryptoSeedTextbox.Text, cryptoViewkeyTextbox.Text, cryptoSpendkeyTextbox.Text, cryptoHeightTextbox.Text, cryptoPasswordTextbox.Text, cryptoNotesTextbox.Text); LoadCryptos(mCryptoKeyword); ClearCryptoFields(); string mes = cultureInfo.Name == mJpLang ? "仮想通貨を追加しました。" : "Cryptocurrency added successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"仮想通貨の追加に失敗:{ex.Message}" : $"Failed to add cryptocurrency: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void cryptoDeleteButton_Click(object sender, EventArgs e) { if (cryptoListbox.SelectedItem is Item selected) { string mes = cultureInfo.Name == mJpLang ? $"本当に {selected.DisplayText} の仮想通貨を削除しますか?" : $"Are you sure you want to delete the cryptocurrency for {selected.DisplayText}?"; string tit = cultureInfo.Name == mJpLang ? "削除の確認" : "Confirm Delete"; var res = MessageBox.Show(mes, tit, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res == DialogResult.Yes) { if (mCryptoMan.DeleteCrypto(selected.Id)) { LoadCryptos(mCryptoKeyword); ClearCryptoFields(); } else { mes = cultureInfo.Name == mJpLang ? "暗号通貨の削除に失敗。" : "Failed to delete cryptocurrency"; tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } private void cryptoEditButton_Click(object sender, EventArgs e) { if (cryptoListbox.SelectedItem is Item selected) { if (mCryptoMan.EditCrypto(selected.Id, cryptoCurrencyCombobox.Text, cryptoNameTextbox.Text, cryptoAddressTextbox.Text, cryptoSeedTextbox.Text, cryptoViewkeyTextbox.Text, cryptoSpendkeyTextbox.Text, cryptoHeightTextbox.Text, cryptoPasswordTextbox.Text, cryptoNotesTextbox.Text)) { LoadCryptos(mCryptoKeyword); ClearCryptoFields(); string mes = cultureInfo.Name == mJpLang ? "暗号通貨の変更に成功。" : "Cryptocurrency changed successfully."; string tit = cultureInfo.Name == mJpLang ? "成功" : "Success"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Information); } else { string mes = cultureInfo.Name == mJpLang ? "暗号通貨の変更に失敗。" : "Failed to change cryptocurrency."; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void cryptoShowButton_Click(object sender, EventArgs e) { cryptoSeedTextbox.UseSystemPasswordChar = !cryptoSeedTextbox.UseSystemPasswordChar; cryptoViewkeyTextbox.UseSystemPasswordChar = !cryptoViewkeyTextbox.UseSystemPasswordChar; cryptoSpendkeyTextbox.UseSystemPasswordChar = !cryptoSpendkeyTextbox.UseSystemPasswordChar; cryptoHeightTextbox.UseSystemPasswordChar = !cryptoHeightTextbox.UseSystemPasswordChar; } private void cryptoDoneButton_Click(object sender, EventArgs e) { LoadCryptos(mCryptoKeyword); ClearCryptoFields(); } private void OtpTimer_Tick(object sender, EventArgs e) { if (otpListbox.SelectedItem is Item selected) { var otps = mOtpMan.GetAll(); var otp = otps.FirstOrDefault(o => o.Id == selected.Id); if (otp != default) { long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long lastUpdate = currentTime / otp.Duration; long nextUpdate = (lastUpdate + 1) * otp.Duration; int secondsRemaining = (int)(nextUpdate - currentTime); // Only update if the TOTP code has changed or at the start of a new period if (secondsRemaining == otp.Duration || string.IsNullOrEmpty(otpCodeLabel.Text)) { UpdateOtpCode(otp); } else { // Update countdown without regenerating TOTP code otpCountdownLabel.Text = cultureInfo.Name == mJpLang ? $"{secondsRemaining}秒" : $"{secondsRemaining}s"; otpCountdownProgress.Value = secondsRemaining; } } else { otpCodeLabel.Text = string.Empty; otpCountdownLabel.Text = string.Empty; } } else { otpCodeLabel.Text = string.Empty; otpCountdownLabel.Text = string.Empty; } } private void ClearPasswordFields() { pwWebsiteTextbox.Text = string.Empty; pwUsernameTextbox.Text = string.Empty; pwPasswordTextbox.Text = string.Empty; pwNotesTextbox.Text = string.Empty; pwAddButton.Enabled = true; pwEditButton.Enabled = false; pwDeleteButton.Enabled = false; pwCopyUsernameButton.Enabled = false; pwCopyPasswordButton.Enabled = false; pwShowButton.Enabled = false; pwDoneButton.Enabled = false; } private void ClearOtpFields() { otpWebsiteTextbox1.Text = string.Empty; otpWebsiteTextbox2.Text = string.Empty; otpAuthTextbox.Text = string.Empty; otpSecretTextbox.Text = string.Empty; otpIssuerTextbox.Text = string.Empty; otpAlgorithmCombobox.SelectedIndex = 0; otpDigitsNumeric.Value = 6; otpDurationNumeric.Value = 30; otpCodeLabel.Text = string.Empty; otpCountdownLabel.Text = string.Empty; otpAddButton.Enabled = true; otpAddLegacyButton.Enabled = true; otpEditButton.Enabled = false; otpDeleteButton.Enabled = false; otpCopyButton.Enabled = false; otpDoneButton.Enabled = false; otpCountdownProgress.Value = 0; } private void ClearPinFields() { pinWebsiteTextbox.Text = string.Empty; pinCodeTextbox.Text = string.Empty; pinNoteTextbox.Text = string.Empty; pinAddButton.Enabled = true; pinEditButton.Enabled = false; pinDeleteButton.Enabled = false; pinCopyButton.Enabled = false; pinShowButton.Enabled = false; pinDoneButton.Enabled = false; } private void ClearNoteFields() { noteTitleTextbox.Text = string.Empty; noteTextbox.Text = string.Empty; noteTextbox.Enabled = false; noteAddEditButton.Text = cultureInfo.Name == mJpLang ? "追加" : "Add"; noteDeleteButton.Enabled = false; noteDoneButton.Enabled = false; noteSaveButton.Enabled = false; } private void ClearQaFields() { qaWebsiteTextbox.Text = string.Empty; qaQuestionTextbox.Text = string.Empty; qaAnswerTextbox.Text = string.Empty; qaNoteTextbox.Text = string.Empty; qaAddButton.Enabled = true; qaEditButton.Enabled = false; qaDeleteButton.Enabled = false; qaCopyButton.Enabled = false; qaShowButton.Enabled = false; qaDoneButton.Enabled = false; } private void ClearCcFields() { ccBrandCombobox.SelectedIndex = 0; ccNumberTextbox.Text = string.Empty; ccExpirationTextbox.Text = string.Empty; ccCvcTextbox.Text = string.Empty; ccHolderTextbox.Text = string.Empty; ccNotesTextbox.Text = string.Empty; ccAddButton.Enabled = true; ccEditButton.Enabled = false; ccDeleteButton.Enabled = false; ccShowButton.Enabled = false; ccDoneButton.Enabled = false; } private void ClearCryptoFields() { cryptoCurrencyCombobox.SelectedIndex = 0; cryptoNameTextbox.Text = string.Empty; cryptoAddressTextbox.Text = string.Empty; cryptoSeedTextbox.Text = string.Empty; cryptoViewkeyTextbox.Text = string.Empty; cryptoSpendkeyTextbox.Text = string.Empty; cryptoHeightTextbox.Text = string.Empty; cryptoPasswordTextbox.Text = string.Empty; cryptoNotesTextbox.Text = string.Empty; cryptoAddButton.Enabled = true; cryptoEditButton.Enabled = false; cryptoDeleteButton.Enabled = false; cryptoShowButton.Enabled = false; cryptoDoneButton.Enabled = false; } private void LoadPasswords(string keyword = "") { pwListbox.Items.Clear(); var passwords = mPassMan.GetAll(keyword); foreach (var pwd in passwords) { pwListbox.Items.Add(new Item(pwd.Id, $"{pwd.Website}/{pwd.Username}")); } } private void LoadOtps(string keyword = "") { otpListbox.Items.Clear(); try { var otps = mOtpMan.GetAll(keyword); foreach (var otp in otps) { otpListbox.Items.Add(new Item(otp.Id, $"{otp.Website} ({otp.Issuer})")); } if (otps.Count == 0) { string mes = cultureInfo.Name == mJpLang ? "データベースにOTPを見つけられませんでした。" : "No OTPs found in the database."; string tit = cultureInfo.Name == mJpLang ? "注意" : "Warning"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Warning); } } catch (Exception ex) { string mes = cultureInfo.Name == mJpLang ? $"OTPの読み込みに失敗:{ex.Message}" : $"Failed to load OTPs: {ex.Message}"; string tit = cultureInfo.Name == mJpLang ? "エラー" : "Error"; MessageBox.Show(mes, tit, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void LoadPins(string keyword = "") { pinListbox.Items.Clear(); var pins = mPinMan.GetAll(keyword); foreach (var pin in pins) { pinListbox.Items.Add(new Item(pin.Id, $"{pin.Website}")); } } private void LoadNotes(string keyword = "") { noteListbox.Items.Clear(); var notes = mNoteMan.GetAll(keyword); foreach (var note in notes) { noteListbox.Items.Add(new Item(note.Id, $"{note.Name}")); } } private void LoadQas(string keyword = "") { qaListbox.Items.Clear(); var qas = mQaMan.GetAll(keyword); foreach (var qa in qas) { qaListbox.Items.Add(new Item(qa.Id, $"{qa.Website}/{qa.Question}")); } } private void LoadCcs(string keyword = "") { ccListbox.Items.Clear(); var ccs = mCcMan.GetAll(keyword); foreach (var cc in ccs) { ccListbox.Items.Add(new Item(cc.Id, $"{cc.Brand}/{cc.Holdername} ({cc.Expiration})")); } } private void LoadCryptos(string keyword = "") { cryptoListbox.Items.Clear(); var cryptos = mCryptoMan.GetAll(keyword); foreach (var crypto in cryptos) { cryptoListbox.Items.Add(new Item(crypto.Id, $"{crypto.Currency}/{crypto.Name}")); } } private void UpdateOtpCode((int Id, string Website, string Secret, string Issuer, string Algorithm, int Duration, int Digits, string Note) otp) { try { var (code, error) = mOtpMan.GenerateTotp(otp.Secret, otp.Digits, otp.Algorithm, otp.Duration); if (!string.IsNullOrEmpty(error)) { otpCodeLabel.Text = cultureInfo.Name == mJpLang ? $"エラー:{error}" : $"Error: {error}"; otpCountdownLabel.Text = string.Empty; } else { otpCodeLabel.Text = code; long currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); int secondsRemaining = otp.Duration - (int)(currentTime % otp.Duration); otpCountdownLabel.Text = cultureInfo.Name == mJpLang ? $"{secondsRemaining}秒" : $"{secondsRemaining}s"; otpCountdownProgress.Maximum = otp.Duration; otpCountdownProgress.Value = secondsRemaining; } } catch (Exception ex) { otpCodeLabel.Text = cultureInfo.Name == mJpLang ? $"エラー:{ex.Message}" : $"Error: {ex.Message}"; otpCountdownLabel.Text = string.Empty; } } private class Item { public int Id { get; } public string DisplayText { get; } public Item(int id, string displayText) { Id = id; DisplayText = displayText; } public override string ToString() => DisplayText; } } }