setupgui/callbacks.cc (380 lines of code) (raw):

// Copyright (c) 2007, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // // This program is designed to work with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, as // designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have either included with // the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of Connector/ODBC, is also subject to the // Universal FOSS Exception, version 1.0, a copy of which can be found at // https://oss.oracle.com/licenses/universal-foss-exception. // // This program 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, version 2.0, for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* TODO no L"" */ #include "setupgui.h" #include "stringutil.h" #include "windows/resource.h" #include <driver.h> #include <error.h> #include <codecvt> #include <locale> SQLWCHAR **errorMsgs= NULL; SQLHDBC hDBC= SQL_NULL_HDBC; /* Tests if it is possible to establish connection using given DS returns message text. user is responsible to free that text after use. */ SQLWSTRING mytest(HWND hwnd, DataSource *params) { SQLWSTRING msg; SQLWCHAR tmpbuf[1024]; SQLHENV hEnv = nullptr; SQLHDBC hDbc = nullptr; /* In case of file data source we do not want it to be created when clicking the Test button */ myodbc::HENV henv; auto preservedSavefile = params->opt_SAVEFILE; params->opt_SAVEFILE.set_default(nullptr); try { myodbc::HDBC hdbc(henv, params); msg = _W(L"Connection successful"); } catch(MYERROR &e) { // Use the ability of optionStr to convert MBchar -> Wchar optionStr e_msg; e_msg = e.message; optionStr e_sqlstate; e_sqlstate = e.sqlstate; msg = _W(L"Connection failed with the following error:\n"); msg.append((const SQLWSTRING &)e_msg); msg.append(_W(L"[")); msg.append((const SQLWSTRING &)e_sqlstate); msg.append(_W(L"]")); } /* Restore savefile parameter */ params->opt_SAVEFILE = preservedSavefile; return msg; } BOOL mytestaccept(HWND hwnd, DataSource* params) { /* TODO validation */ return TRUE; } std::vector<SQLWSTRING> mygetdatabases(HWND hwnd, DataSource* params) { SQLRETURN ret; SQLWCHAR catalog[MYODBC_DB_NAME_MAX]; SQLLEN n_catalog; auto preserved_database = params->opt_DATABASE; auto preserved_no_catalog = params->opt_NO_CATALOG; std::vector<SQLWSTRING> result; result.reserve(20); /* In case of file data source we do not want it to be created when clicking the Test button */ auto preserved_savefile = params->opt_SAVEFILE; params->opt_SAVEFILE.set_default(nullptr); params->opt_DATABASE.set_default(nullptr); params->opt_NO_CATALOG.set_default(false); try { myodbc::HENV henv; myodbc::HDBC hdbc(henv, params); params->opt_SAVEFILE = preserved_savefile; params->opt_DATABASE = preserved_database; params->opt_NO_CATALOG = preserved_no_catalog; myodbc::HSTMT hstmt(hdbc); SQLWCHAR tmpbuf[1024]; SQLWCHAR empty = 0; SQLWCHAR *w_all = _W(L"%"); ret = SQLTablesW(hstmt, w_all, SQL_NTS, &empty, 0, &empty, 0, &empty, 0); if (!SQL_SUCCEEDED(ret)) return result; ret = SQLBindCol(hstmt, 1, SQL_C_WCHAR, catalog, MYODBC_DB_NAME_MAX, &n_catalog); if (!SQL_SUCCEEDED(ret)) return result; while (true) { if (result.size() % 20) result.reserve(result.size() + 20); if (SQL_SUCCEEDED(SQLFetch(hstmt))) result.emplace_back(catalog); else break; } } catch (...) { } return result; } std::vector<SQLWSTRING> mygetcharsets(HWND hwnd, DataSource* params) { SQLRETURN ret; SQLWCHAR charset[MYODBC_DB_NAME_MAX] = { 0 }; SQLLEN n_charset = 0; auto preserved_database = params->opt_DATABASE; auto preserved_no_catalog= params->opt_NO_CATALOG; SQLWCHAR tmpbuf[1024]; std::vector<SQLWSTRING> csl; csl.reserve(20); /* In case of file data source we do not want it to be created when clicking the Test button */ auto preserved_savefile = params->opt_SAVEFILE; params->opt_SAVEFILE.set_default(nullptr); params->opt_DATABASE.set_default(nullptr); params->opt_NO_CATALOG.set_default(false); try { myodbc::HENV henv; myodbc::HDBC hdbc(henv, params); params->opt_SAVEFILE = preserved_savefile; params->opt_DATABASE = preserved_database; params->opt_NO_CATALOG = preserved_no_catalog; myodbc::HSTMT hstmt(hdbc); #ifdef DRIVER_ANSI /* Skip undesired charsets */ nReturn = SQLExecDirectW(hStmt, _W(L"SHOW CHARACTER SET WHERE " "charset <> 'utf16' AND " "charset <> 'utf32' AND " "charset <> 'ucs2'"), SQL_NTS); #else ret = SQLExecDirectW(hstmt, _W(L"SHOW CHARACTER SET"), SQL_NTS); #endif if (!SQL_SUCCEEDED(ret)) return csl; ret = SQLBindCol(hstmt, 1, SQL_C_WCHAR, charset, MYODBC_DB_NAME_MAX, &n_charset); if (!SQL_SUCCEEDED(ret)) return csl; while (true) { if (csl.size() % 20) csl.reserve(csl.size() + 20); if (SQL_SUCCEEDED(SQLFetch(hstmt))) csl.emplace_back(charset); else break; } } catch (...) { } return csl; } /* Init DataSource from the main dialog controls */ void syncData(HWND hwnd, DataSource *params) { GET_STRING(DSN); GET_STRING(DESCRIPTION); GET_STRING(SERVER); GET_STRING(SOCKET); GET_UNSIGNED(PORT); GET_STRING(UID); GET_STRING(PWD); GET_COMBO(DATABASE); #ifdef _WIN32 /* use this flag exclusively for Windows */ if (READ_BOOL(hwnd, IDC_RADIO_NAMED_PIPE)) params->opt_NAMED_PIPE = true; else params->opt_NAMED_PIPE.set_default(false); #endif } /* Set the main dialog controls using DataSource */ void syncForm(HWND hwnd, DataSource *params) { SET_STRING(DSN); SET_STRING(DESCRIPTION); SET_STRING(SERVER); SET_UNSIGNED(PORT); SET_STRING(UID); SET_STRING(PWD); SET_STRING(SOCKET); SET_COMBO(DATABASE); #ifdef _WIN32 if (params->opt_NAMED_PIPE) { SET_RADIO(hwnd, IDC_RADIO_NAMED_PIPE, TRUE); } else { SET_RADIO(hwnd, IDC_RADIO_tcp, TRUE); } SwitchTcpOrPipe(hwnd, params->opt_NAMED_PIPE); #else if (params->opt_SOCKET) { /* this flag means the socket file in Linux */ SET_CHECKED(__UNUSED, use_socket_file, TRUE); SET_SENSITIVE(SERVER, FALSE); SET_SENSITIVE(SOCKET, TRUE); } else { SET_CHECKED(__UNUSED, use_tcp_ip_server, TRUE); SET_SENSITIVE(SERVER, TRUE); SET_SENSITIVE(SOCKET, FALSE); } #endif } #undef CLIENT_INTERACTIVE /* Sets the DataSource fields from the dialog inputs */ void syncTabsData(HWND hwnd, DataSource *params) { /* 1 - Connection */ GET_BOOL_TAB(CONNECTION_TAB, BIG_PACKETS); GET_BOOL_TAB(CONNECTION_TAB, COMPRESSED_PROTO); GET_BOOL_TAB(CONNECTION_TAB, NO_PROMPT); #if MYSQL_VERSION_ID < 80300 GET_BOOL_TAB(CONNECTION_TAB, AUTO_RECONNECT); #endif GET_BOOL_TAB(CONNECTION_TAB, MULTI_STATEMENTS); GET_BOOL_TAB(CONNECTION_TAB, CLIENT_INTERACTIVE); GET_BOOL_TAB(CONNECTION_TAB, CAN_HANDLE_EXP_PWD); GET_BOOL_TAB(CONNECTION_TAB, GET_SERVER_PUBLIC_KEY); GET_BOOL_TAB(CONNECTION_TAB, ENABLE_DNS_SRV); if (params->opt_ENABLE_DNS_SRV.is_set() && params->opt_ENABLE_DNS_SRV) params->opt_PORT.set_default(3306); GET_BOOL_TAB(CONNECTION_TAB, MULTI_HOST); GET_COMBO_TAB(CONNECTION_TAB, CHARSET); GET_STRING_TAB(CONNECTION_TAB, INITSTMT); GET_STRING_TAB(CONNECTION_TAB, PLUGIN_DIR); /* 2 - Authentication */ GET_BOOL_TAB(AUTH_TAB, ENABLE_CLEARTEXT_PLUGIN); #ifdef _WIN32 GET_STRING_TAB(AUTH_TAB, AUTHENTICATION_KERBEROS_MODE); #endif GET_STRING_TAB(AUTH_TAB, DEFAULT_AUTH); #if MFA_ENABLED GET_STRING_TAB(AUTH_TAB, pwd2); GET_STRING_TAB(AUTH_TAB, pwd3); #endif GET_STRING_TAB(AUTH_TAB, OCI_CONFIG_FILE); GET_STRING_TAB(AUTH_TAB, OCI_CONFIG_PROFILE); GET_STRING_TAB(AUTH_TAB, OPENID_TOKEN_FILE); GET_UNSIGNED_TAB(AUTH_TAB, WEBAUTHN_DEVICE_NUMBER); /* 3 - Metadata*/ GET_BOOL_TAB(METADATA_TAB, NO_BIGINT); GET_BOOL_TAB(METADATA_TAB, NO_BINARY_RESULT); GET_BOOL_TAB(METADATA_TAB, FULL_COLUMN_NAMES); GET_BOOL_TAB(METADATA_TAB, NO_CATALOG); GET_BOOL_TAB(METADATA_TAB, NO_SCHEMA); GET_BOOL_TAB(METADATA_TAB, COLUMN_SIZE_S32); /* 4 - Cursors/Results */ GET_BOOL_TAB(CURSORS_TAB, FOUND_ROWS); GET_BOOL_TAB(CURSORS_TAB, AUTO_IS_NULL); GET_BOOL_TAB(CURSORS_TAB, DYNAMIC_CURSOR); GET_BOOL_TAB(CURSORS_TAB, NO_DEFAULT_CURSOR); GET_BOOL_TAB(CURSORS_TAB, PAD_SPACE); GET_BOOL_TAB(CURSORS_TAB, NO_CACHE); GET_BOOL_TAB(CURSORS_TAB, FORWARD_CURSOR); GET_BOOL_TAB(CURSORS_TAB, ZERO_DATE_TO_MIN); if (READ_BOOL_TAB(CURSORS_TAB, cursor_prefetch_active)) { GET_UNSIGNED_TAB(CURSORS_TAB, PREFETCH); } else { params->opt_PREFETCH = 0; } /* 5 - debug*/ GET_BOOL_TAB(DEBUG_TAB,LOG_QUERY); /* 6 - ssl related */ GET_STRING_TAB(SSL_TAB, SSL_KEY); GET_STRING_TAB(SSL_TAB, SSL_CERT); GET_STRING_TAB(SSL_TAB, SSL_CA); GET_STRING_TAB(SSL_TAB, SSL_CAPATH); GET_STRING_TAB(SSL_TAB, SSL_CIPHER); GET_COMBO_TAB(SSL_TAB, SSL_MODE); GET_STRING_TAB(SSL_TAB, RSAKEY); GET_BOOL_TAB(SSL_TAB, NO_TLS_1_2); GET_BOOL_TAB(SSL_TAB, NO_TLS_1_3); GET_STRING_TAB(SSL_TAB, TLS_VERSIONS); GET_STRING_TAB(SSL_TAB, SSL_CRL); GET_STRING_TAB(SSL_TAB, SSL_CRLPATH); /* 7 - Misc*/ GET_BOOL_TAB(MISC_TAB, SAFE); GET_BOOL_TAB(MISC_TAB, NO_LOCALE); GET_BOOL_TAB(MISC_TAB, IGNORE_SPACE); GET_BOOL_TAB(MISC_TAB, USE_MYCNF); GET_BOOL_TAB(MISC_TAB, NO_TRANSACTIONS); GET_BOOL_TAB(MISC_TAB, MIN_DATE_TO_ZERO); GET_BOOL_TAB(MISC_TAB, NO_SSPS); GET_BOOL_TAB(MISC_TAB, DFLT_BIGINT_BIND_STR); GET_BOOL_TAB(MISC_TAB, NO_DATE_OVERFLOW); GET_BOOL_TAB(MISC_TAB, ENABLE_LOCAL_INFILE); GET_STRING_TAB(MISC_TAB, LOAD_DATA_LOCAL_DIR); } /* Sets the options in the dialog tabs using DataSource */ void syncTabs(HWND hwnd, DataSource *params) { /* 1 - Connection */ SET_BOOL_TAB(CONNECTION_TAB, BIG_PACKETS); SET_BOOL_TAB(CONNECTION_TAB, COMPRESSED_PROTO); SET_BOOL_TAB(CONNECTION_TAB, NO_PROMPT); #if MYSQL_VERSION_ID < 80300 SET_BOOL_TAB(CONNECTION_TAB, AUTO_RECONNECT); #endif SET_BOOL_TAB(CONNECTION_TAB, ENABLE_DNS_SRV); SET_BOOL_TAB(CONNECTION_TAB, MULTI_STATEMENTS); SET_BOOL_TAB(CONNECTION_TAB, CLIENT_INTERACTIVE); SET_BOOL_TAB(CONNECTION_TAB, CAN_HANDLE_EXP_PWD); SET_BOOL_TAB(CONNECTION_TAB, GET_SERVER_PUBLIC_KEY); SET_BOOL_TAB(CONNECTION_TAB, ENABLE_DNS_SRV); SET_BOOL_TAB(CONNECTION_TAB, MULTI_HOST); #ifdef _WIN32 if ( getTabCtrlTabPages(CONNECTION_TAB-1)) #endif { if (is_unicode) { #ifdef _WIN32 SET_ENABLED(CONNECTION_TAB, IDC_EDIT_CHARSET, FALSE); #else SET_SENSITIVE(CHARSET, FALSE); #endif } else { SET_COMBO_TAB(CONNECTION_TAB, CHARSET); } SET_STRING_TAB(CONNECTION_TAB, INITSTMT); SET_STRING_TAB(CONNECTION_TAB, PLUGIN_DIR); } /* 2 - Authentication */ SET_BOOL_TAB(AUTH_TAB, ENABLE_CLEARTEXT_PLUGIN); #ifdef _WIN32 SET_STRING_TAB(AUTH_TAB, AUTHENTICATION_KERBEROS_MODE); #endif SET_STRING_TAB(AUTH_TAB, DEFAULT_AUTH); #if MFA_ENABLED SET_STRING_TAB(AUTH_TAB, PWD2); SET_STRING_TAB(AUTH_TAB, PWD3); #endif SET_STRING_TAB(AUTH_TAB, OCI_CONFIG_FILE); SET_STRING_TAB(AUTH_TAB, OCI_CONFIG_PROFILE); SET_STRING_TAB(AUTH_TAB, OPENID_TOKEN_FILE); SET_UNSIGNED_TAB(AUTH_TAB, WEBAUTHN_DEVICE_NUMBER); /* 3 - Metadata*/ SET_BOOL_TAB(METADATA_TAB, NO_BIGINT); SET_BOOL_TAB(METADATA_TAB, NO_BINARY_RESULT); SET_BOOL_TAB(METADATA_TAB, FULL_COLUMN_NAMES); SET_BOOL_TAB(METADATA_TAB, NO_CATALOG); SET_BOOL_TAB(METADATA_TAB, NO_SCHEMA); SET_BOOL_TAB(METADATA_TAB, COLUMN_SIZE_S32); /* 4 - Cursors/Results */ SET_BOOL_TAB(CURSORS_TAB, FOUND_ROWS); SET_BOOL_TAB(CURSORS_TAB, AUTO_IS_NULL); SET_BOOL_TAB(CURSORS_TAB, DYNAMIC_CURSOR); SET_BOOL_TAB(CURSORS_TAB, NO_DEFAULT_CURSOR); SET_BOOL_TAB(CURSORS_TAB, PAD_SPACE); SET_BOOL_TAB(CURSORS_TAB, NO_CACHE); SET_BOOL_TAB(CURSORS_TAB, FORWARD_CURSOR); SET_BOOL_TAB(CURSORS_TAB, ZERO_DATE_TO_MIN); if(params->opt_PREFETCH > 0) { #ifdef _WIN32 SET_ENABLED(CURSORS_TAB, IDC_EDIT_PREFETCH, TRUE); #endif SET_CHECKED_TAB(CURSORS_TAB, cursor_prefetch_active, TRUE); SET_UNSIGNED_TAB(CURSORS_TAB, PREFETCH); } /* 5 - debug*/ SET_BOOL_TAB(DEBUG_TAB,LOG_QUERY); /* 6 - ssl related */ #ifdef _WIN32 if ( getTabCtrlTabPages(SSL_TAB-1) ) #endif { if(params->opt_SSL_KEY) SET_STRING_TAB(SSL_TAB, SSL_KEY); if (params->opt_SSL_CERT) SET_STRING_TAB(SSL_TAB, SSL_CERT); if (params->opt_SSL_CA) SET_STRING_TAB(SSL_TAB, SSL_CA); if (params->opt_SSL_CAPATH) SET_STRING_TAB(SSL_TAB, SSL_CAPATH); if (params->opt_SSL_CIPHER) SET_STRING_TAB(SSL_TAB, SSL_CIPHER); if (params->opt_SSL_MODE) SET_COMBO_TAB(SSL_TAB, SSL_MODE); if (params->opt_RSAKEY) SET_STRING_TAB(SSL_TAB, RSAKEY); if (params->opt_SSL_CRL) SET_STRING_TAB(SSL_TAB, SSL_CRL); if (params->opt_SSL_CRLPATH) SET_STRING_TAB(SSL_TAB, SSL_CRLPATH); SET_BOOL_TAB(SSL_TAB, NO_TLS_1_2); SET_BOOL_TAB(SSL_TAB, NO_TLS_1_3); SET_STRING_TAB(SSL_TAB, TLS_VERSIONS); } /* 7 - Misc*/ SET_BOOL_TAB(MISC_TAB, SAFE); SET_BOOL_TAB(MISC_TAB, NO_LOCALE); SET_BOOL_TAB(MISC_TAB, IGNORE_SPACE); SET_BOOL_TAB(MISC_TAB, USE_MYCNF); SET_BOOL_TAB(MISC_TAB, NO_TRANSACTIONS); SET_BOOL_TAB(MISC_TAB, MIN_DATE_TO_ZERO); SET_BOOL_TAB(MISC_TAB, NO_SSPS); SET_BOOL_TAB(MISC_TAB, DFLT_BIGINT_BIND_STR); SET_BOOL_TAB(MISC_TAB, NO_DATE_OVERFLOW); SET_BOOL_TAB(MISC_TAB, ENABLE_LOCAL_INFILE); SET_STRING_TAB(MISC_TAB, LOAD_DATA_LOCAL_DIR); } void FillParameters(HWND hwnd, DataSource *params) { syncData(hwnd, params ); #if MYSQL_VERSION_ID >= 80300 // Turn off AUTO_RECONNECT unconditionally. params->opt_AUTO_RECONNECT.set_default(false); #endif #ifdef _WIN32 // Controls in Details cannot be read unless it is expanded. if(getTabCtrlTab()) #endif syncTabsData(hwnd, params); }