LCOV - code coverage report
Current view: top level - clients/odbc/driver - SQLDriverConnect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 109 220 49.5 %
Date: 2024-04-26 00:35:57 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * This code was created by Peter Harvey (mostly during Christmas 98/99).
      15             :  * This code is LGPL. Please ensure that this message remains in future
      16             :  * distributions and uses of this code (thats about all I get out of it).
      17             :  * - Peter Harvey pharvey@codebydesign.com
      18             :  *
      19             :  * This file has been modified for the MonetDB project.  See the file
      20             :  * Copyright in this directory for more information.
      21             :  */
      22             : 
      23             : /**********************************************************************
      24             :  * SQLDriverConnect()
      25             :  * CLI Compliance: ODBC (Microsoft)
      26             :  *
      27             :  * Author: Martin van Dinther, Sjoerd Mullender
      28             :  * Date  : 30 aug 2002
      29             :  *
      30             :  **********************************************************************/
      31             : 
      32             : #include "ODBCGlobal.h"
      33             : #include "ODBCDbc.h"
      34             : #include "ODBCUtil.h"
      35             : #ifdef HAVE_STRINGS_H
      36             : #include <strings.h>              /* for strcasecmp */
      37             : #else
      38             : #include <string.h>
      39             : #endif
      40             : 
      41             : int
      42           4 : ODBCGetKeyAttr(const SQLCHAR **conn, SQLSMALLINT *nconn, char **key, char **attr)
      43             : {
      44           4 :         const SQLCHAR *p;
      45           4 :         size_t len;
      46             : 
      47           4 :         *key = *attr = NULL;
      48             : 
      49           4 :         p = *conn;
      50           4 :         if (!**conn)
      51             :                 return 0;
      52           8 :         while (*nconn > 0 && **conn && **conn != '=' && **conn != ';') {
      53           6 :                 (*conn)++;
      54           6 :                 (*nconn)--;
      55             :         }
      56           2 :         if (*nconn == 0 || !**conn || **conn == ';')
      57             :                 return 0;
      58           2 :         len = *conn - p;
      59           2 :         *key = (char *) malloc(len + 1);
      60           2 :         if (*key == NULL)
      61             :                 return -1;
      62           2 :         strcpy_len(*key, (char *) p, len + 1);
      63           2 :         (*conn)++;
      64           2 :         (*nconn)--;
      65           2 :         p = *conn;
      66             : 
      67           2 :         if (*nconn > 0 && **conn == '{' && strcasecmp(*key, "DRIVER") == 0) {
      68           0 :                 (*conn)++;
      69           0 :                 (*nconn)--;
      70           0 :                 p++;
      71           0 :                 while (*nconn > 0 && **conn && **conn != '}') {
      72           0 :                         (*conn)++;
      73           0 :                         (*nconn)--;
      74             :                 }
      75           0 :                 len = *conn - p;
      76           0 :                 *attr = (char *) malloc(len + 1);
      77           0 :                 if (*attr == NULL) {
      78           0 :                         free(*key);
      79           0 :                         *key = NULL;
      80           0 :                         return -1;
      81             :                 }
      82           0 :                 strcpy_len(*attr, (char *) p, len + 1);
      83           0 :                 (*conn)++;
      84           0 :                 (*nconn)--;
      85             :                 /* should check that *nconn == 0 || **conn == ';' */
      86             :         } else {
      87          26 :                 while (*nconn > 0 && **conn && **conn != ';') {
      88          24 :                         (*conn)++;
      89          24 :                         (*nconn)--;
      90             :                 }
      91           2 :                 len = *conn - p;
      92           2 :                 *attr = (char *) malloc(len + 1);
      93           2 :                 if (*attr == NULL) {
      94           0 :                         free(*key);
      95           0 :                         *key = NULL;
      96           0 :                         return -1;
      97             :                 }
      98           2 :                 strcpy_len(*attr, (char *) p, len + 1);
      99             :         }
     100           2 :         if (*nconn > 0 && **conn) {
     101           0 :                 (*conn)++;
     102           0 :                 (*nconn)--;
     103             :         }
     104             :         return 1;
     105             : }
     106             : 
     107             : SQLRETURN
     108           2 : ODBCConnectionString(SQLRETURN rc,
     109             :                      ODBCDbc *dbc,
     110             :                      SQLCHAR *OutConnectionString,
     111             :                      SQLSMALLINT BufferLength,
     112             :                      SQLSMALLINT *StringLength2Ptr,
     113             :                      const char *dsn,
     114             :                      const char *uid,
     115             :                      const char *pwd,
     116             :                      const char *host,
     117             :                      int port,
     118             :                      const char *database,
     119             :                      int mapToLongVarchar)
     120             : {
     121           2 :         int n;
     122             : #ifdef ODBCDEBUG
     123           2 :         SQLCHAR *buf = OutConnectionString;
     124           2 :         int buflen = BufferLength;
     125             : #endif
     126             : 
     127           2 :         if (OutConnectionString == NULL)
     128             :                 BufferLength = -1;
     129           1 :         if (BufferLength > 0) {
     130           1 :                 n = snprintf((char *) OutConnectionString, BufferLength,
     131             :                              "DSN=%s;", dsn ? dsn : "DEFAULT");
     132             :                 /* some snprintf's return -1 if buffer too small */
     133           1 :                 if (n < 0)
     134           0 :                         n = BufferLength + 1;   /* make sure it becomes < 0 */
     135           1 :                 BufferLength -= n;
     136           1 :                 OutConnectionString += n;
     137             :         } else {
     138             :                 BufferLength = -1;
     139             :         }
     140           2 :         if (uid) {
     141           0 :                 if (BufferLength > 0) {
     142           0 :                         n = snprintf((char *) OutConnectionString,
     143             :                                      BufferLength, "UID=%s;", uid);
     144           0 :                         if (n < 0)
     145           0 :                                 n = BufferLength + 1;
     146           0 :                         BufferLength -= n;
     147           0 :                         OutConnectionString += n;
     148             :                 } else {
     149             :                         BufferLength = -1;
     150             :                 }
     151             :         }
     152           2 :         if (pwd) {
     153           0 :                 if (BufferLength > 0) {
     154           0 :                         n = snprintf((char *) OutConnectionString,
     155             :                                      BufferLength, "PWD=%s;", pwd);
     156           0 :                         if (n < 0)
     157           0 :                                 n = BufferLength + 1;
     158           0 :                         BufferLength -= n;
     159           0 :                         OutConnectionString += n;
     160             :                 } else {
     161             :                         BufferLength = -1;
     162             :                 }
     163             :         }
     164           2 :         if (host) {
     165           0 :                 if (BufferLength > 0) {
     166           0 :                         n = snprintf((char *) OutConnectionString,
     167             :                                      BufferLength, "HOST=%s;", host);
     168           0 :                         if (n < 0)
     169           0 :                                 n = BufferLength + 1;
     170           0 :                         BufferLength -= n;
     171           0 :                         OutConnectionString += n;
     172             :                 } else {
     173             :                         BufferLength = -1;
     174             :                 }
     175             :         }
     176           2 :         if (port) {
     177           0 :                 char portbuf[10];
     178             : 
     179           0 :                 if (BufferLength > 0) {
     180           0 :                         n = snprintf((char *) OutConnectionString,
     181             :                                      BufferLength, "PORT=%d;", port);
     182           0 :                         if (n < 0)
     183           0 :                                 n = BufferLength + 1;
     184           0 :                         BufferLength -= n;
     185           0 :                         OutConnectionString += n;
     186             :                 } else {
     187             :                         BufferLength = -1;
     188             :                 }
     189           0 :                 port = snprintf(portbuf, sizeof(portbuf), "%d", port);
     190             :         }
     191           2 :         if (database) {
     192           0 :                 if (BufferLength > 0) {
     193           0 :                         n = snprintf((char *) OutConnectionString,
     194             :                                      BufferLength, "DATABASE=%s;", database);
     195           0 :                         if (n < 0)
     196           0 :                                 n = BufferLength + 1;
     197           0 :                         BufferLength -= n;
     198           0 :                         OutConnectionString += n;
     199             :                 } else {
     200             :                         BufferLength = -1;
     201             :                 }
     202             :         }
     203           2 :         if (mapToLongVarchar > 0) {
     204           0 :                 if (BufferLength > 0) {
     205           0 :                         n = snprintf((char *) OutConnectionString,
     206             :                                      BufferLength, "mapToLongVarchar=%d;", mapToLongVarchar);
     207           0 :                         if (n < 0)
     208           0 :                                 n = BufferLength + 1;
     209           0 :                         BufferLength -= n;
     210           0 :                         OutConnectionString += n;
     211             :                 } else {
     212             :                         BufferLength = -1;
     213             :                 }
     214             :         }
     215           2 :         n = 0;
     216             : #ifdef ODBCDEBUG
     217             : #ifdef NATIVE_WIN32
     218             :         if (ODBCdebug && _wgetenv(L"ODBCDEBUG") == NULL) {
     219             :                 if (BufferLength > 0) {
     220             :                         n = snprintf((char *) OutConnectionString,
     221             :                                      BufferLength,
     222             :                                      "LOGFILE=%ls;", ODBCdebug);
     223             :                         if (n < 0) {
     224             :                                 n = 0;
     225             :                                 BufferLength = -1;
     226             :                         } else {
     227             :                                 BufferLength -= n;
     228             :                                 OutConnectionString += n;
     229             :                         }
     230             :                 } else {
     231             :                         BufferLength = -1;
     232             :                 }
     233             :         }
     234             : #else
     235           2 :         if (ODBCdebug && getenv("ODBCDEBUG") == NULL) {
     236           2 :                 if (BufferLength > 0) {
     237           1 :                         n = snprintf((char *) OutConnectionString,
     238             :                                      BufferLength,
     239             :                                      "LOGFILE=%s;", ODBCdebug);
     240           1 :                         if (n < 0) {
     241             :                                 n = 0;
     242             :                                 BufferLength = -1;
     243             :                         } else {
     244           1 :                                 BufferLength -= n;
     245           1 :                                 OutConnectionString += n;
     246             :                         }
     247             :                 } else {
     248             :                         BufferLength = -1;
     249             :                 }
     250             :         }
     251             : #endif
     252             : #endif
     253             : 
     254             :         /* calculate how much space was needed */
     255           2 :         if (StringLength2Ptr)
     256           4 :                 *StringLength2Ptr = (SQLSMALLINT)
     257           2 :                         (strlen(dsn ? dsn : "DEFAULT") + 5 +
     258           2 :                          (uid ? strlen(uid) + 5 : 0) +
     259           2 :                          (pwd ? strlen(pwd) + 5 : 0) +
     260           2 :                          (host ? strlen(host) + 6 : 0) +
     261           2 :                          (port ? port + 6 : 0) +
     262           0 :                          (database ? strlen(database) + 10 : 0)
     263           2 :                          + n);
     264             : 
     265             : #ifdef ODBCDEBUG
     266           2 :         ODBCLOG("ConnectionString: \"%.*s\" %d\n", buf ? buflen : 6, buf ? (char *) buf : "(null)", buflen);
     267             : #endif
     268             : 
     269             :         /* if it didn't fit, say so */
     270           2 :         if (BufferLength < 0) {
     271             :                 /* String data, right-truncated */
     272           2 :                 addDbcError(dbc, "01004", NULL, 0);
     273           2 :                 return SQL_SUCCESS_WITH_INFO;
     274             :         }
     275             :         return rc;
     276             : }
     277             : 
     278             : #ifdef ODBCDEBUG
     279             : static char *
     280           0 : translateDriverCompletion(SQLUSMALLINT DriverCompletion)
     281             : {
     282           0 :         switch (DriverCompletion) {
     283             :         case SQL_DRIVER_PROMPT:
     284             :                 return "SQL_DRIVER_PROMPT";
     285           0 :         case SQL_DRIVER_COMPLETE:
     286           0 :                 return "SQL_DRIVER_COMPLETE";
     287           0 :         case SQL_DRIVER_COMPLETE_REQUIRED:
     288           0 :                 return "SQL_DRIVER_COMPLETE_REQUIRED";
     289           0 :         case SQL_DRIVER_NOPROMPT:
     290           0 :                 return "SQL_DRIVER_NOPROMPT";
     291           0 :         default:
     292           0 :                 return "unknown";
     293             :         }
     294             : }
     295             : #endif
     296             : 
     297             : static SQLRETURN
     298           2 : MNDBDriverConnect(ODBCDbc *dbc,
     299             :                   SQLHWND WindowHandle,
     300             :                   const SQLCHAR *InConnectionString,
     301             :                   SQLSMALLINT StringLength1,
     302             :                   SQLCHAR *OutConnectionString,
     303             :                   SQLSMALLINT BufferLength,
     304             :                   SQLSMALLINT *StringLength2Ptr,
     305             :                   SQLUSMALLINT DriverCompletion,
     306             :                   int tryOnly)
     307             : {
     308           2 :         char *key, *attr;
     309           2 :         char *dsn = 0, *uid = 0, *pwd = 0, *host = 0, *database = 0;
     310           2 :         int port = 0, mapToLongVarchar = 0;
     311           2 :         SQLRETURN rc;
     312           2 :         int n;
     313             : 
     314           2 :         (void) WindowHandle;            /* Stefan: unused!? */
     315             : 
     316             :         /* check connection state, should not be connected */
     317           2 :         if (dbc->Connected) {
     318             :                 /* Connection name in use */
     319           0 :                 addDbcError(dbc, "08002", NULL, 0);
     320           0 :                 return SQL_ERROR;
     321             :         }
     322           2 :         assert(!dbc->Connected);
     323             : 
     324           2 :         fixODBCstring(InConnectionString, StringLength1, SQLSMALLINT,
     325             :                       addDbcError, dbc, return SQL_ERROR);
     326             : 
     327             : #ifdef ODBCDEBUG
     328           2 :         ODBCLOG("\"%.*s\" %s\n", StringLength1,
     329             :                 (char *) InConnectionString,
     330             :                 translateDriverCompletion(DriverCompletion));
     331             : #endif
     332             : 
     333             :         /* check input arguments */
     334           2 :         switch (DriverCompletion) {
     335             :         case SQL_DRIVER_PROMPT:
     336             :         case SQL_DRIVER_COMPLETE:
     337             :         case SQL_DRIVER_COMPLETE_REQUIRED:
     338             :         case SQL_DRIVER_NOPROMPT:
     339             :                 break;
     340           0 :         default:
     341             :                 /* Invalid attribute/option identifier */
     342           0 :                 addDbcError(dbc, "HY092", NULL, 0);
     343           0 :                 return SQL_ERROR;
     344             :         }
     345             : 
     346           4 :         while ((n = ODBCGetKeyAttr(&InConnectionString, &StringLength1, &key, &attr)) > 0) {
     347           2 :                 if (strcasecmp(key, "dsn") == 0 && dsn == NULL)
     348           2 :                         dsn = attr;
     349           0 :                 else if (strcasecmp(key, "uid") == 0 && uid == NULL)
     350           0 :                         uid = attr;
     351           0 :                 else if (strcasecmp(key, "pwd") == 0 && pwd == NULL)
     352           0 :                         pwd = attr;
     353           0 :                 else if (strcasecmp(key, "host") == 0 && host == NULL)
     354           0 :                         host = attr;
     355           0 :                 else if (strcasecmp(key, "database") == 0 && database == NULL)
     356           0 :                         database = attr;
     357           0 :                 else if (strcasecmp(key, "port") == 0 && port == 0) {
     358           0 :                         port = atoi(attr);
     359           0 :                         free(attr);
     360           0 :                 } else if (strcasecmp(key, "mapToLongVarchar") == 0 && mapToLongVarchar == 0) {
     361           0 :                         mapToLongVarchar = atoi(attr);
     362           0 :                         free(attr);
     363             : #ifdef ODBCDEBUG
     364             : #ifdef NATIVE_WIN32
     365             :                 } else if (strcasecmp(key, "logfile") == 0 &&
     366             :                            _wgetenv(L"ODBCDEBUG") == NULL) {
     367             :                         if (ODBCdebug)
     368             :                                 free((void *) ODBCdebug); /* discard const */
     369             :                         size_t attrlen = strlen(attr);
     370             :                         SQLWCHAR *wattr = malloc((attrlen + 1) * sizeof(SQLWCHAR));
     371             :                         if (ODBCutf82wchar(attr,
     372             :                                            (SQLINTEGER) attrlen,
     373             :                                            wattr,
     374             :                                            (SQLLEN) ((attrlen + 1) * sizeof(SQLWCHAR)),
     375             :                                            NULL,
     376             :                                            NULL)) {
     377             :                                 free(wattr);
     378             :                                 wattr = NULL;
     379             :                         }
     380             :                         free(attr);
     381             :                         ODBCdebug = wattr;
     382             : #else
     383           0 :                 } else if (strcasecmp(key, "logfile") == 0 &&
     384           0 :                            getenv("ODBCDEBUG") == NULL) {
     385           0 :                         if (ODBCdebug)
     386           0 :                                 free((void *) ODBCdebug); /* discard const */
     387           0 :                         ODBCdebug = attr;
     388             : #endif
     389             : #endif
     390             :                 } else
     391           0 :                         free(attr);
     392           2 :                 free(key);
     393             :         }
     394             : 
     395           2 :         if (n < 0) {
     396             :                 /* Memory allocation error */
     397           0 :                 addDbcError(dbc, "HY001", NULL, 0);
     398           0 :                 rc = SQL_ERROR;
     399           2 :         } else if (dsn && strlen(dsn) > SQL_MAX_DSN_LENGTH) {
     400             :                 /* Data source name too long */
     401           0 :                 addDbcError(dbc, "IM010", NULL, 0);
     402           0 :                 rc = SQL_ERROR;
     403           2 :         } else if (tryOnly) {
     404             :                 rc = SQL_SUCCESS;
     405             :         } else {
     406           1 :                 rc = MNDBConnect(dbc, (SQLCHAR *) dsn, SQL_NTS,
     407             :                                  (SQLCHAR *) uid, SQL_NTS,
     408             :                                  (SQLCHAR *) pwd, SQL_NTS,
     409             :                                  host, port, database,
     410             :                                  mapToLongVarchar);
     411             :         }
     412             : 
     413           1 :         if (SQL_SUCCEEDED(rc)) {
     414           2 :                 rc = ODBCConnectionString(rc, dbc, OutConnectionString,
     415             :                                           BufferLength, StringLength2Ptr,
     416             :                                           dsn, uid, pwd, host, port, database,
     417             :                                           mapToLongVarchar);
     418             :         }
     419             : 
     420           2 :         if (dsn)
     421           2 :                 free(dsn);
     422           2 :         if (uid)
     423           0 :                 free(uid);
     424           2 :         if (pwd)
     425           0 :                 free(pwd);
     426           2 :         if (host)
     427           0 :                 free(host);
     428           2 :         if (database)
     429           0 :                 free(database);
     430             :         return rc;
     431             : }
     432             : 
     433             : SQLRETURN SQL_API
     434             : SQLDriverConnect(SQLHDBC ConnectionHandle,
     435             :                  SQLHWND WindowHandle,
     436             :                  SQLCHAR *InConnectionString,
     437             :                  SQLSMALLINT StringLength1,
     438             :                  SQLCHAR *OutConnectionString,
     439             :                  SQLSMALLINT BufferLength,
     440             :                  SQLSMALLINT *StringLength2Ptr,
     441             :                  SQLUSMALLINT DriverCompletion)
     442             : {
     443           0 :         ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
     444             : 
     445             : #ifdef ODBCDEBUG
     446           0 :         ODBCLOG("SQLDriverConnect %p ", ConnectionHandle);
     447             : #endif
     448             : 
     449           0 :         if (!isValidDbc(dbc))
     450             :                 return SQL_INVALID_HANDLE;
     451             : 
     452           0 :         clearDbcErrors(dbc);
     453             : 
     454           0 :         return MNDBDriverConnect(dbc,
     455             :                                  WindowHandle,
     456             :                                  InConnectionString,
     457             :                                  StringLength1,
     458             :                                  OutConnectionString,
     459             :                                  BufferLength,
     460             :                                  StringLength2Ptr,
     461             :                                  DriverCompletion,
     462             :                                  0);
     463             : }
     464             : 
     465             : SQLRETURN SQL_API
     466             : SQLDriverConnectA(SQLHDBC ConnectionHandle,
     467             :                   SQLHWND WindowHandle,
     468             :                   SQLCHAR *InConnectionString,
     469             :                   SQLSMALLINT StringLength1,
     470             :                   SQLCHAR *OutConnectionString,
     471             :                   SQLSMALLINT BufferLength,
     472             :                   SQLSMALLINT *StringLength2Ptr,
     473             :                   SQLUSMALLINT DriverCompletion)
     474             : {
     475           0 :         return SQLDriverConnect(ConnectionHandle,
     476             :                                 WindowHandle,
     477             :                                 InConnectionString,
     478             :                                 StringLength1,
     479             :                                 OutConnectionString,
     480             :                                 BufferLength,
     481             :                                 StringLength2Ptr,
     482             :                                 DriverCompletion);
     483             : }
     484             : 
     485             : SQLRETURN SQL_API
     486             : SQLDriverConnectW(SQLHDBC ConnectionHandle,
     487             :                   SQLHWND WindowHandle,
     488             :                   SQLWCHAR *InConnectionString,
     489             :                   SQLSMALLINT StringLength1,
     490             :                   SQLWCHAR *OutConnectionString,
     491             :                   SQLSMALLINT BufferLength,
     492             :                   SQLSMALLINT *StringLength2Ptr,
     493             :                   SQLUSMALLINT DriverCompletion)
     494             : {
     495           1 :         ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
     496           1 :         SQLCHAR *in = NULL, *out;
     497           1 :         SQLSMALLINT n;
     498           1 :         SQLRETURN rc;
     499             : 
     500             : #ifdef ODBCDEBUG
     501           1 :         ODBCLOG("SQLDriverConnectW %p ", ConnectionHandle);
     502             : #endif
     503             : 
     504           1 :         if (!isValidDbc(dbc))
     505             :                 return SQL_INVALID_HANDLE;
     506             : 
     507           1 :         clearDbcErrors(dbc);
     508             : 
     509           1 :         fixWcharIn(InConnectionString, StringLength1, SQLCHAR, in,
     510             :                    addDbcError, dbc, return SQL_ERROR);
     511             : 
     512           1 :         rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, NULL, 0, &n,
     513             :                                DriverCompletion, 1);
     514           1 :         if (!SQL_SUCCEEDED(rc))
     515             :                 return rc;
     516           1 :         clearDbcErrors(dbc);
     517           1 :         n++;                    /* account for NUL byte */
     518           1 :         out = malloc(n);
     519           1 :         if (out == NULL) {
     520             :                 /* Memory allocation error */
     521           0 :                 addDbcError(dbc, "HY001", NULL, 0);
     522           0 :                 return SQL_ERROR;
     523             :         }
     524           1 :         rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, out, n, &n,
     525             :                                DriverCompletion, 0);
     526           1 :         if (SQL_SUCCEEDED(rc)) {
     527           1 :                 fixWcharOut(rc, out, n, OutConnectionString, BufferLength,
     528             :                             StringLength2Ptr, 1, addDbcError, dbc);
     529             :         }
     530           1 :         free(out);
     531           1 :         if (in)
     532           1 :                 free(in);
     533             :         return rc;
     534             : }

Generated by: LCOV version 1.14