📄 drvconn.c
字号:
/*------- Module: drvconn.c * * Description: This module contains only routines related to * implementing SQLDriverConnect. * * Classes: n/a * * API functions: SQLDriverConnect * * Comments: See "notice.txt" for copyright and license information. *------- */#include "psqlodbc.h"#include <stdio.h>#include <stdlib.h>#include "connection.h"#ifndef WIN32#include <sys/types.h>#include <sys/socket.h>#define NEAR#else#include <winsock2.h>#endif#include <string.h>#ifdef WIN32#include <windowsx.h>#include "resource.h"#endif#include "pgapifunc.h"#include "dlg_specific.h"#define NULL_IF_NULL(a) (a ? a : "(NULL)")static char * hide_password(const char *str){ char *outstr, *pwdp; if (!str) return NULL; outstr = strdup(str); if (pwdp = strstr(outstr, "PWD="), !pwdp) pwdp = strstr(outstr, "pwd="); if (pwdp) { char *p; for (p=pwdp + 4; *p && *p != ';'; p++) *p = 'x'; } return outstr;}/* prototypes */void dconn_get_connect_attributes(const SQLCHAR FAR * connect_string, ConnInfo *ci);static void dconn_get_common_attributes(const SQLCHAR FAR * connect_string, ConnInfo *ci);#ifdef WIN32LRESULT CALLBACK dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);extern HINSTANCE NEAR s_hModule; /* Saved module handle. */#endifRETCODE SQL_APIPGAPI_DriverConnect( HDBC hdbc, HWND hwnd, const SQLCHAR FAR * szConnStrIn, SQLSMALLINT cbConnStrIn, SQLCHAR FAR * szConnStrOut, SQLSMALLINT cbConnStrOutMax, SQLSMALLINT FAR * pcbConnStrOut, SQLUSMALLINT fDriverCompletion){ CSTR func = "PGAPI_DriverConnect"; ConnectionClass *conn = (ConnectionClass *) hdbc; ConnInfo *ci;#ifdef WIN32 RETCODE dialog_result;#endif BOOL paramRequired, didUI = FALSE; RETCODE result; char *connStrIn = NULL; char connStrOut[MAX_CONNECT_STRING]; int retval; char salt[5]; char password_required = AUTH_REQ_OK; ssize_t len = 0; SQLSMALLINT lenStrout; mylog("%s: entering...\n", func); if (!conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } connStrIn = make_string(szConnStrIn, cbConnStrIn, NULL, 0);#ifdef FORCE_PASSWORD_DISPLAY mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn); qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);#else if (get_qlog() || get_mylog()) { char *hide_str = hide_password(connStrIn); mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, NULL_IF_NULL(hide_str)); qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, NULL_IF_NULL(hide_str), fDriverCompletion); if (hide_str) free(hide_str); }#endif /* FORCE_PASSWORD_DISPLAY */ ci = &(conn->connInfo); /* Parse the connect string and fill in conninfo for this hdbc. */ dconn_get_connect_attributes(connStrIn, ci); /* * If the ConnInfo in the hdbc is missing anything, this function will * fill them in from the registry (assuming of course there is a DSN * given -- if not, it does nothing!) */ getDSNinfo(ci, CONN_DONT_OVERWRITE); dconn_get_common_attributes(connStrIn, ci); logs_on_off(1, ci->drivers.debug, ci->drivers.commlog); if (connStrIn) { free(connStrIn); connStrIn = NULL; } /* Fill in any default parameters if they are not there. */ getDSNdefaults(ci); /* initialize pg_version */ CC_initialize_pg_version(conn); memset(salt, 0, sizeof(salt));#ifdef WIN32dialog:#endif ci->focus_password = password_required;inolog("DriverCompletion=%d\n", fDriverCompletion); switch (fDriverCompletion) {#ifdef WIN32 case SQL_DRIVER_PROMPT: dialog_result = dconn_DoDialog(hwnd, ci); didUI = TRUE; if (dialog_result != SQL_SUCCESS) return dialog_result; break; case SQL_DRIVER_COMPLETE_REQUIRED: /* Fall through */ case SQL_DRIVER_COMPLETE: paramRequired = password_required; /* Password is not a required parameter. */ if (ci->database[0] == '\0') paramRequired = TRUE; else if (ci->port[0] == '\0') paramRequired = TRUE;#ifdef WIN32 else if (ci->server[0] == '\0') paramRequired = TRUE;#endif /* WIN32 */ if (paramRequired) { dialog_result = dconn_DoDialog(hwnd, ci); didUI = TRUE; if (dialog_result != SQL_SUCCESS) return dialog_result; } break;#else case SQL_DRIVER_PROMPT: case SQL_DRIVER_COMPLETE: case SQL_DRIVER_COMPLETE_REQUIRED:#endif case SQL_DRIVER_NOPROMPT: break; } /* * Password is not a required parameter unless authentication asks for * it. For now, I think it's better to just let the application ask * over and over until a password is entered (the user can always hit * Cancel to get out) */ paramRequired = FALSE; if (ci->database[0] == '\0') paramRequired = TRUE; else if (ci->port[0] == '\0') paramRequired = TRUE;#ifdef WIN32 else if (ci->server[0] == '\0') paramRequired = TRUE;#endif /* WIN32 */ if (paramRequired) { if (didUI) return SQL_NO_DATA_FOUND; CC_set_error(conn, CONN_OPENDB_ERROR, "connction string lacks some options", func); return SQL_ERROR; }inolog("before CC_connect\n"); /* do the actual connect */ retval = CC_connect(conn, password_required, salt); if (retval < 0) { /* need a password */ if (fDriverCompletion == SQL_DRIVER_NOPROMPT) { CC_log_error(func, "Need password but Driver_NoPrompt", conn); return SQL_ERROR; /* need a password but not allowed to * prompt so error */ } else {#ifdef WIN32 password_required = -retval; goto dialog;#else return SQL_ERROR; /* until a better solution is found. */#endif } } else if (retval == 0) { /* error msg filled in above */ CC_log_error(func, "Error from CC_Connect", conn); return SQL_ERROR; } /* * Create the Output Connection String */ result = SQL_SUCCESS; lenStrout = cbConnStrOutMax; if (conn->ms_jet && lenStrout > 255) lenStrout = 255; makeConnectString(connStrOut, ci, lenStrout); len = strlen(connStrOut); if (szConnStrOut) { /* * Return the completed string to the caller. The correct method * is to only construct the connect string if a dialog was put up, * otherwise, it should just copy the connection input string to * the output. However, it seems ok to just always construct an * output string. There are possible bad side effects on working * applications (Access) by implementing the correct behavior, * anyway. */ /*strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);*/ strncpy(szConnStrOut, connStrOut, cbConnStrOutMax); if (len >= cbConnStrOutMax) { int clen; for (clen = cbConnStrOutMax - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--) szConnStrOut[clen] = '\0'; result = SQL_SUCCESS_WITH_INFO; CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the ConnStrOut.", func); } } if (pcbConnStrOut) *pcbConnStrOut = (SQLSMALLINT) len;#ifdef FORCE_PASSWORD_DISPLAY if (cbConnStrOutMax > 0) { mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(szConnStrOut), len, cbConnStrOutMax); qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(szConnStrOut)); }#else if (get_qlog() || get_mylog()) { char *hide_str = NULL; if (cbConnStrOutMax > 0) hide_str = hide_password(szConnStrOut); mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str), len, cbConnStrOutMax); qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(hide_str)); if (hide_str) free(hide_str); }#endif /* FORCE_PASSWORD_DISPLAY */ if (connStrIn) free(connStrIn); mylog("PGAPI_DriverConnect: returning %d\n", result); return result;}#ifdef WIN32RETCODEdconn_DoDialog(HWND hwnd, ConnInfo *ci){ LRESULT dialog_result; mylog("dconn_DoDialog: ci = %p\n", ci); if (hwnd) { dialog_result = DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_CONFIG), hwnd, dconn_FDriverConnectProc, (LPARAM) ci); if (!dialog_result || (dialog_result == -1)) return SQL_NO_DATA_FOUND; else return SQL_SUCCESS; } return SQL_ERROR;}LRESULT CALLBACKdconn_FDriverConnectProc( HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam){ ConnInfo *ci; char strbuf[64]; switch (wMsg) { case WM_INITDIALOG: ci = (ConnInfo *) lParam; /* Change the caption for the setup dialog */ SetWindowText(hdlg, "PostgreSQL Connection"); LoadString(s_hModule, IDS_ADVANCE_CONNECTION, strbuf, sizeof(strbuf)); SetWindowText(GetDlgItem(hdlg, IDC_DATASOURCE), strbuf); /* Hide the DSN and description fields */ ShowWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DSNAME), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_DRIVER), SW_HIDE); ShowWindow(GetDlgItem(hdlg, IDC_TEST), SW_HIDE); if ('\0' != ci->server[0]) EnableWindow(GetDlgItem(hdlg, IDC_SERVER), FALSE); if ('\0' != ci->port[0]) EnableWindow(GetDlgItem(hdlg, IDC_PORT), FALSE); SetWindowLongPtr(hdlg, DWLP_USER, lParam); /* Save the ConnInfo for * the "OK" */ SetDlgStuff(hdlg, ci); if (ci->database[0] == '\0') ; /* default focus */ else if (ci->server[0] == '\0') SetFocus(GetDlgItem(hdlg, IDC_SERVER)); else if (ci->port[0] == '\0') SetFocus(GetDlgItem(hdlg, IDC_PORT)); else if (ci->username[0] == '\0') SetFocus(GetDlgItem(hdlg, IDC_USER)); else if (ci->focus_password) SetFocus(GetDlgItem(hdlg, IDC_PASSWORD)); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: ci = (ConnInfo *) GetWindowLongPtr(hdlg, DWLP_USER); GetDlgStuff(hdlg, ci); case IDCANCEL: EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); return TRUE; case IDC_DATASOURCE: ci = (ConnInfo *) GetWindowLongPtr(hdlg, DWLP_USER); DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), hdlg, ds_options1Proc, (LPARAM) ci); break; case IDC_DRIVER: ci = (ConnInfo *) GetWindowLongPtr(hdlg, DWLP_USER); DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV), hdlg, driver_optionsProc, (LPARAM) ci); break; } } return FALSE;}#endif /* WIN32 */typedef void (*copyfunc)(ConnInfo *, const char *attribute, const char *value);static voiddconn_get_attributes(copyfunc func, const SQLCHAR FAR * connect_string, ConnInfo *ci){ char *our_connect_string; const char *pair, *attribute, *value; char *equals; char *strtok_arg;#ifdef HAVE_STRTOK_R char *last;#endif /* HAVE_STRTOK_R */ our_connect_string = strdup(connect_string); strtok_arg = our_connect_string;#ifdef FORCE_PASSWORD_DISPLAY mylog("our_connect_string = '%s'\n", our_connect_string);#else if (get_mylog()) { char *hide_str = hide_password(our_connect_string); mylog("our_connect_string = '%s'\n", hide_str); free(hide_str); }#endif /* FORCE_PASSWORD_DISPLAY */ while (1) {#ifdef HAVE_STRTOK_R pair = strtok_r(strtok_arg, ";", &last);#else pair = strtok(strtok_arg, ";");#endif /* HAVE_STRTOK_R */ if (strtok_arg) strtok_arg = 0; if (!pair) break; equals = strchr(pair, '='); if (!equals) continue; *equals = '\0'; attribute = pair; /* ex. DSN */ value = equals + 1; /* ex. 'CEO co1' */#ifndef FORCE_PASSWORD_DISPLAY if (stricmp(attribute, INI_PASSWORD) == 0 || stricmp(attribute, "pwd") == 0) mylog("attribute = '%s', value = 'xxxxx'\n", attribute); else#endif /* FORCE_PASSWORD_DISPLAY */ mylog("attribute = '%s', value = '%s'\n", attribute, value); if (!attribute || !value) continue; /* Copy the appropriate value to the conninfo */ (*func)(ci, attribute, value); } free(our_connect_string);}voiddconn_get_connect_attributes(const SQLCHAR FAR * connect_string, ConnInfo *ci){ CC_conninfo_init(ci); dconn_get_attributes(copyAttributes, connect_string, ci);}static voiddconn_get_common_attributes(const SQLCHAR FAR * connect_string, ConnInfo *ci){ dconn_get_attributes(copyCommonAttributes, connect_string, ci);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -