2022-02-16 00:53:01 -05:00
# include " stdafx.h "
// ----------------------------------------------------------------------------
// frame
// ----------------------------------------------------------------------------
2022-04-02 22:07:41 -04:00
Frame * singletonFrame { nullptr } ;
2022-02-16 00:53:01 -05:00
void Frame : : RestorePositionFromConfig ( const wxSize & bestSize ) {
// SetPath() understands ".." but you should probably never use it.
singletonApp - > pConfig - > SetPath ( _T ( " /MainFrame " ) ) ; wxPoint scr { wxSystemSettings : : GetMetric ( wxSYS_SCREEN_X ) , wxSystemSettings : : GetMetric ( wxSYS_SCREEN_Y ) } ;
// restore frame position and size
int x = singletonApp - > pConfig - > ReadLong ( _T ( " x " ) , scr . x / 4 ) ;
int y = singletonApp - > pConfig - > ReadLong ( _T ( " y " ) , scr . y / 4 ) ;
int w = singletonApp - > pConfig - > ReadLong ( _T ( " w " ) , scr . x / 2 ) ;
int h = singletonApp - > pConfig - > ReadLong ( _T ( " h " ) , scr . y / 2 ) ;
w = std : : min ( std : : max ( std : : max ( w , scr . x / 5 ) , bestSize . GetWidth ( ) ) , 8 * scr . x / 9 ) ;
h = std : : min ( std : : max ( std : : max ( h , scr . y / 9 ) , bestSize . GetHeight ( ) ) , 4 * scr . y / 5 ) ;
x = std : : max ( scr . x / 12 , std : : min ( x , scr . x - w - scr . x / 12 ) ) ;
y = std : : max ( scr . y / 10 , std : : min ( y , scr . y - h - scr . y / 10 ) ) ;
this - > Move ( x , y ) ;
this - > Maximize ( singletonApp - > pConfig - > ReadBool ( _T ( " Maximized " ) , false ) ) ;
this - > SetSize ( w , h ) ;
singletonApp - > pConfig - > SetPath ( _T ( " / " ) ) ;
if ( singletonApp - > m_display | | m_pLogWindow ! = nullptr ) {
m_pLogWindow - > GetFrame ( ) - > SetSize ( w , h ) ;
if ( singletonApp - > m_display_in_front ) {
m_pLogWindow - > GetFrame ( ) - > Move ( std : : min ( x + 46 , scr . x - w ) , std : : min ( y + 46 , scr . y - h ) ) ;
}
else {
m_pLogWindow - > GetFrame ( ) - > Move ( std : : max ( x - 32 , 0 ) , std : : max ( y - 32 , 0 ) ) ;
}
m_pLogWindow - > GetFrame ( ) - > SetTitle ( sz_unit_test_log ) ;
m_pLogWindow - > Show ( true ) ;
}
else {
m_pLogNull = std : : make_unique < wxLogNull > ( ) ;
}
}
void Frame : : StorePositionToConfig ( ) {
if ( singletonApp - > pConfig ) {
singletonApp - > pConfig - > SetPath ( _T ( " /MainFrame " ) ) ;
if ( this - > IsMaximized ( ) ) {
singletonApp - > pConfig - > Write ( _T ( " Maximized " ) , true ) ;
}
else {
// save the frame position
int x , y , w , h ;
this - > GetSize ( & w , & h ) ;
this - > GetPosition ( & x , & y ) ;
singletonApp - > pConfig - > Write ( _T ( " x " ) , ( long ) x ) ;
singletonApp - > pConfig - > Write ( _T ( " y " ) , ( long ) y ) ;
singletonApp - > pConfig - > Write ( _T ( " w " ) , ( long ) w ) ;
singletonApp - > pConfig - > Write ( _T ( " h " ) , ( long ) h ) ;
singletonApp - > pConfig - > Write ( _T ( " Maximized " ) , false ) ;
}
singletonApp - > pConfig - > SetPath ( _T ( " / " ) ) ;
}
}
// main frame ctor
Frame : : Frame ( wxString wxs )
: wxFrame ( nullptr , myID_MAINFRAME , wxs , wxDefaultPosition , wxDefaultSize , wxDEFAULT_FRAME_STYLE , wxs ) ,
m_panel ( ) ,
m_LastUsedSqlite ( )
{
try {
assert ( singletonFrame = = nullptr ) ;
singletonFrame = this ;
SetIcon ( wxICON ( AAArho ) ) ;
sqlite3_init ( ) ;
if ( sodium_init ( ) = = - 1 ) {
szError = " Fatal Error: Encryption library did not init. " ;
errorCode = 6 ;
// Cannot log the error, because logging not set up yet, so logging itself causes an exception
throw FatalException ( szError . c_str ( ) ) ;
}
wxIdleEvent : : SetMode ( wxIDLE_PROCESS_SPECIFIED ) ;
if ( singletonApp - > m_display | | singletonApp - > m_log_focus_events ) {
m_pLogNull . reset ( nullptr ) ;
m_pLogWindow = new wxLogWindow ( this , wxs , false , false ) ;
wxLog : : EnableLogging ( true ) ;
wxLog : : SetActiveTarget ( m_pLogWindow ) ;
m_pLogWindow - > GetFrame ( ) - > SetName ( sz_unit_test_log ) ;
m_pLogWindow - > GetFrame ( ) - > SetIcon ( wxICON ( AAArho ) ) ;
if ( singletonApp - > m_unit_test ) {
2022-02-23 04:21:31 -05:00
wxLogMessage ( _T ( " Command line specified %s unit test with%s exit on completion of unit test. " ) ,
singletonApp - > m_complete_unit_test ? _T ( " complete " ) : singletonApp - > m_quick_unit_test ? _T ( " quick " ) : _T ( " " ) ,
2022-02-16 00:53:01 -05:00
singletonApp - > m_display ? _T ( " out " ) : _T ( " " ) ) ;
wxLogMessage ( _T ( " If an error occurs during unit test, the program will return a non zero "
" error number on exit. " ) ) ;
2022-02-23 04:21:31 -05:00
wxLogMessage ( _T ( " " ) ) ;
2022-02-16 00:53:01 -05:00
}
} else {
wxLog : : EnableLogging ( false ) ;
wxLog : : SetActiveTarget ( nullptr ) ;
m_pLogNull . reset ( new wxLogNull ( ) ) ;
}
if ( singletonApp - > m_unit_test ) singletonApp - > Bind (
wxEVT_IDLE ,
& UnitTest
) ;
2022-02-23 04:21:31 -05:00
if ( singletonApp - > m_log_focus_events ) {
wxLogMessage ( _T ( " Logging focus events " ) ) ;
wxLogMessage ( _T ( " " ) ) ;
}
2022-02-16 00:53:01 -05:00
if ( singletonApp - > m_params . empty ( ) ) {
wxLogMessage ( _T ( " No wallet specified. Attempting to open last used wallet " ) ) ;
} else {
wxString subcommands ( _T ( " " ) ) ;
for ( auto & str : singletonApp - > m_params ) {
subcommands + = str + _T ( " " ) ;
}
wxLogMessage ( _T ( " command argument%s %s " ) , singletonApp - > m_params . size ( ) = = 1 ? " " : " s " , subcommands ) ;
wxLogMessage ( _T ( " attempting to open %s " ) , singletonApp - > m_params [ 0 ] ) ;
}
SetIcon ( wxICON ( AAArho ) ) ; //Does not appear to do anything. Maybe it does something in Unix.
//wxICON is a namestring on windows, and a symbol on Unix
Bind ( wxEVT_CLOSE_WINDOW , & Frame : : OnClose , this ) ;
wxMenu * menuFile = new wxMenu ;
2022-03-07 23:46:14 -05:00
menuFile - > Append ( wxID_NEW , menu_strings [ 0 ] . tail [ 0 ] [ 0 ] , menu_strings [ 0 ] . tail [ 0 ] [ 1 ] ) ;
2022-02-16 00:53:01 -05:00
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnSaveNew , this , wxID_NEW ) ;
2022-03-07 23:46:14 -05:00
menuFile - > Append ( wxID_REFRESH , menu_strings [ 0 ] . tail [ 1 ] [ 0 ] , menu_strings [ 0 ] . tail [ 1 ] [ 1 ] ) ;
2022-02-16 00:53:01 -05:00
menuFile - > Bind ( wxEVT_MENU , & Frame : : RecreateWalletFromExistingSecret , this , wxID_REFRESH ) ;
2022-03-07 23:46:14 -05:00
menuFile - > Append ( wxID_OPEN , menu_strings [ 0 ] . tail [ 2 ] [ 0 ] , menu_strings [ 0 ] . tail [ 2 ] [ 1 ] ) ;
2022-02-16 00:53:01 -05:00
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnFileOpen , this , wxID_OPEN ) ;
2022-03-07 23:46:14 -05:00
menuFile - > Append ( wxID_DELETE , menu_strings [ 0 ] . tail [ 3 ] [ 0 ] , menu_strings [ 0 ] . tail [ 3 ] [ 1 ] + m_LastUsedSqlite . GetFullPath ( ) ) ;
2022-04-02 22:07:41 -04:00
wxLogMessage ( m_LastUsedSqlite . GetFullPath ( ) + " wallet path " ) ;
2022-02-16 00:53:01 -05:00
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnDelete , this , wxID_DELETE ) ;
2022-03-07 23:46:14 -05:00
menuFile - > Append ( myID_DELETECONFIG , menu_strings [ 0 ] . tail [ 4 ] [ 0 ] , menu_strings [ 0 ] . tail [ 4 ] [ 1 ] + m_LastUsedSqlite . GetFullPath ( ) ) ;
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnDeleteConfiguration , this , myID_DELETECONFIG ) ;
2022-04-02 22:07:41 -04:00
menuFile - > Append ( myID_MYEXIT , " my exit, testing destruction " ) ;
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnMyCloseMpanel , this , myID_MYEXIT ) ;
menuFile - > Append ( wxID_EXIT ) ;
menuFile - > Bind ( wxEVT_MENU , & Frame : : OnExit , this , wxID_EXIT ) ;
2022-02-16 00:53:01 -05:00
wxMenu * menuHelp = new wxMenu ;
menuHelp - > Append ( wxID_ABOUT ) ;
menuHelp - > Bind ( wxEVT_MENU , & Frame : : OnAbout , this , wxID_ABOUT ) ;
wxMenuBar * menuBar = new wxMenuBar ;
2022-03-07 23:46:14 -05:00
menuBar - > Append ( menuFile , menu_strings [ 0 ] . head ) ;
2022-05-07 00:40:17 -04:00
menuBar - > Append ( new wxMenu , menu_strings [ 1 ] . head ) ; //Edit menu, initially empty and disabled
2022-03-07 23:46:14 -05:00
menuBar - > Append ( menuHelp , menu_strings [ 2 ] . head ) ;
2022-02-16 00:53:01 -05:00
SetMenuBar ( menuBar ) ;
CreateStatusBar ( ) ;
2022-05-07 00:40:17 -04:00
menuBar - > EnableTop ( 1 , false ) ; //disable edit menu.
2022-02-16 00:53:01 -05:00
// child controls
m_LastUsedSqlite . Assign ( singletonApp - > pConfig - > Read ( _T ( " /Wallet/LastUsed " ) , _T ( " " ) ) ) ;
if ( ! m_LastUsedSqlite . IsOk ( ) | | ! m_LastUsedSqlite . HasName ( ) | | ! m_LastUsedSqlite . HasExt ( ) ) {
m_panel = new welcome_to_rhocoin ( this ) ; //Owner is "this", via the base class wxFrame. m_panel is a
// non owning pointer in the derived class that duplicates the owning pointer in the base class.
}
else {
display_wallet * panel = new display_wallet ( this , m_LastUsedSqlite ) ;
m_panel = panel ;
}
this - > RestorePositionFromConfig ( ClientToWindowSize ( m_panel - > GetBestSize ( ) ) ) ;
SetClientSize ( GetClientSize ( ) ) ;
}
catch ( const std : : exception & e ) {
2022-04-02 22:07:41 -04:00
// cannot throw when no window is available. Construction of the base frame has to be completed,
// come what may.
2022-02-16 00:53:01 -05:00
// if an exception propagated from the constructor of the derived frame, it would destruct the base frame
// and chaos would ensue as a windowing program attempts to handle an error with no main window.
// so exceptions in the constructor of the main frame have to be caught and not rethrown.
queue_error_message ( e . what ( ) ) ;
}
}
2022-04-02 22:07:41 -04:00
void Frame : : OnMyCloseMpanel ( wxCommandEvent & event ) {
if ( m_panel ) {
m_panel - > Close ( true ) ;
}
}
2022-02-16 00:53:01 -05:00
void Frame : : OnExit ( wxCommandEvent & event ) {
2022-04-02 22:07:41 -04:00
if ( m_panel ) {
m_panel - > Close ( true ) ;
m_panel = nullptr ;
}
2022-02-16 00:53:01 -05:00
Close ( true ) ;
}
void Frame : : OnClose ( wxCloseEvent & event ) {
// This event gives you the opportunity to clean up anything that needs explicit cleanup, albeit if you have done your work right nothing should need explicit cleanup,
// and to object to the closing in a "file not saved" type situation.
// https://docs.wxwidgets.org/trunk/classwx_close_event.html
2022-04-02 22:07:41 -04:00
if ( sqlite3_shutdown ( ) ) wxMessageBox ( _T ( R " |(Sqlite3 shutdown error)| " ) , wsz_error , wxICON_ERROR ) ;
DestroyChildren ( ) ;
2022-02-16 00:53:01 -05:00
Destroy ( ) ; //Default handler will destroy the window. This is our handler for the user calling close, replacing the default handler.
}
void Frame : : OnAbout ( wxCommandEvent & event )
{
2022-04-02 22:07:41 -04:00
wxMessageBox ( szAboutWallet ,
szAboutTitle , wxOK | wxICON_INFORMATION ) ;
2022-02-16 00:53:01 -05:00
}
void Frame : : OnDeleteConfiguration ( wxCommandEvent & )
{
std : : unique_ptr < wxConfigBase > pConfig { wxConfigBase : : Set ( nullptr ) } ;
if ( pConfig )
{
if ( pConfig - > DeleteAll ( ) )
{
wxLogMessage ( _T ( " Config file/registry key successfully deleted. " ) ) ;
wxConfigBase : : DontCreateOnDemand ( ) ;
pConfig . release ( ) ;
}
else
{
wxLogError ( _T ( " Deleting config file/registry key failed. " ) ) ;
}
}
else {
wxLogError ( _T ( " No config to delete! " ) ) ;
return ;
}
}
using ro : : bin2hex , ro : : to_base64_string ;
2022-04-14 05:17:18 -04:00
void Frame : : NewWallet ( wxFileName & filename , ristretto255 : : hash < 256 > & secret ) {
/*If creation fails, abort with exception. If it succeeds, set LastUsed to default filename.
The exception in unit test should simply generate an error message , but if run during initialization ,
should bring up the more complex UI for constructing or selecting your wallet file . */
wxLogMessage ( _wx ( " New wallet file %s " ) , filename . GetFullPath ( ) ) ;
std : : unique_ptr < ISqlite3 > db { nullptr } ;
try {
// Disk operations to create wallet, which may throw.
// This try/catch block exists to catch disk io issues.
db . reset ( Sqlite3_create ( filename . GetFullPath ( ) . ToUTF8 ( ) ) ) ;
db - > exec ( R " |(
2022-02-16 00:53:01 -05:00
PRAGMA journal_mode = WAL ;
PRAGMA synchronous = 1 ;
BEGIN TRANSACTION ;
CREATE TABLE " Keys " (
" pubkey " BLOB NOT NULL UNIQUE PRIMARY KEY ,
" id " integer NOT NULL ,
" use " INTEGER NOT NULL ) ;
CREATE TABLE " Names " (
" name " TEXT NOT NULL UNIQUE
) ;
CREATE TABLE " Misc " (
" index " INTEGER NOT NULL UNIQUE PRIMARY KEY ,
" m " BLOB
) ;
COMMIT ; ) | " );
2022-04-14 05:17:18 -04:00
wxLogMessage ( " \t \t Constructing default wallet %s " , filename . GetFullPath ( ) ) ;
// We now have a working wallet file with no valid data. Attempting to create a strong random secret, a name, and public and private keys for that name.
wxLogMessage ( " \t \t Generating random 128 bit wallet secret " ) ;
auto text_secret { DeriveTextSecret ( ristretto255 : : scalar : : random ( ) , 1 ) } ;
ro : : msec start_time { ro : : msec_since_epoch ( ) } ;
ristretto255 : : CMasterSecret MasterSecret ( DeriveStrongSecret ( & text_secret [ 0 ] ) ) ;
decltype ( start_time ) end_time { ro : : msec_since_epoch ( ) } ;
wxLogMessage ( " \t \t Strong secret derivation took %d milliseconds " , ( end_time - start_time ) . count ( ) ) ;
sql_update_to_misc update_to_misc ( db ) ;
update_to_misc ( 1 , WALLET_FILE_IDENTIFIER ) ;
update_to_misc ( 2 , WALLET_FILE_SCHEMA_VERSION_0_0 ) ;
update_to_misc ( 3 , & text_secret [ 0 ] ) ;
update_to_misc ( 4 , MasterSecret ) ;
}
catch ( const MyException & e ) {
ILogError ( R " |(Failed to create or failed to properly initialize wallet)| " ) ;
errorCode = 20 ;
szError = e . what ( ) ;
ILogError ( szError . c_str ( ) ) ;
}
2022-02-16 00:53:01 -05:00
}
void Frame : : OnSaveNew ( wxCommandEvent & WXUNUSED ( event ) )
{
wxFileDialog dialog ( this ,
sz_new_wallet_new_secret ,
wxStandardPaths : : Get ( ) . GetUserLocalDataDir ( ) ,
sz_default_wallet_name ,
sz_wallet_files_title ,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT ) ;
dialog . SetFilterIndex ( 1 ) ;
if ( dialog . ShowModal ( ) = = wxID_OK )
{
wxLogMessage ( " %s, filter %d " ,
dialog . GetPath ( ) , dialog . GetFilterIndex ( ) ) ;
}
2022-05-13 01:31:48 -04:00
wxString wxStrWallet { dialog . GetDirectory ( ) + " / " + dialog . GetFilename ( ) } ;
wxFileName wxFileWallet ( wxStrWallet ) ;
ristretto255 : : hash < 256 > WalletSecret { wxStrWallet . ToUTF8 ( ) } ;
NewWallet ( wxFileWallet , WalletSecret ) ;
wxLogMessage ( " new wallet created: %s " , wxStrWallet ) ;
wxConfigBase : : Get ( ) - > Write ( _T ( " /Wallet/ LastUsed " ) , wxStrWallet ) ;
2022-02-16 00:53:01 -05:00
}
void Frame : : OnFileOpen ( wxCommandEvent & ) {
wxString directory { _T ( " " ) } ;
wxString file { _T ( " " ) } ;
if ( m_LastUsedSqlite . IsOk ( ) ) {
directory = m_LastUsedSqlite . GetPath ( ) ;
file = m_LastUsedSqlite . GetFullName ( ) ;
}
wxFileDialog
dialog ( this , sz_open_wallet_file , directory , file ,
sz_wallet_files_title , wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR ) ;
if ( dialog . ShowModal ( ) = = wxID_CANCEL )
return ; // the user changed idea...
wxLogMessage ( " Opening %s " , dialog . GetPath ( ) ) ;
wxFileName walletfile ( dialog . GetPath ( ) ) ;
if ( m_panel ) m_panel - > Destroy ( ) ; //Destroy somehow manages to execute
2022-05-13 01:31:48 -04:00
// the correct derived destructor regardless of what kind of object it is.
display_wallet * panel = new display_wallet ( this , walletfile ) ;
2022-02-16 00:53:01 -05:00
m_panel = panel ;
m_panel - > Show ( ) ;
}
void Frame : : RecreateWalletFromExistingSecret ( wxCommandEvent & ) {
wxMessageBox ( _T ( " new wallet existing secret event " ) , _T ( " " ) ) ;
auto standardpaths = wxStandardPaths : : Get ( ) ;
wxFileDialog dialog ( this ,
sz_new_wallet_existing_secret ,
wxStandardPaths : : Get ( ) . GetAppDocumentsDir ( ) ,
sz_default_wallet_name ,
sz_wallet_files_title ,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT ) ;
dialog . SetFilterIndex ( 1 ) ;
if ( dialog . ShowModal ( ) = = wxID_OK )
{
wxLogMessage ( " %s, filter %d " ,
dialog . GetPath ( ) , dialog . GetFilterIndex ( ) ) ;
}
}
void Frame : : OnDelete ( wxCommandEvent & WXUNUSED ( event ) )
{
singletonApp - > pConfig - > SetPath ( _T ( " /Wallet " ) ) ;
wxFileName LastUsedSqlite ( singletonApp - > pConfig - > Read ( _T ( " LastUsed " ) , _T ( " " ) ) ) ;
singletonApp - > pConfig - > DeleteEntry ( _T ( " LastUsed " ) ) ;
if ( LastUsedSqlite . IsOk ( ) & & LastUsedSqlite . FileExists ( ) ) {
if ( wxRemoveFile ( LastUsedSqlite . GetFullPath ( ) ) ) wxLogMessage ( _T ( " Deleting % s " ) , LastUsedSqlite . GetFullPath ( ) ) ;
}
}
void Frame : : OnMenuOpen ( wxMenuEvent & evt ) {
auto pMenu ( evt . GetMenu ( ) ) ;
if ( pMenu ) {
auto label ( pMenu - > GetTitle ( ) ) ;
wxLogMessage ( _T ( " Open menu \" %s \" " ) , label ) ;
}
}
Frame : : ~ Frame ( ) {
assert ( singletonFrame = = this ) ;
singletonFrame = nullptr ;
wxConfigBase * pConfig = wxConfigBase : : Get ( ) ;
if ( pConfig = = nullptr ) return ;
StorePositionToConfig ( ) ;
pConfig - > Write ( _T ( " /Wallet/LastUsed " ) , m_LastUsedSqlite . GetFullPath ( ) ) ;
2022-04-02 22:07:41 -04:00
}