2 * Description: This module contains only routines related to
3 * implementing SQLDriverConnect.
12 #include "connection.h"
15 #include <sys/types.h>
16 #include <sys/socket.h>
28 #include "pgapifunc.h"
30 #include "wvdbusconn.h"
32 #include "dlg_specific.h"
33 #include "wvssl_necessities.h"
35 #define NULL_IF_NULL(a) (a ? a : "(NULL)")
37 static char *hide_password(const char *str
)
44 if (pwdp
= strstr(outstr
, "PWD="), !pwdp
)
45 pwdp
= strstr(outstr
, "pwd=");
50 for (p
= pwdp
+ 4; *p
&& *p
!= ';'; p
++)
57 void dconn_get_connect_attributes(const SQLCHAR FAR
* connect_string
,
59 static void dconn_get_common_attributes(const SQLCHAR FAR
*
60 connect_string
, ConnInfo
* ci
);
66 BOOL CALLBACK
dconn_FDriverConnectProc(HWND hdlg
, UINT wMsg
,
67 WPARAM wParam
, LPARAM lParam
);
68 RETCODE
dconn_DoDialog(HWND hwnd
, ConnInfo
* ci
);
73 extern HINSTANCE NEAR s_hModule
; /* Saved module handle. */
78 PGAPI_DriverConnect(HDBC hdbc
,
80 const SQLCHAR FAR
* szConnStrIn
,
81 SQLSMALLINT cbConnStrIn
,
82 SQLCHAR FAR
* szConnStrOut
,
83 SQLSMALLINT cbConnStrOutMax
,
84 SQLSMALLINT FAR
* pcbConnStrOut
,
85 SQLUSMALLINT fDriverCompletion
)
87 CSTR func
= "PGAPI_DriverConnect";
88 ConnectionClass
*conn
= (ConnectionClass
*) hdbc
;
92 RETCODE dialog_result
;
94 BOOL paramRequired
, didUI
= FALSE
;
96 char *connStrIn
= NULL
;
97 char connStrOut
[MAX_CONNECT_STRING
];
100 char password_required
= AUTH_REQ_OK
;
102 SQLSMALLINT lenStrout
;
105 mylog("%s: entering...\n", func
);
110 CC_log_error(func
, "", NULL
);
111 return SQL_INVALID_HANDLE
;
114 connStrIn
= make_string(szConnStrIn
, cbConnStrIn
, NULL
, 0);
116 #ifdef FORCE_PASSWORD_DISPLAY
118 ("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n",
119 fDriverCompletion
, connStrIn
);
120 qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn
, connStrIn
, fDriverCompletion
);
122 if (get_qlog() || get_mylog())
124 char *hide_str
= hide_password(connStrIn
);
127 ("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n",
128 fDriverCompletion
, NULL_IF_NULL(hide_str
));
129 qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn
, NULL_IF_NULL(hide_str
), fDriverCompletion
);
133 #endif /* FORCE_PASSWORD_DISPLAY */
135 ci
= &(conn
->connInfo
);
137 /* Parse the connect string and fill in conninfo for this hdbc. */
138 dconn_get_connect_attributes((const UCHAR
*)connStrIn
, ci
);
140 bool dbus_provided
= ci
->dbus_moniker
!= NULL
&& ci
->dbus_moniker
[0] != '\0';
143 * If the ConnInfo in the hdbc is missing anything, this function will
144 * fill them in from the registry (assuming of course there is a DSN
145 * given -- if not, it does nothing!)
147 getDSNinfo(ci
, CONN_DONT_OVERWRITE
);
148 dconn_get_common_attributes((const UCHAR
*)connStrIn
, ci
);
149 logs_on_off(1, TRUE
, TRUE
);
156 /* Fill in any default parameters if they are not there. */
158 CC_initialize_pg_version(conn
);
159 memset(salt
, 0, sizeof(salt
));
161 ci
->focus_password
= password_required
;
163 inolog("DriverCompletion=%d\n", fDriverCompletion
);
164 switch (fDriverCompletion
)
167 case SQL_DRIVER_PROMPT
:
168 dialog_result
= dconn_DoDialog(hwnd
, ci
);
170 if (dialog_result
!= SQL_SUCCESS
)
171 return dialog_result
;
174 case SQL_DRIVER_COMPLETE_REQUIRED
:
178 case SQL_DRIVER_COMPLETE
:
180 paramRequired
= password_required
;
181 /* Password is not a required parameter. */
182 if (ci
->database
[0] == '\0')
183 paramRequired
= TRUE
;
184 else if (!dbus_provided
&& ci
->port
[0] == '\0')
185 paramRequired
= TRUE
;
187 else if (!dbus_provided
&& ci
->server
[0] == '\0')
188 paramRequired
= TRUE
;
192 dialog_result
= dconn_DoDialog(hwnd
, ci
);
194 if (dialog_result
!= SQL_SUCCESS
)
195 return dialog_result
;
199 case SQL_DRIVER_PROMPT
:
200 case SQL_DRIVER_COMPLETE
:
201 case SQL_DRIVER_COMPLETE_REQUIRED
:
203 case SQL_DRIVER_NOPROMPT
:
208 * Password is not a required parameter unless authentication asks for
209 * it. For now, I think it's better to just let the application ask
210 * over and over until a password is entered (the user can always hit
213 paramRequired
= FALSE
;
214 WvString missingoptions
= "Connection string lacks options: ";
215 if (ci
->database
[0] == '\0')
217 paramRequired
= TRUE
;
218 missingoptions
.append("'database' ");
220 else if (!dbus_provided
&& ci
->port
[0] == '\0')
222 paramRequired
= TRUE
;
223 missingoptions
.append("'port' ");
225 else if (!dbus_provided
&& ci
->server
[0] == '\0')
227 paramRequired
= TRUE
;
228 missingoptions
.append("'server' ");
232 missingoptions
.append("'dbus connection' ");
237 return SQL_NO_DATA_FOUND
;
238 CC_set_error(conn
, CONN_OPENDB_ERROR
,
239 missingoptions
, func
);
245 // If we weren't provided with a pre-made DBus moniker, use the
246 // provided server and port. If we weren't provided with those
247 // either, we'll have already returned an error above.
248 WvString
moniker("dbus:tcp:host=%s,port=%s", ci
->server
, ci
->port
);
249 mylog("Moniker=%s\n", moniker
.cstr());
250 if (moniker
.len() < sizeof(ci
->dbus_moniker
))
251 strncpy(ci
->dbus_moniker
, moniker
.cstr(), sizeof(ci
->dbus_moniker
));
254 CC_set_error(conn
, CONN_OPENDB_ERROR
,
255 "The DBus connection moniker was too long.", func
);
260 mylog("PGAPI_DriverConnect making DBus connection to %s\n",
262 mylog("dbus:session is '%s'\n", getenv("DBUS_SESSION_BUS_ADDRESS"));
263 conn
->dbus
= new WvDBusConn(ci
->dbus_moniker
);
265 WvDBusMsg reply
= conn
->dbus
->send_and_wait
266 (WvDBusMsg("vx.versaplexd", "/db", "vx.db", "Test"),
269 if (!conn
->dbus
->isok())
271 CC_set_error(conn
, CONN_OPENDB_ERROR
, WvString(
272 "Could not open DBus connection to %s: %s (%s).",
274 conn
->dbus
->errstr(), conn
->dbus
->geterr()).cstr(),
281 WvDBusMsg::Iter
i(reply
);
282 WvString errstr
= i
.getnext();
283 CC_set_error(conn
, CONN_OPENDB_ERROR
, WvString(
284 "DBus connected, but test failed: %s. Is versaplexd running?",
291 * Create the Output Connection String
293 result
= SQL_SUCCESS
;
295 lenStrout
= cbConnStrOutMax
;
296 if (conn
->ms_jet
&& lenStrout
> 255)
298 makeConnectString(connStrOut
, ci
, lenStrout
);
299 len
= strlen(connStrOut
);
304 * Return the completed string to the caller. The correct method
305 * is to only construct the connect string if a dialog was put up,
306 * otherwise, it should just copy the connection input string to
307 * the output. However, it seems ok to just always construct an
308 * output string. There are possible bad side effects on working
309 * applications (Access) by implementing the correct behavior,
312 /*strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax); */
313 strncpy((char *)szConnStrOut
, connStrOut
, cbConnStrOutMax
);
315 if (len
>= cbConnStrOutMax
)
319 for (clen
= cbConnStrOutMax
- 1;
320 clen
>= 0 && szConnStrOut
[clen
] != ';'; clen
--)
321 szConnStrOut
[clen
] = '\0';
322 result
= SQL_SUCCESS_WITH_INFO
;
323 CC_set_error(conn
, CONN_TRUNCATED
,
324 "The buffer was too small for the ConnStrOut.",
330 *pcbConnStrOut
= (SQLSMALLINT
) len
;
332 #ifdef FORCE_PASSWORD_DISPLAY
333 if (cbConnStrOutMax
> 0)
335 mylog("szConnStrOut = '%s' len=%d,%d\n",
336 NULL_IF_NULL(szConnStrOut
), len
, cbConnStrOutMax
);
337 qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn
,
338 NULL_IF_NULL(szConnStrOut
));
341 if (get_qlog() || get_mylog())
343 char *hide_str
= NULL
;
345 if (cbConnStrOutMax
> 0)
346 hide_str
= hide_password((const char *)szConnStrOut
);
347 mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str
),
348 len
, cbConnStrOutMax
);
349 qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn
,
350 NULL_IF_NULL(hide_str
));
354 #endif /* FORCE_PASSWORD_DISPLAY */
358 mylog("PGAPI_DriverConnect: returning %d\n", result
);
364 RETCODE
dconn_DoDialog(HWND hwnd
, ConnInfo
* ci
)
366 LRESULT dialog_result
;
368 mylog("dconn_DoDialog: ci = %p\n", ci
);
373 DialogBoxParam(s_hModule
, MAKEINTRESOURCE(DLG_CONFIG
), hwnd
,
374 dconn_FDriverConnectProc
, (LPARAM
) ci
);
375 if (!dialog_result
|| (dialog_result
== -1))
376 return SQL_NO_DATA_FOUND
;
385 BOOL CALLBACK
dconn_FDriverConnectProc(HWND hdlg
, UINT wMsg
,
386 WPARAM wParam
, LPARAM lParam
)
393 ci
= (ConnInfo
*) lParam
;
395 /* Change the caption for the setup dialog */
396 SetWindowText(hdlg
, "Versaplex Connection");
398 /* Hide the DSN and description fields */
399 ShowWindow(GetDlgItem(hdlg
, IDC_DSNAMETEXT
), SW_HIDE
);
400 ShowWindow(GetDlgItem(hdlg
, IDC_DSNAME
), SW_HIDE
);
401 ShowWindow(GetDlgItem(hdlg
, IDC_TEST
), SW_HIDE
);
402 if ('\0' != ci
->server
[0])
403 EnableWindow(GetDlgItem(hdlg
, IDC_SERVER
), FALSE
);
404 if ('\0' != ci
->port
[0])
405 EnableWindow(GetDlgItem(hdlg
, IDC_PORT
), FALSE
);
407 SetWindowLongPtr(hdlg
, DWLP_USER
, lParam
); /* Save the ConnInfo for
409 SetDlgStuff(hdlg
, ci
);
411 if (ci
->database
[0] == '\0')
412 ; /* default focus */
413 else if (ci
->server
[0] == '\0')
414 SetFocus(GetDlgItem(hdlg
, IDC_SERVER
));
415 else if (ci
->port
[0] == '\0')
416 SetFocus(GetDlgItem(hdlg
, IDC_PORT
));
417 else if (ci
->username
[0] == '\0')
418 SetFocus(GetDlgItem(hdlg
, IDC_USER
));
419 else if (ci
->focus_password
)
420 SetFocus(GetDlgItem(hdlg
, IDC_PASSWORD
));
424 switch (GET_WM_COMMAND_ID(wParam
, lParam
))
427 ci
= (ConnInfo
*) GetWindowLongPtr(hdlg
, DWLP_USER
);
429 GetDlgStuff(hdlg
, ci
);
432 EndDialog(hdlg
, GET_WM_COMMAND_ID(wParam
, lParam
) == IDOK
);
442 typedef BOOL (*copyfunc
) (ConnInfo
*, const char *attribute
,
444 static void dconn_get_attributes(copyfunc func
,
445 const SQLCHAR FAR
* connect_string
,
448 char *our_connect_string
;
449 const char *pair
, *attribute
, *value
;
454 #endif /* HAVE_STRTOK_R */
456 our_connect_string
= strdup((const char *)connect_string
);
457 strtok_arg
= our_connect_string
;
459 #ifdef FORCE_PASSWORD_DISPLAY
460 mylog("our_connect_string = '%s'\n", our_connect_string
);
464 char *hide_str
= hide_password(our_connect_string
);
466 mylog("our_connect_string = '%s'\n", hide_str
);
469 #endif /* FORCE_PASSWORD_DISPLAY */
474 pair
= strtok_r(strtok_arg
, ";", &last
);
476 pair
= strtok(strtok_arg
, ";");
477 #endif /* HAVE_STRTOK_R */
483 equals
= strchr(pair
, '=');
488 attribute
= pair
; /* ex. DSN */
489 value
= equals
+ 1; /* ex. 'CEO co1' */
491 #ifndef FORCE_PASSWORD_DISPLAY
492 if (stricmp(attribute
, INI_PASSWORD
) == 0 ||
493 stricmp(attribute
, "pwd") == 0)
494 mylog("attribute = '%s', value = 'xxxxx'\n", attribute
);
496 #endif /* FORCE_PASSWORD_DISPLAY */
497 mylog("attribute = '%s', value = '%s'\n", attribute
, value
);
499 if (!attribute
|| !value
)
502 /* Copy the appropriate value to the conninfo */
503 (*func
) (ci
, attribute
, value
);
507 free(our_connect_string
);
510 void dconn_get_connect_attributes(const SQLCHAR FAR
* connect_string
,
514 CC_conninfo_init(ci
);
515 dconn_get_attributes(copyAttributes
, connect_string
, ci
);
518 static void dconn_get_common_attributes(const SQLCHAR FAR
* connect_string
,
521 dconn_get_attributes(copyCommonAttributes
, connect_string
, ci
);