
/* 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 <stdio.h>
#include <stdlib.h>

#include "psqlodbc.h"
#include "connection.h"

#include <winsock.h>
#include <sqlext.h>
#include <string.h>
#include <windows.h>
#include <windowsx.h>
#include <odbcinst.h>
#include "resource.h"

#include "dlg_specific.h"

/* prototypes */
BOOL FAR PASCAL dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci);
void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci);

extern HINSTANCE NEAR s_hModule;               /* Saved module handle. */
extern GLOBAL_VALUES globals;


RETCODE SQL_API SQLDriverConnect(
                                 HDBC      hdbc,
                                 HWND      hwnd,
                                 UCHAR FAR *szConnStrIn,
                                 SWORD     cbConnStrIn,
                                 UCHAR FAR *szConnStrOut,
                                 SWORD     cbConnStrOutMax,
                                 SWORD FAR *pcbConnStrOut,
                                 UWORD     fDriverCompletion)
{
char *func = "SQLDriverConnect";
ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci;
RETCODE dialog_result;
char connect_string[MAX_CONNECT_STRING];
int retval;
char password_required = FALSE;

	mylog("**** SQLDriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, szConnStrIn);

	if ( ! conn) {
		CC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	qlog("conn=%u, SQLDriverConnect( in)='%s'\n", conn, szConnStrIn);

	ci = &(conn->connInfo);

	//	Parse the connect string and fill in conninfo for this hdbc.
	dconn_get_connect_attributes(szConnStrIn, 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);

	//	Fill in any default parameters if they are not there.
	getDSNdefaults(ci);

dialog:
	ci->focus_password = password_required;

	switch(fDriverCompletion) {
	case SQL_DRIVER_PROMPT:
		dialog_result = dconn_DoDialog(hwnd, ci);
		if(dialog_result != SQL_SUCCESS) {
			return dialog_result;
		}
		break;

	case SQL_DRIVER_COMPLETE:
	case SQL_DRIVER_COMPLETE_REQUIRED:
	/* Password is not a required parameter. */
		if( ci->username[0] == '\0' ||
			ci->server[0] == '\0' ||
			ci->database[0] == '\0' ||
			ci->port[0] == '\0' ||
			password_required) { 

			dialog_result = dconn_DoDialog(hwnd, ci);
			if(dialog_result != SQL_SUCCESS) {
				return dialog_result;
			}
		}
		break;
	case SQL_DRIVER_NOPROMPT:
		break;
	}

	/*	Password is not a required parameter unless authentication asks for it.
		For now, I think its better to just let the application ask over and over until
		a password is entered (the user can always hit Cancel to get out)
	*/
	if( ci->username[0] == '\0' ||
		ci->server[0] == '\0' ||
		ci->database[0] == '\0' || 
		ci->port[0] == '\0') {
//		(password_required && ci->password[0] == '\0'))

		return SQL_NO_DATA_FOUND;
	}

	if(szConnStrOut) {

		//	return the completed string to the caller.

		makeConnectString(connect_string, ci);

		if(pcbConnStrOut) {
			*pcbConnStrOut = strlen(connect_string);
		}
		strncpy_null(szConnStrOut, connect_string, cbConnStrOutMax);
	}

	mylog("szConnStrOut = '%s'\n", szConnStrOut);
	qlog("conn=%u, SQLDriverConnect(out)='%s'\n", conn, szConnStrOut);

	// do the actual connect
	retval = CC_connect(conn, password_required);
	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 {
			password_required = TRUE;
			goto dialog;
		}
	}
	else if (retval == 0) {
		//	error msg filled in above
		CC_log_error(func, "Error from CC_Connect", conn);
		return SQL_ERROR;
	}

	mylog("SQLDRiverConnect: returning success\n");
	return SQL_SUCCESS;
}


RETCODE dconn_DoDialog(HWND hwnd, ConnInfo *ci)
{
int dialog_result;

mylog("dconn_DoDialog: ci = %u\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;
}


BOOL FAR PASCAL dconn_FDriverConnectProc(
                                         HWND    hdlg,
                                         UINT    wMsg,
                                         WPARAM  wParam,
                                         LPARAM  lParam)
{
ConnInfo *ci;

	switch (wMsg) {
	case WM_INITDIALOG:
		ci = (ConnInfo *) lParam;		

		/*	Change the caption for the setup dialog */
		SetWindowText(hdlg, "PostgreSQL Connection");

		SetWindowText(GetDlgItem(hdlg, IDC_DATASOURCE), "Connection");

		/*	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);

		SetWindowLong(hdlg, DWL_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 *) GetWindowLong(hdlg, DWL_USER);

			GetDlgStuff(hdlg, ci);


		case IDCANCEL:
			EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
			return TRUE;

		case IDC_DRIVER:

			DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
									hdlg, driver_optionsProc, (LPARAM) NULL);


			break;

		case IDC_DATASOURCE:

			ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
			DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DS),
									hdlg, ds_optionsProc, (LPARAM) ci);

			break;
		}
	}

	return FALSE;
}



void dconn_get_connect_attributes(UCHAR FAR *connect_string, ConnInfo *ci)
{
char *our_connect_string;
char *pair, *attribute, *value, *equals;
char *strtok_arg;

	memset(ci, 0, sizeof(ConnInfo));

	our_connect_string = strdup(connect_string);
	strtok_arg = our_connect_string;

	mylog("our_connect_string = '%s'\n", our_connect_string);

	while(1) {
		pair = strtok(strtok_arg, ";");
		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'

		mylog("attribute = '%s', value = '%s'\n", attribute, value);

		if( !attribute || !value)
			continue;          

		//	Copy the appropriate value to the conninfo 
		copyAttributes(ci, attribute, value);

	}


	free(our_connect_string);
}

