/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
class wxEAPBannerPanel;
template class wxEAPConfigDialog;
class wxEAPGeneralDialog;
class wxEAPCredentialsDialog;
class wxEAPNotePanel;
class wxEAPProviderLockedPanel;
class wxEAPCredentialWarningPanel;
class wxEAPConfigWindow;
class wxEAPProviderContactInfoPanel;
class wxEAPProviderIDPanel;
class wxEAPConfigProvider;
template class wxEAPCredentialsConfigPanel;
template class wxEAPCredentialsPanel;
template class wxPasswordCredentialsPanel;
class wxEAPProviderSelectDialog;
///
/// \defgroup EAPBaseGUI GUI
/// Graphical User Interface
///
/// @{
///
/// Loads icon from resource
///
/// When icon of desired \p cx × \p cy dimensions is not found, the most appropriate variant (larger if available) is loaded and scaled to \p cx × \p cy.
///
/// \sa [LoadIconWithScaleDown function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb775703.aspx)
///
/// \param[in] hinst Resource module instance handle
/// \param[in] pszName Resource name (`MAKEINTRESOURCE()` macro can be used for numerical resources)
/// \param[in] cx Desired width of the icon
/// \param[in] cy Desired height of the icon
///
/// \returns
/// - Loaded icon when successful;
/// - \c wxNullIcon otherwise.
///
inline wxIcon wxLoadIconFromResource(HINSTANCE hinst, PCWSTR pszName, int cx = GetSystemMetrics(SM_CXICON), int cy = GetSystemMetrics(SM_CYICON));
///
/// Loads icon from resource
///
/// When icon of desired \p size dimensions is not found, the most appropriate variant (larger if available) is loaded and scaled to \p size.
///
/// \sa [LoadIconWithScaleDown function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb775703.aspx)
///
/// \param[in] hinst Resource module instance handle
/// \param[in] pszName Resource name (`MAKEINTRESOURCE()` macro can be used for numerical resources)
/// \param[in] size Desired width and height of the icon
///
/// \returns
/// - Loaded icon when successful;
/// - \c wxNullIcon otherwise.
///
inline wxIcon wxLoadIconFromResource(HINSTANCE hinst, PCWSTR pszName, const wxSize &size);
///
/// Returns GUI displayable provider name
///
/// \param[in] id Provider name
///
/// \returns
/// - \p id when \p id is not blank;
/// - localized "" otherwise.
///
inline wxString wxEAPGetProviderName(const std::wstring &id);
///
/// Initializes wxWidgets application configuration scheme
///
inline void wxInitializeConfig();
/// @}
namespace eap
{
class monitor_ui;
}
#pragma once
#include // Fixes `CreateDialog` name collision
#include "../res/wxEAP_UI.h"
#include "../../EAPBase/include/Config.h"
#include "../../EAPBase/include/Credentials.h"
#include
#include
#include
#include
#include
#include
#include
#include
/// \addtogroup EAPBaseGUI
/// @{
///
/// Reusable EAP dialog banner for `wxEAPConfigDialog` and `wxEAPCredentialsDialog`
///
class wxEAPBannerPanel : public wxEAPBannerPanelBase
{
public:
///
/// Constructs a banner pannel and set the title text to product name
///
/// \param[in] parent Parent window
///
wxEAPBannerPanel(wxWindow* parent);
protected:
/// \cond internal
virtual bool AcceptsFocusFromKeyboard() const;
/// \endcond
};
///
/// EAP top-most configuration dialog template
///
template
class wxEAPConfigDialog : public wxEAPConfigDialogBase
{
public:
///
/// Constructs a configuration dialog
///
/// \param[inout] cfg Connection configuration
/// \param[in] parent Parent window
///
wxEAPConfigDialog(eap::config_connection &cfg, wxWindow* parent) :
m_cfg(cfg),
wxEAPConfigDialogBase(parent)
{
// Set extra style here, as wxFormBuilder overrides all default flags.
this->SetExtraStyle(this->GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
// Load window icons.
#ifdef __WINDOWS__
wxIconBundle icons;
icons.AddIcon(wxIcon(wxT("product.ico"), wxBITMAP_TYPE_ICO_RESOURCE, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON)));
icons.AddIcon(wxIcon(wxT("product.ico"), wxBITMAP_TYPE_ICO_RESOURCE, ::GetSystemMetrics(SM_CXICON ), ::GetSystemMetrics(SM_CYICON )));
this->SetIcons(icons);
#else
this->SetIcon(wxIcon(wxICON(product.ico)));
#endif
// Set banner title.
std::unique_ptr cfg_dummy(cfg.m_module.make_config_method());
m_banner->m_title->SetLabel(wxString::Format("%s %s", wxT(PRODUCT_NAME_STR), cfg_dummy->get_method_str()));
for (auto provider = m_cfg.m_providers.begin(), provider_end = m_cfg.m_providers.end(); provider != provider_end; ++provider) {
bool is_single = provider->m_methods.size() == 1;
std::vector >::size_type count = 0;
auto method = provider->m_methods.begin(), method_end = provider->m_methods.end();
for (; method != method_end; ++method, count++) {
m_providers->AddPage(
new _wxT(
*provider,
*method->get(),
m_providers),
is_single ?
wxEAPGetProviderName(provider->m_name) :
winstd::tstring_printf(_T("%s (%u)"), static_cast(wxEAPGetProviderName(provider->m_name)), count));
}
}
this->Layout();
this->GetSizer()->Fit(this);
m_buttonsOK->SetDefault();
}
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event)
{
wxEAPConfigDialogBase::OnInitDialog(event);
// Forward the event to child panels.
for (wxWindowList::compatibility_iterator provider = m_providers->GetChildren().GetFirst(); provider; provider = provider->GetNext()) {
wxWindow *prov = wxDynamicCast(provider->GetData(), wxWindow);
if (prov)
prov->GetEventHandler()->ProcessEvent(event);
}
}
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
wxEAPConfigDialogBase::OnUpdateUI(event);
int idx = m_providers->GetSelection();
if (idx != wxNOT_FOUND) {
eap::config_provider &cfg_provider = dynamic_cast<_wxT*>(m_providers->GetPage(idx))->GetProvider();
m_prov_remove->Enable(true);
m_prov_advanced->Enable(!cfg_provider.m_read_only);
} else {
m_prov_remove->Enable(false);
m_prov_advanced->Enable(false);
}
}
virtual void OnProvAdd(wxCommandEvent& event)
{
wxEAPConfigDialogBase::OnProvAdd(event);
// One method
std::unique_ptr cfg_method(m_cfg.m_module.make_config_method());
// Create provider.
eap::config_provider cfg_provider(m_cfg.m_module);
GUID guid;
CoCreateGuid(&guid);
cfg_provider.m_namespace = L"urn:uuid";
cfg_provider.m_id = winstd::wstring_guid(guid).substr(1, 36);
cfg_provider.m_methods.push_back(std::move(cfg_method));
// Append provider.
m_cfg.m_providers.push_back(std::move(cfg_provider));
eap::config_provider &cfg_provider2 = m_cfg.m_providers.back();
eap::config_method *cfg_method2 = cfg_provider2.m_methods.front().get();
_wxT *page = new _wxT(cfg_provider2, *cfg_method2, m_providers);
m_providers->InsertPage(m_providers->GetSelection() + 1, page, wxEAPGetProviderName(cfg_provider2.m_name), true);
this->Layout();
this->GetSizer()->Fit(this);
// We initialized other pages in OnInitDialog(). This one was added later so it needs to be initialized.
// (Timers in child panels didn't start otherwise.)
wxInitDialogEvent event_init;
page->GetEventHandler()->ProcessEvent(event_init);
}
virtual void OnProvRemove(wxCommandEvent& event)
{
wxEAPConfigDialogBase::OnProvRemove(event);
int idx = m_providers->GetSelection();
eap::config_provider &cfg_provider = dynamic_cast<_wxT*>(m_providers->GetPage(idx))->GetProvider();
if (wxMessageBox(tstring_printf(_("Are you sure you want to permanently remove %s provider from configuration?"), static_cast(wxEAPGetProviderName(cfg_provider.m_name))), _("Warning"), wxYES_NO, this) == wxYES) {
// Delete provider.
auto it = m_cfg.m_providers.begin();
for (int i = 0; i < idx; i++, ++it);
m_cfg.m_providers.erase(it);
m_providers->DeletePage(idx);
if ((size_t)idx < m_providers->GetPageCount())
m_providers->SetSelection(idx);
this->Layout();
this->Fit();
}
}
virtual void OnProvAdvanced(wxCommandEvent& event)
{
wxEAPConfigDialogBase::OnProvAdvanced(event);
int idx = m_providers->GetSelection();
eap::config_provider &cfg_provider = dynamic_cast<_wxT*>(m_providers->GetPage(idx))->GetProvider();
wxEAPConfigProvider dlg(cfg_provider, this);
if (dlg.ShowModal() == wxID_OK)
m_providers->SetPageText(idx, wxEAPGetProviderName(cfg_provider.m_name));
}
/// \endcond
protected:
eap::config_connection &m_cfg; ///< Connection configuration
};
///
/// EAP general-use dialog
///
class wxEAPGeneralDialog : public wxEAPGeneralDialogBase
{
public:
///
/// Constructs a dialog
///
/// \param[in] parent Parent window
/// \param[in] id An identifier for the dialog. A value of \c wxID_ANY is taken to mean a default.
/// \param[in] title The title of the dialog
/// \param[in] pos The dialog position. The value \c wxDefaultPosition indicates a default position, chosen by either the windowing system or wxWidgets, depending on platform.
/// \param[in] size The dialog size. The value \c wxDefaultSize indicates a default size, chosen by either the windowing system or wxWidgets, depending on platform.
/// \param[in] style The window style.
///
wxEAPGeneralDialog(wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &title = wxEmptyString, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE);
///
/// Adds panels to the dialog
///
void AddContent(wxPanel **contents, size_t content_count);
///
/// Adds single panel to the dialog
///
void AddContent(wxPanel *content);
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event);
/// \endcond
};
///
/// EAP method credential dialog
///
class wxEAPCredentialsDialog : public wxEAPGeneralDialog
{
public:
///
/// Constructs a credential dialog
///
wxEAPCredentialsDialog(const eap::config_provider &prov, wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &title = _("EAP Credentials"), const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE);
};
///
/// EAP provider select dialog
///
class wxEAPProviderSelectDialog : public wxEAPProviderSelectDialogBase
{
public:
///
/// Constructs a provider select dialog
///
/// \param[inout] cfg Connection configuration
/// \param[in] parent Parent window
///
wxEAPProviderSelectDialog(eap::config_connection &cfg, wxWindow* parent);
///
/// Returns pointer to selected provider or NULL if no provider is selected.
///
inline eap::config_provider* GetSelection() const
{
return m_selected;
}
protected:
/// \cond internal
virtual void OnProvSelect(wxCommandEvent& event);
/// \endcond
protected:
eap::config_provider* m_selected; ///< Pointer to selected provider (or NULL if none selected).
};
///
/// EAP general note
///
class wxEAPNotePanel : public wxEAPNotePanelBase
{
public:
///
/// Constructs an empty notice pannel
///
wxEAPNotePanel(wxWindow* parent);
protected:
/// \cond internal
virtual bool AcceptsFocusFromKeyboard() const;
template
static std::basic_string<_Elem, _Traits, _Ax> GetPhoneNumber(_In_z_ const _Elem *num)
{
assert(num);
std::basic_string<_Elem, _Traits, _Ax> str;
for (; *num; num++) {
_Elem c = *num;
if ('0' <= c && c <= '9' || c == '+' || c == '*' || c == '#')
str += c;
}
return str;
}
template
static std::basic_string<_Elem, std::char_traits<_Elem>, std::allocator<_Elem> > GetPhoneNumber(_In_z_ const _Elem *num)
{
return GetPhoneNumber<_Elem, std::char_traits<_Elem>, std::allocator<_Elem> >(num);
}
void CreateContactFields(const eap::config_provider &prov);
/// \endcond
protected:
wxStaticText *m_provider_notice; ///< Identity provider notice
wxStaticText *m_help_web_label; ///< Helpdesk URL label
wxHyperlinkCtrl *m_help_web_value; ///< Helpdesk URL
wxStaticText *m_help_email_label; ///< Helpdesk e-mail label
wxHyperlinkCtrl *m_help_email_value; ///< Helpdesk e-mail
wxStaticText *m_help_phone_label; ///< Helpdesk phone number label
wxHyperlinkCtrl *m_help_phone_value; ///< Helpdesk phone number
};
///
/// EAP provider-locked congifuration note
///
class wxEAPProviderLockedPanel : public wxEAPNotePanel
{
public:
///
/// Constructs a notice pannel and set the title text
///
wxEAPProviderLockedPanel(const eap::config_provider &prov, wxWindow* parent);
};
///
/// EAP credential warning note
///
class wxEAPCredentialWarningPanel : public wxEAPNotePanel
{
public:
///
/// Constructs a notice pannel and set the title text
///
wxEAPCredentialWarningPanel(const eap::config_provider &prov, eap::config_method::status_t status, wxWindow* parent);
};
///
/// EAP Configuration window
///
class wxEAPConfigWindow : public wxScrolledWindow
{
public:
///
/// Constructs a configuration window
///
/// \param[in] prov Provider configuration data
/// \param[inout] cfg Configuration data
/// \param[in] parent Parent window
///
wxEAPConfigWindow(eap::config_provider &prov, eap::config_method &cfg, wxWindow* parent);
///
/// Destructs the configuration window
///
virtual ~wxEAPConfigWindow();
public:
///
/// Returns reference to configuration provider
///
inline eap::config_provider& GetProvider() const
{
return m_prov;
}
///
/// Returns reference to method configuration
///
inline eap::config_method& GetConfig() const
{
return m_cfg;
}
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event);
/// \endcond
protected:
eap::config_provider &m_prov; ///< EAP provider
eap::config_method &m_cfg; ///< Method configuration
};
///
/// EAP provider contact info config panel
///
class wxEAPProviderContactInfoPanel : public wxEAPProviderContactInfoPanelBase
{
public:
///
/// Constructs a provider contact info pannel
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPProviderContactInfoPanel(eap::config_provider &prov, wxWindow* parent);
friend class wxEAPConfigProvider; // Allows direct setting of keyboard focus
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
eap::config_provider &m_prov; ///< Provider configuration
};
///
/// EAP provider identity config panel
///
class wxEAPProviderIDPanel : public wxEAPProviderIDPanelBase
{
public:
///
/// Constructs a provider identity pannel
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPProviderIDPanel(eap::config_provider &prov, wxWindow* parent);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
eap::config_provider &m_prov; ///< Provider configuration
};
///
/// EAP provider lock config panel
///
class wxEAPProviderLockPanel : public wxEAPProviderLockPanelBase
{
public:
///
/// Constructs a provider lock pannel
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPProviderLockPanel(eap::config_provider &prov, wxWindow* parent);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
eap::config_provider &m_prov; ///< EAP method configuration
};
///
/// EAP provider configuration dialog
///
class wxEAPConfigProvider : public wxEAPGeneralDialog
{
public:
///
/// Constructs a provider config dialog
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
/// \param[in] id An identifier for the dialog. A value of \c wxID_ANY is taken to mean a default.
/// \param[in] title The title of the dialog
/// \param[in] pos The dialog position. The value \c wxDefaultPosition indicates a default position, chosen by either the windowing system or wxWidgets, depending on platform.
/// \param[in] size The dialog size. The value \c wxDefaultSize indicates a default size, chosen by either the windowing system or wxWidgets, depending on platform.
/// \param[in] style The window style.
///
wxEAPConfigProvider(eap::config_provider &prov, wxWindow *parent, wxWindowID id = wxID_ANY, const wxString &title = _("Provider Settings"), const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE);
protected:
eap::config_provider &m_prov; ///< EAP method configuration
wxEAPProviderContactInfoPanel *m_contact; ///< Provider contact info panel
wxEAPProviderIDPanel *m_identity; ///< Provider identity panel
wxEAPProviderLockPanel *m_lock; ///< Provider lock panel
};
///
/// Base template for credential configuration panel
///
template
class wxEAPCredentialsConfigPanel : public wxEAPCredentialsConfigPanelBase
{
public:
///
/// Constructs a credential configuration panel
///
/// \param[in] prov Provider configuration data
/// \param[inout] cfg Configuration data
/// \param[in] parent Parent window
/// \param[in] method Method name to display
///
wxEAPCredentialsConfigPanel(const eap::config_provider &prov, eap::config_method_with_cred &cfg, wxWindow *parent, const wxString &method = wxEmptyString) :
m_prov(prov),
m_cfg(cfg),
m_has_storage(false),
m_cred_storage(cfg.m_module),
m_cred_config(cfg.m_module),
wxEAPCredentialsConfigPanelBase(parent)
{
m_sb_credentials->GetStaticBox()->SetLabel(method.empty() ? wxString::Format(_("%s User Credentials"), cfg.get_method_str()) : method);
// Load and set icon.
winstd::library lib_shell32;
if (lib_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
m_credentials_icon->SetIcon(wxLoadIconFromResource(lib_shell32, MAKEINTRESOURCE(/*16770*/269)));
}
///
/// Sets keyboard focus to the first control that do not capture mouse wheel
///
inline void SetFocusFromKbd()
{
m_storage->SetFocusFromKbd();
}
protected:
/// \cond internal
virtual bool TransferDataToWindow()
{
if (!m_cfg.m_use_cred)
m_storage->SetValue(true);
else
m_config->SetValue(true);
if (m_cfg.m_allow_save) {
RetrieveStorageCredentials();
m_timer_storage.Start(3000);
}
m_cred_config = *(_Tcred*)m_cfg.m_cred.get();
UpdateConfigIdentity();
return wxEAPCredentialsConfigPanelBase::TransferDataToWindow();
}
virtual bool TransferDataFromWindow()
{
wxCHECK(wxEAPCredentialsConfigPanelBase::TransferDataFromWindow(), false);
if (!m_prov.m_read_only) {
// This is not a provider-locked configuration. Save the data.
m_cfg.m_use_cred = !m_storage->GetValue();
*(_Tcred*)m_cfg.m_cred.get() = m_cred_config;
}
return true;
}
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
wxEAPCredentialsConfigPanelBase::OnUpdateUI(event);
if (m_cfg.m_allow_save) {
if (m_storage->GetValue()) {
m_storage_identity->Enable(true);
m_storage_set ->Enable(true);
m_storage_clear ->Enable(m_has_storage);
} else {
m_storage_identity->Enable(false);
m_storage_set ->Enable(false);
m_storage_clear ->Enable(false);
}
} else {
m_storage_identity->Enable(false);
m_storage_set ->Enable(false);
m_storage_clear ->Enable(false);
}
if (m_prov.m_read_only) {
// This is provider-locked configuration. Disable controls.
// To avoid run-away selection of radio buttons, disable the selected one last.
if (m_storage->GetValue()) {
m_config ->Enable(false);
m_storage->Enable(false);
} else {
m_storage->Enable(false);
m_config ->Enable(false);
}
m_config_identity->Enable(false);
m_config_set ->Enable(false);
} else {
// This is not a provider-locked configuration. Selectively enable/disable controls.
m_storage->Enable(true);
m_config->Enable(true);
if (m_storage->GetValue()) {
m_config_identity->Enable(false);
m_config_set ->Enable(false);
} else {
m_config_identity->Enable(true);
m_config_set ->Enable(true);
}
}
}
virtual void OnSetStorage(wxCommandEvent& event)
{
wxEAPCredentialsConfigPanelBase::OnSetStorage(event);
m_timer_storage.Stop();
// Read credentials from Credential Manager.
RetrieveStorageCredentials();
// Display credential prompt.
wxEAPCredentialsDialog dlg(m_prov, this);
_wxT *panel = new _wxT(m_prov, m_cfg, m_cred_storage, &dlg, true);
dlg.AddContent(panel);
if (dlg.ShowModal() == wxID_OK) {
// Write credentials to credential manager.
try {
m_cred_storage.store(m_prov.get_id().c_str(), m_cfg.m_level);
m_has_storage = TRUE;
UpdateStorageIdentity();
} catch (winstd::win_runtime_error &err) {
wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str());
RetrieveStorageCredentials();
} catch (...) {
wxLogError(_("Writing credentials failed."));
RetrieveStorageCredentials();
}
}
m_timer_storage.Start(3000);
}
virtual void OnClearStorage(wxCommandEvent& event)
{
wxEAPCredentialsConfigPanelBase::OnClearStorage(event);
m_timer_storage.Stop();
if (CredDelete(m_cred_storage.target_name(m_prov.get_id().c_str(), m_cfg.m_level).c_str(), CRED_TYPE_GENERIC, 0)) {
m_storage_identity->Clear();
m_cred_storage.clear();
m_has_storage = false;
} else
wxLogError(_("Deleting credentials failed (error %u)."), GetLastError());
m_timer_storage.Start(3000);
}
virtual void OnSetConfig(wxCommandEvent& event)
{
wxEAPCredentialsConfigPanelBase::OnSetConfig(event);
wxEAPCredentialsDialog dlg(m_prov, this);
_wxT *panel = new _wxT(m_prov, m_cfg, m_cred_config, &dlg, true);
dlg.AddContent(panel);
if (dlg.ShowModal() == wxID_OK)
UpdateConfigIdentity();
}
virtual void OnTimerStorage(wxTimerEvent& event)
{
wxEAPCredentialsConfigPanelBase::OnTimerStorage(event);
if (m_storage_identity->IsShownOnScreen())
RetrieveStorageCredentials();
}
void RetrieveStorageCredentials()
{
try {
m_cred_storage.retrieve(m_prov.get_id().c_str(), m_cfg.m_level);
m_has_storage = true;
UpdateStorageIdentity();
} catch (winstd::win_runtime_error &err) {
if (err.number() == ERROR_NOT_FOUND) {
m_storage_identity->Clear();
m_cred_storage.clear();
m_has_storage = false;
} else {
m_storage_identity->SetValue(wxString::Format(_(""), err.number()));
m_has_storage = true;
}
} catch (...) {
m_storage_identity->SetValue(_(""));
m_has_storage = true;
}
}
inline void UpdateStorageIdentity()
{
wxString identity(m_cred_storage.get_identity());
m_storage_identity->SetValue(
!identity.empty() ? identity :
m_cred_storage.empty() ? _("") : _(""));
}
inline void UpdateConfigIdentity()
{
wxString identity(m_cred_config.get_identity());
m_config_identity->SetValue(
!identity.empty() ? identity :
m_cred_config.empty() ? _("") : _(""));
}
/// \endcond
protected:
const eap::config_provider &m_prov; ///< EAP provider
eap::config_method_with_cred &m_cfg; ///< EAP method configuration
private:
bool m_has_storage; ///< Does the user has (some sort of) credentials stored in Credential Manager?
_Tcred m_cred_storage; ///< Temporary stored credential data
_Tcred m_cred_config; ///< Temporary config credential data
};
///
/// Helper template for all credential entry panels
///
template
class wxEAPCredentialsPanel : public _Tbase
{
public:
///
/// Constructs a credentials panel
///
/// \param[in] prov Provider configuration data
/// \param[in] cfg Configuration data
/// \param[inout] cred Credentials data
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to config credentials?
///
wxEAPCredentialsPanel(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, _Tcred &cred, wxWindow* parent, bool is_config = false) :
m_prov(prov),
m_cfg(cfg),
m_cred(cred),
m_is_config(is_config),
_Tbase(parent)
{
if (!is_config && !m_cfg.m_use_cred && m_cfg.m_allow_save) {
m_remember = new wxCheckBox(m_sb_credentials->GetStaticBox(), wxID_ANY, _("&Remember"));
m_remember->SetHelpText(_("Check if you would like to save credentials"));
m_sb_credentials_vert->Add(m_remember, 0, wxALL|wxEXPAND, 5);
} else
m_remember = NULL;
}
///
/// (Un)checks "Remember credentials" checkbox
///
/// \param[in] val If \c true, checkbox is checked; otherwise cleared
///
virtual void SetRemember(bool val)
{
if (m_remember)
m_remember->SetValue(val);
}
///
/// Returns \c true if "Remember credentials" checkbox is checked
///
virtual bool GetRemember() const
{
return m_remember ?
m_remember->GetValue() :
!m_cfg.m_use_cred && m_cfg.m_allow_save;
}
protected:
const eap::config_provider &m_prov; ///< Provider configuration
const eap::config_method_with_cred &m_cfg; ///< Method configuration
_Tcred &m_cred; ///< Credentials
bool m_is_config; ///< Is this a configuration dialog?
wxCheckBox *m_remember; ///< "Remember" checkbox
};
///
/// Generic password credential entry panel
///
template
class wxPasswordCredentialsPanel : public wxEAPCredentialsPanel<_Tcred, _Tbase>
{
public:
///
/// Constructs a password credentials panel
///
/// \param[in] prov Provider configuration data
/// \param[in] cfg Configuration data
/// \param[inout] cred Credentials data
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to config credentials?
///
wxPasswordCredentialsPanel(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, _Tcred &cred, wxWindow* parent, bool is_config = false) :
m_password_set(false),
wxEAPCredentialsPanel<_Tcred, _Tbase>(prov, cfg, cred, parent, is_config)
{
// Load and set icon.
winstd::library lib_shell32;
if (lib_shell32.load(_T("imageres.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
m_credentials_icon->SetIcon(wxLoadIconFromResource(lib_shell32, MAKEINTRESOURCE(82)));
bool layout = false;
if (!m_prov.m_lbl_alt_credential.empty()) {
m_credentials_label->SetLabel(m_prov.m_lbl_alt_credential);
m_credentials_label->Wrap( 440 );
layout = true;
}
if (!m_prov.m_lbl_alt_identity.empty()) {
m_identity_label->SetLabel(m_prov.m_lbl_alt_identity);
layout = true;
}
if (!m_prov.m_lbl_alt_password.empty()) {
m_password_label->SetLabel(m_prov.m_lbl_alt_password);
layout = true;
}
if (layout)
this->Layout();
}
protected:
/// \cond internal
virtual bool TransferDataToWindow()
{
m_identity->SetValue(m_cred.m_identity);
m_identity->SetSelection(0, -1);
m_password->SetValue(m_cred.m_password.empty() ? wxEmptyString : wxT("dummypass"));
m_password_set = false;
if (!m_is_config && m_cfg.m_use_cred) {
// Credential prompt mode & Using configured credentials
m_identity_label->Enable(false);
m_identity ->Enable(false);
m_password_label->Enable(false);
m_password ->Enable(false);
}
return wxEAPCredentialsPanel<_Tcred, wxPasswordCredentialsPanelBase>::TransferDataToWindow();
}
virtual bool TransferDataFromWindow()
{
if (!wxEAPCredentialsPanel<_Tcred, wxPasswordCredentialsPanelBase>::TransferDataFromWindow())
return false;
m_cred.m_identity = m_identity->GetValue();
if (m_password_set)
m_cred.m_password = m_password->GetValue();
return true;
}
virtual void OnPasswordText(wxCommandEvent& event)
{
wxEAPCredentialsPanel<_Tcred, _Tbase>::OnPasswordText(event);
m_password_set = true;
}
/// \endcond
private:
bool m_password_set;
};
/// @}
inline wxIcon wxLoadIconFromResource(HINSTANCE hinst, PCWSTR pszName, int cx, int cy)
{
HICON hIcon;
if (SUCCEEDED(LoadIconWithScaleDown(hinst, pszName, cx, cy, &hIcon))) {
wxIcon icon;
icon.CreateFromHICON(hIcon);
return icon;
} else
return wxNullIcon;
}
inline wxIcon wxLoadIconFromResource(HINSTANCE hinst, PCWSTR pszName, const wxSize &size)
{
HICON hIcon;
if (SUCCEEDED(LoadIconWithScaleDown(hinst, pszName, size.GetWidth(), size.GetHeight(), &hIcon))) {
wxIcon icon;
icon.CreateFromHICON(hIcon);
return icon;
} else
return wxNullIcon;
}
inline wxString wxEAPGetProviderName(const std::wstring &id)
{
return
!id.empty() ? id : _("");
}
inline void wxInitializeConfig()
{
wxConfigBase *cfgPrev = wxConfigBase::Set(new wxConfig(wxT(PRODUCT_NAME_STR), wxT(VENDOR_NAME_STR)));
if (cfgPrev) wxDELETE(cfgPrev);
}
namespace eap
{
/// \addtogroup EAPBaseGUI
/// @{
///
/// Base class to enable single instance of the same dialog (master) return result to multiple threads (slaves)
///
class monitor_ui
{
public:
///
/// Constructs a UI monitor
///
monitor_ui(_In_ HINSTANCE module, _In_ const GUID &guid);
///
/// Destructs the UI monitor
///
virtual ~monitor_ui();
///
/// Sets pop-up window handle
///
/// \param[in] hwnd Handle of window to set as a new pop-up
///
void set_popup(_In_ HWND hwnd);
///
/// Notifies all slaves waiting for this master and send them result data
///
/// \param[in] data Pointer to result data
/// \param[in] size \p data size in bytes
///
void release_slaves(_In_bytecount_(size) const void *data, _In_ size_t size) const;
///
/// Returns true if this is a master
///
inline bool is_master() const
{
return m_is_master;
}
///
/// Returns true if this is a slave
///
inline bool is_slave() const
{
return !is_master();
}
///
/// Returns the data master send
///
inline const std::vector& master_data() const
{
return m_data;
}
protected:
/// \cond internal
virtual LRESULT winproc(
_In_ UINT msg,
_In_ WPARAM wparam,
_In_ LPARAM lparam);
static LRESULT CALLBACK winproc(
_In_ HWND hwnd,
_In_ UINT msg,
_In_ WPARAM wparam,
_In_ LPARAM lparam);
/// \endcond
protected:
bool m_is_master; ///< Is this monitor master?
HWND m_hwnd; ///< Message window handle
std::list m_slaves; ///< List of slaves to notify on finish
HWND m_hwnd_popup; ///< Pop-up window handle
std::vector m_data; ///< Data master sent
// Custom window messages
static const UINT s_msg_attach; ///< Slave sends this message to attach to master
static const UINT s_msg_finish; ///< Master sends this message to slaves to notify them it has finished (wparam has size, lparam has data)
};
/// @}
}