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 (that's 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 : #include "ODBCAttrs.h"
36 : #ifdef HAVE_STRINGS_H
37 : #include <strings.h> /* for strcasecmp */
38 : #else
39 : #include <string.h>
40 : #endif
41 :
42 : int
43 148 : ODBCGetKeyAttr(const SQLCHAR **conn, SQLSMALLINT *nconn, char **key, char **attr)
44 : {
45 148 : const SQLCHAR *p;
46 148 : size_t len;
47 :
48 148 : *key = *attr = NULL;
49 :
50 148 : p = *conn;
51 148 : if (!**conn)
52 : return 0;
53 680 : while (*nconn > 0 && **conn && **conn != '=' && **conn != ';') {
54 568 : (*conn)++;
55 568 : (*nconn)--;
56 : }
57 112 : if (*nconn == 0 || !**conn || **conn == ';')
58 : return 0;
59 111 : len = *conn - p;
60 111 : *key = (char *) malloc(len + 1);
61 111 : if (*key == NULL)
62 : return -1;
63 111 : strcpy_len(*key, (char *) p, len + 1);
64 111 : (*conn)++;
65 111 : (*nconn)--;
66 111 : p = *conn;
67 :
68 111 : if (*nconn > 0 && **conn == '{' && strcasecmp(*key, "DRIVER") == 0) {
69 10 : (*conn)++;
70 10 : (*nconn)--;
71 10 : p++;
72 80 : while (*nconn > 0 && **conn && **conn != '}') {
73 70 : (*conn)++;
74 70 : (*nconn)--;
75 : }
76 10 : len = *conn - p;
77 10 : *attr = (char *) malloc(len + 1);
78 10 : if (*attr == NULL) {
79 0 : free(*key);
80 0 : *key = NULL;
81 0 : return -1;
82 : }
83 10 : strcpy_len(*attr, (char *) p, len + 1);
84 10 : (*conn)++;
85 10 : (*nconn)--;
86 : /* should check that *nconn == 0 || **conn == ';' */
87 : } else {
88 1247 : while (*nconn > 0 && **conn && **conn != ';') {
89 1146 : (*conn)++;
90 1146 : (*nconn)--;
91 : }
92 101 : len = *conn - p;
93 101 : *attr = (char *) malloc(len + 1);
94 101 : if (*attr == NULL) {
95 0 : free(*key);
96 0 : *key = NULL;
97 0 : return -1;
98 : }
99 101 : strcpy_len(*attr, (char *) p, len + 1);
100 : }
101 111 : if (*nconn > 0 && **conn) {
102 79 : (*conn)++;
103 79 : (*nconn)--;
104 : }
105 : return 1;
106 : }
107 :
108 : #ifdef ODBCDEBUG
109 : static char *
110 29 : translateDriverCompletion(SQLUSMALLINT DriverCompletion)
111 : {
112 29 : switch (DriverCompletion) {
113 : case SQL_DRIVER_PROMPT:
114 : return "SQL_DRIVER_PROMPT";
115 0 : case SQL_DRIVER_COMPLETE:
116 0 : return "SQL_DRIVER_COMPLETE";
117 0 : case SQL_DRIVER_COMPLETE_REQUIRED:
118 0 : return "SQL_DRIVER_COMPLETE_REQUIRED";
119 29 : case SQL_DRIVER_NOPROMPT:
120 29 : return "SQL_DRIVER_NOPROMPT";
121 0 : default:
122 0 : return "unknown";
123 : }
124 : }
125 : #endif
126 :
127 : SQLRETURN
128 29 : MNDBDriverConnect(ODBCDbc *dbc,
129 : SQLHWND WindowHandle,
130 : const SQLCHAR *InConnectionString,
131 : SQLSMALLINT StringLength1,
132 : SQLCHAR *OutConnectionString,
133 : SQLSMALLINT BufferLength,
134 : SQLSMALLINT *StringLength2Ptr,
135 : SQLUSMALLINT DriverCompletion,
136 : int tryOnly)
137 : {
138 29 : (void) WindowHandle;
139 :
140 29 : SQLRETURN rc = SQL_SUCCESS;
141 29 : const char *sqlstate = NULL;
142 29 : size_t out_len;
143 29 : const char *scratch_no_alloc;
144 :
145 : // These will be free'd at the end label
146 29 : msettings *settings = NULL;
147 29 : char *scratch_alloc = NULL;
148 29 : char *dsn = NULL;
149 :
150 : /* check connection state, should not be connected */
151 29 : if (dbc->Connected) {
152 0 : sqlstate = "08002";
153 0 : goto failure;
154 : }
155 :
156 29 : fixODBCstring(InConnectionString, StringLength1, SQLSMALLINT,
157 : addDbcError, dbc, return SQL_ERROR);
158 :
159 29 : settings = msettings_clone(dbc->settings);
160 29 : if (!settings)
161 0 : goto failure;
162 :
163 : #ifdef ODBCDEBUG
164 29 : ODBCLOG("\"%.*s\" %s\n", StringLength1,
165 : (char *) InConnectionString,
166 : translateDriverCompletion(DriverCompletion));
167 : #endif
168 :
169 : /* check input arguments */
170 29 : switch (DriverCompletion) {
171 : case SQL_DRIVER_PROMPT:
172 : case SQL_DRIVER_COMPLETE:
173 : case SQL_DRIVER_COMPLETE_REQUIRED:
174 : case SQL_DRIVER_NOPROMPT:
175 29 : break;
176 0 : default:
177 : /* Invalid attribute/option identifier */
178 0 : sqlstate = "HY092";
179 0 : goto failure;
180 : }
181 :
182 29 : rc = takeFromConnString(dbc, settings, InConnectionString, StringLength1, &dsn);
183 29 : if (!SQL_SUCCEEDED(rc))
184 0 : goto end;
185 :
186 29 : if (!msettings_validate(settings, &scratch_alloc)) {
187 0 : addDbcError(dbc, "HY009", scratch_alloc, 0);
188 0 : rc = SQL_ERROR;
189 0 : goto end;
190 : }
191 :
192 : // Build a connect string for the current connection and put it in the out buffer.
193 50 : scratch_alloc = buildConnectionString(dsn ? dsn : "DEFAULT", settings);
194 29 : if (!scratch_alloc)
195 0 : goto failure;
196 29 : out_len = strcpy_len((char*)OutConnectionString, scratch_alloc, BufferLength);
197 29 : if (StringLength2Ptr)
198 29 : *StringLength2Ptr = (SQLSMALLINT)out_len;
199 29 : if (out_len + 1 > (size_t)BufferLength) {
200 3 : addDbcError(dbc, "01004", NULL, 0);
201 3 : rc = SQL_SUCCESS_WITH_INFO;
202 : }
203 :
204 29 : if (tryOnly) {
205 3 : assert(sqlstate == NULL);
206 3 : goto end;
207 : }
208 :
209 26 : scratch_no_alloc = msetting_string(settings, MP_LOGFILE);
210 26 : if (*scratch_no_alloc)
211 0 : setODBCdebug(scratch_no_alloc, false);
212 :
213 26 : rc = MNDBConnectSettings(dbc, dsn, settings);
214 26 : settings = NULL; // do not free now
215 :
216 : // always go to end, MNDBConnectSettings has already logged any failures
217 26 : goto end;
218 :
219 : failure:
220 0 : if (sqlstate == NULL)
221 : sqlstate = "HY001"; // malloc failure
222 : rc = SQL_ERROR;
223 : // fallthrough
224 29 : end:
225 29 : if (sqlstate != NULL)
226 0 : addDbcError(dbc, sqlstate, NULL, 0);
227 29 : msettings_destroy(settings);
228 29 : free(scratch_alloc);
229 29 : free(dsn);
230 29 : return rc;
231 : }
232 :
233 : SQLRETURN SQL_API
234 : SQLDriverConnect(SQLHDBC ConnectionHandle,
235 : SQLHWND WindowHandle,
236 : SQLCHAR *InConnectionString,
237 : SQLSMALLINT StringLength1,
238 : SQLCHAR *OutConnectionString,
239 : SQLSMALLINT BufferLength,
240 : SQLSMALLINT *StringLength2Ptr,
241 : SQLUSMALLINT DriverCompletion)
242 : {
243 13 : ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
244 :
245 : #ifdef ODBCDEBUG
246 13 : ODBCLOG("SQLDriverConnect %p ", ConnectionHandle);
247 : #endif
248 :
249 13 : if (!isValidDbc(dbc))
250 : return SQL_INVALID_HANDLE;
251 :
252 13 : clearDbcErrors(dbc);
253 :
254 13 : return MNDBDriverConnect(dbc,
255 : WindowHandle,
256 : InConnectionString,
257 : StringLength1,
258 : OutConnectionString,
259 : BufferLength,
260 : StringLength2Ptr,
261 : DriverCompletion,
262 : 0);
263 : }
264 :
265 : SQLRETURN SQL_API
266 : SQLDriverConnectA(SQLHDBC ConnectionHandle,
267 : SQLHWND WindowHandle,
268 : SQLCHAR *InConnectionString,
269 : SQLSMALLINT StringLength1,
270 : SQLCHAR *OutConnectionString,
271 : SQLSMALLINT BufferLength,
272 : SQLSMALLINT *StringLength2Ptr,
273 : SQLUSMALLINT DriverCompletion)
274 : {
275 0 : return SQLDriverConnect(ConnectionHandle,
276 : WindowHandle,
277 : InConnectionString,
278 : StringLength1,
279 : OutConnectionString,
280 : BufferLength,
281 : StringLength2Ptr,
282 : DriverCompletion);
283 : }
284 :
285 : SQLRETURN SQL_API
286 : SQLDriverConnectW(SQLHDBC ConnectionHandle,
287 : SQLHWND WindowHandle,
288 : SQLWCHAR *InConnectionString,
289 : SQLSMALLINT StringLength1,
290 : SQLWCHAR *OutConnectionString,
291 : SQLSMALLINT BufferLength,
292 : SQLSMALLINT *StringLength2Ptr,
293 : SQLUSMALLINT DriverCompletion)
294 : {
295 3 : ODBCDbc *dbc = (ODBCDbc *) ConnectionHandle;
296 3 : SQLCHAR *in = NULL, *out;
297 3 : SQLSMALLINT n;
298 3 : SQLRETURN rc;
299 :
300 : #ifdef ODBCDEBUG
301 3 : ODBCLOG("SQLDriverConnectW %p ", ConnectionHandle);
302 : #endif
303 :
304 3 : if (!isValidDbc(dbc))
305 : return SQL_INVALID_HANDLE;
306 :
307 3 : clearDbcErrors(dbc);
308 :
309 3 : fixWcharIn(InConnectionString, StringLength1, SQLCHAR, in,
310 : addDbcError, dbc, return SQL_ERROR);
311 :
312 3 : rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, NULL, 0, &n,
313 : DriverCompletion, 1); // 1 = Try Only
314 3 : if (!SQL_SUCCEEDED(rc))
315 : return rc;
316 3 : clearDbcErrors(dbc);
317 3 : n++; /* account for NUL byte */
318 3 : out = malloc(n);
319 3 : if (out == NULL) {
320 : /* Memory allocation error */
321 0 : addDbcError(dbc, "HY001", NULL, 0);
322 0 : return SQL_ERROR;
323 : }
324 3 : rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, out, n, &n,
325 : DriverCompletion, 0);
326 3 : if (SQL_SUCCEEDED(rc)) {
327 2 : fixWcharOut(rc, out, n, OutConnectionString, BufferLength,
328 : StringLength2Ptr, 1, addDbcError, dbc);
329 : }
330 3 : free(out);
331 3 : if (in)
332 3 : free(in);
333 : return rc;
334 : }
|