Logo Search packages:      
Sourcecode: psqlodbc version File versions

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 <winsock.h>
#endif

#include <string.h>

#ifdef WIN32
#include <windowsx.h>
#include "resource.h"
#endif
#include "pgapifunc.h"

#ifndef TRUE
#define TRUE      (BOOL)1
#endif
#ifndef FALSE
#define FALSE     (BOOL)0
#endif

#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 UCHAR FAR * connect_string, ConnInfo *ci);
static void dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci);

#ifdef WIN32
BOOL FAR PASCAL 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. */
#endif


RETCODE           SQL_API
PGAPI_DriverConnect(
                              HDBC hdbc,
                              HWND hwnd,
                              UCHAR FAR * szConnStrIn,
                              SWORD cbConnStrIn,
                              UCHAR FAR * szConnStrOut,
                              SWORD cbConnStrOutMax,
                              SWORD FAR * pcbConnStrOut,
                              UWORD fDriverCompletion)
{
      CSTR func = "PGAPI_DriverConnect";
      ConnectionClass *conn = (ConnectionClass *) hdbc;
      ConnInfo   *ci;

#ifdef WIN32
      RETCODE           dialog_result;
#endif
      RETCODE           result;
      char        connStrIn[MAX_CONNECT_STRING];
      char        connStrOut[MAX_CONNECT_STRING];
      int               retval;
      char        salt[5];
      char        password_required = AUTH_REQ_OK;
      int               len = 0;
      SWORD       lenStrout;


      mylog("%s: entering...\n", func);

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

      make_string(szConnStrIn, cbConnStrIn, connStrIn);

#ifdef      FORCE_PASSWORD_DISPLAY
      mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
      qlog("conn=%u, 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=%u, 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);

      /* Fill in any default parameters if they are not there. */
      getDSNdefaults(ci);
      /* initialize pg_version */
      CC_initialize_pg_version(conn);
      salt[0] = '\0';

#ifdef WIN32
dialog:
#endif
      ci->focus_password = password_required;

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

            case SQL_DRIVER_COMPLETE_REQUIRED:

                  /* Fall through */

            case SQL_DRIVER_COMPLETE:

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

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

            if (len >= cbConnStrOutMax)
            {
                  int               clen;

                  for (clen = strlen(szConnStrOut) - 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.");
            }
      }

      if (pcbConnStrOut)
            *pcbConnStrOut = len;

#ifdef      FORCE_PASSWORD_DISPLAY
      mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(szConnStrOut), len, cbConnStrOutMax);
      qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(szConnStrOut));
#else
      if (get_qlog() || get_mylog())
      {
            char  *hide_str = hide_password(szConnStrOut);

            mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str), len, cbConnStrOutMax);
            qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(hide_str));
            if (hide_str)
                  free(hide_str);
      }
#endif /* FORCE_PASSWORD_DISPLAY */


      mylog("PGAPI_DriverConnect: returning %d\n", result);
      return result;
}


#ifdef WIN32
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;
      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);

                  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_DATASOURCE:
                              ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
                              DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
                                                   hdlg, ds_options1Proc, (LPARAM) ci);
                              break;

                        case IDC_DRIVER:
                              ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
                              DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
                                                   hdlg, driver_optionsProc, (LPARAM) ci);
                              break;
                  }
      }

      return FALSE;
}
#endif   /* WIN32 */


void
dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci)
{
      char     *our_connect_string;
      char     *pair,
                     *attribute,
                     *value,
                     *equals;
      char     *strtok_arg;
#ifdef      HAVE_STRTOK_R
      char     *last;
#endif /* HAVE_STRTOK_R */

      CC_conninfo_init(ci);

      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  */
            copyAttributes(ci, attribute, value);

      }

      free(our_connect_string);
}

static void
dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci)
{
      char     *our_connect_string;
      char     *pair,
                     *attribute,
                     *value,
                     *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  */
            copyCommonAttributes(ci, attribute, value);

      }

      free(our_connect_string);
}

Generated by  Doxygen 1.6.0   Back to index