/* * appmysql.cpp * * Created on: Oct 14, 2025 * Author: user */ #include "sqlite3.h" #include "cardinal825.h" #include "../appinfo.h" #include "../apphelpers.h" #include "appdatabase.h" using namespace std; enum { DB_CFG_MODE = 21, DB_CFG_SERVER, DB_CFG_SERVER2, DB_CFG_USER, DB_CFG_PASSWORD, DB_CFG_DATABASE }; void CAppDatabaseCfg::UpdateConfigForm(CForm *pForm) { AppDbType mode = appDataSQLite; CFormInput *pMode = dynamic_cast(pForm->GetItemByIDVal(DB_CFG_MODE)); if(pMode != nullptr) { mode = static_cast(pMode->GetSelItem()); } if(mode == appDataMySQL || mode == appDataMSSQL) { pForm->ShowItem(DB_CFG_SERVER); pForm->ShowItem(DB_CFG_SERVER2); pForm->ShowItem(DB_CFG_USER); pForm->ShowItem(DB_CFG_PASSWORD); pForm->ShowItem(DB_CFG_DATABASE); } else { pForm->HideItem(DB_CFG_SERVER); pForm->HideItem(DB_CFG_SERVER2); pForm->HideItem(DB_CFG_USER); pForm->HideItem(DB_CFG_PASSWORD); pForm->HideItem(DB_CFG_DATABASE); } } EVENT(ConfigMySQLShow) { ClearScreenAndShowTitle(pForm, "Database Configuration"); return 0; } EVENT(DatabaseModeChg) { CAppDatabaseCfg* p = static_cast(pForm->GetUserStruct()); if(p != nullptr) { p->UpdateConfigForm(pForm); } return 0; } int show_db_callback(char* response, void* data) { DEBUG_MSG2("Res [%s]\n", response); vector* lines = (vector*)data; lines->push_back(response); return 0; } int CAppDatabaseCfg::Config(void) { int n = 0; uint8 mode = static_cast(dbType_); string server = server_; string server2 = server2_; string user = user_; string password = password_; string database = database_; #if ARM64 CFormRect rectInpBtn; CFormButton btnOk; while(1) { FORM_INIT(MySQL, EventConfigMySQLShow, NULL, NULL, NULL, /*nFormFlgShowHelp |*/ nFormFlgAutoPresentPopup | nFormFlgShowPopupTabKeypad); SetupInputFormToUseFontSet(formMySQL, rectInpBtn, 0.40, 1.2); CFormAdvanceY advY; advY.SetBasedOnFont(formFontSet.GetFont(fontIndexPrompt), 1.4); FORM_ADD_INPUT2(MySQL, Mode, rectInpBtn, rectKeypad, "Mode: ", 14, 0, 2, EventDatabaseModeChg, mode, FORM_UINT8_SEL | FORM_FLAG_POPUP_LEFT_PROMPT, "SQLite|MySQL|SQL Server", NULL, DB_CFG_MODE); rectInpBtn += advY; FORM_ADD_INPUT2(MySQL, Server, rectInpBtn, rectKeypad, "Server: ", 40, 0, 0, NULL, server, FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, NULL, NULL, DB_CFG_SERVER); rectInpBtn += advY; FORM_ADD_INPUT2(MySQL, Server2, rectInpBtn, rectKeypad, " ", 40, 0, 0, NULL, server2, FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, NULL, NULL, DB_CFG_SERVER2); rectInpBtn += advY; FORM_ADD_INPUT2(MySQL, User, rectInpBtn, rectKeypad, "User: ", 40, 0, 0, NULL, user, FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, NULL, NULL, DB_CFG_USER); rectInpBtn += advY; FORM_ADD_INPUT2(MySQL, Password, rectInpBtn, rectKeypad, "Password: ", 40, 0, 0, NULL, password, FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, NULL, NULL, DB_CFG_PASSWORD); rectInpBtn += advY; FORM_ADD_INPUT2(MySQL, Database, rectInpBtn, rectKeypad, "Database: ", 40, 0, 0, NULL, database, FORM_STR | FORM_FLAG_POPUP_LEFT_PROMPT | FORM_FLAG_DISABLE, NULL, NULL, DB_CFG_DATABASE); formMySQL.LeftAlignPromptInputs(inpMode, inpDatabase); AddFormOkButton(formMySQL, btnOk); formMySQL.SetUserStruct(this); FORM_SHOW(MySQL); UpdateConfigForm(&formMySQL); n = FORM_RUN(MySQL); FORM_HIDE(MySQL); if(n == FORM_RESULT_ESC || static_cast(mode) == appDataSQLite) { break; } if(password.length() < 3) { DrawMessageBox("Password too short", 2); } else { break; } } if (n != FORM_RESULT_ESC) { if(static_cast(mode) != dbType_ || server_ != server || server2_ != server2 || user_ != user || password_ != password || database_ != database) { if (DrawConfirmBox("Are you sure you want to change database settings?", LANG(STR_YES), LANG(STR_NO))) { dbType_ = static_cast(mode); server_ = server; server2_ = server2; user_ = user; password_ = password; database_ = database; chg_ = true; WriteJSON(); if(dbType_ == appDataMySQL) { if(server_ == "127.0.0.1" || server_ == "localhost") { bool checkForDatabase = false; if(IsServiceActive("mysqld") == false) { if (DrawConfirmBox("Enable local MySQL Server?", LANG(STR_YES), LANG(STR_NO))) { SetService("mysqld", true); SleepMilliseconds(1000); DoShellCmd("sudo enablemysql"); checkForDatabase = true; } } else { checkForDatabase = true; } if(checkForDatabase) { // Check if database exists vector lines; bool found = false; const char* cmd = "sudo mysql -e \"show databases;\""; DoShellCmd(cmd, show_db_callback, &lines); for(auto& line : lines) { DEBUG_MSG("response [%s]\n", line.c_str()); if(line == database_) { DEBUG_MSG("%s found\n", database_.c_str()); found = true; } } if(found == false) { if (DrawConfirmBox("Create database?", LANG(STR_YES), LANG(STR_NO))) { string cmd = "sudo createdb " + database_; DoShellCmd(cmd.c_str()); SleepMilliseconds(200); cmd = "sudo createdbuser " + database_ + " " + user_ + " \"" + password_ + "\""; DoShellCmd(cmd.c_str()); } } } } } DrawMessageBox("Restart app to apply database changes", 4); } } } #else #endif return n; } EVENT(ConfigDBFirstTimeShow) { ClearScreenAndShowTitle(pForm, "Database first-time configuration"); CFormRect rect; CFormAdvanceY advY; rect.SetTopAndHeightBasedOnFont(pForm->GetFontSet()->GetFont(fontIndexSmallPrompt), 2.4, 1.0); rect.SetLeftAndWidthBasedOnDspArea(pForm->GetDspArea(), 0.03, 0.92); advY.SetBasedOnFont(pForm->GetFontSet()->GetFont(fontIndexSmallPrompt), 1.0); const char* lines[] = { "Select \"SQLite\" for legacy 825 style database.", "", "Select \"Local MySQL\" to be able to view reports of the", "data on this indicator's web page.", "", "Select \"Advanced\" for a custom configuration such as using", "a MySQL database on another server." }; int n; SetCurColor(COLOR_REQUEST); for(n = 0; n < ARRAY_ELEMS(lines); n++) { if(lines[n][0] != '\0') { pForm->GetFontSet()->GetFont(fontIndexSmallPrompt).DisplayTextCairo(rect, lines[n]); } rect += advY; } return 0; } enum { FIRSTTIME_DB_SQLITE = 1, FIRSTTIME_DB_LOCAL_MYSQL, FIRSTTIME_DB_ADVANCED }; int CAppDatabaseCfg::FirstTimePrompt(void) { CFormRect rect; FORM_INIT(FirstTime, EventConfigDBFirstTimeShow, NULL, NULL, NULL, 0); SetupMenuFormToUseFontSet(formFirstTime, rect, MENU_BTN_WIDE_WIDTH); rect.SetTopBasedOnFont(formFontSet.GetFont(fontIndexPrompt), 9.0); FORM_ADD_BUTTON2(FirstTime, SQLite, rect, "SQLite", 'S', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_SQLITE); rect += buttonAdvanceY; FORM_ADD_BUTTON2(FirstTime, MySQL, rect, "Local MySQL - Allows web page reporting", 'M', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_LOCAL_MYSQL); rect += buttonAdvanceY; FORM_ADD_BUTTON2(FirstTime, Advanced, rect, "Advanced", 'M', nullptr, FORM_BUTTON_SHADOW | FORM_FLAG_BTN_RETURN_ID, "", FIRSTTIME_DB_ADVANCED); FORM_SHOW(FirstTime); int n = FORM_RUN(FirstTime); FORM_HIDE(FirstTime); if(n == FIRSTTIME_DB_LOCAL_MYSQL) { DEBUG_MSG("Create MySQL database\n"); dbType_ = appDataMySQL; server_ = "127.0.0.1"; user_ = MYSQL_DEFAULT_DBUSER; password_ = "81440"; database_ = MYSQL_DEFAULT_DB; chg_ = true; WriteJSON(); if(IsServiceActive("mysqld") == false) { SetService("mysqld", true); SleepMilliseconds(1000); DoShellCmd("sudo enablemysql"); } vector lines; bool found = false; const char* cmd = "sudo mysql -e \"show databases;\""; DoShellCmd(cmd, show_db_callback, &lines); for(auto& line : lines) { DEBUG_MSG("response [%s]\n", line.c_str()); if(line == database_) { DEBUG_MSG("%s found\n", database_.c_str()); found = true; } } if(found == false) { //if (DrawConfirmBox("Create database?", LANG(STR_YES), LANG(STR_NO))) { string cmd = "sudo createdb " + database_; DoShellCmd(cmd.c_str()); SleepMilliseconds(200); cmd = "sudo createdbuser " + database_ + " " + user_ + " \"" + password_ + "\""; DoShellCmd(cmd.c_str()); //} } } else if(n == FIRSTTIME_DB_ADVANCED) { Config(); } DEBUG_MSG("Calling WriteJSON [%s]\n", GetJSONFilepath().c_str()); WriteJSON(); return n; }