1913 lines
55 KiB
C
1913 lines
55 KiB
C
/*-------
|
|
* Module: dlg_specific.c
|
|
*
|
|
* Description: This module contains any specific code for handling
|
|
* dialog boxes such as driver/datasource options. Both the
|
|
* ConfigDSN() and the SQLDriverConnect() functions use
|
|
* functions in this module. If you were to add a new option
|
|
* to any dialog box, you would most likely only have to change
|
|
* things in here rather than in 2 separate places as before.
|
|
*
|
|
* Classes: none
|
|
*
|
|
* API functions: none
|
|
*
|
|
* Comments: See "readme.txt" for copyright and license information.
|
|
*-------
|
|
*/
|
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
|
|
|
#include <ctype.h>
|
|
#include "dlg_specific.h"
|
|
#include "misc.h"
|
|
|
|
#include "pgapifunc.h"
|
|
|
|
#define NULL_IF_NULL(a) ((a) ? ((const char *)(a)) : "(null)")
|
|
CSTR ENTRY_TEST = " @@@ ";
|
|
|
|
static void encode(const pgNAME, char *out, int outlen);
|
|
static pgNAME decode(const char *in);
|
|
static pgNAME decode_or_remove_braces(const char *in);
|
|
|
|
#define OVR_EXTRA_BITS (BIT_FORCEABBREVCONNSTR | BIT_FAKE_MSS | BIT_BDE_ENVIRONMENT | BIT_CVT_NULL_DATE | BIT_ACCESSIBLE_ONLY | BIT_IGNORE_ROUND_TRIP_TIME | BIT_DISABLE_KEEPALIVE)
|
|
UInt4 getExtraOptions(const ConnInfo *ci)
|
|
{
|
|
UInt4 flag = ci->extra_opts & (~OVR_EXTRA_BITS);
|
|
|
|
if (ci->force_abbrev_connstr > 0)
|
|
flag |= BIT_FORCEABBREVCONNSTR;
|
|
else if (ci->force_abbrev_connstr == 0)
|
|
flag &= (~BIT_FORCEABBREVCONNSTR);
|
|
if (ci->fake_mss > 0)
|
|
flag |= BIT_FAKE_MSS;
|
|
else if (ci->fake_mss == 0)
|
|
flag &= (~BIT_FAKE_MSS);
|
|
if (ci->bde_environment > 0)
|
|
flag |= BIT_BDE_ENVIRONMENT;
|
|
else if (ci->bde_environment == 0)
|
|
flag &= (~BIT_BDE_ENVIRONMENT);
|
|
if (ci->cvt_null_date_string > 0)
|
|
flag |= BIT_CVT_NULL_DATE;
|
|
else if (ci->cvt_null_date_string == 0)
|
|
flag &= (~BIT_CVT_NULL_DATE);
|
|
if (ci->accessible_only > 0)
|
|
flag |= BIT_ACCESSIBLE_ONLY;
|
|
else if (ci->accessible_only == 0)
|
|
flag &= (~BIT_ACCESSIBLE_ONLY);
|
|
if (ci->ignore_round_trip_time > 0)
|
|
flag |= BIT_IGNORE_ROUND_TRIP_TIME;
|
|
else if (ci->ignore_round_trip_time == 0)
|
|
flag &= (~BIT_IGNORE_ROUND_TRIP_TIME);
|
|
if (ci->disable_keepalive > 0)
|
|
flag |= BIT_DISABLE_KEEPALIVE;
|
|
else if (ci->disable_keepalive == 0)
|
|
flag &= (~BIT_DISABLE_KEEPALIVE);
|
|
|
|
return flag;
|
|
}
|
|
|
|
CSTR hex_format = "%x";
|
|
CSTR dec_format = "%u";
|
|
CSTR octal_format = "%o";
|
|
static UInt4 replaceExtraOptions(ConnInfo *ci, UInt4 flag, BOOL overwrite)
|
|
{
|
|
if (overwrite)
|
|
ci->extra_opts = flag;
|
|
else
|
|
ci->extra_opts |= (flag & ~(OVR_EXTRA_BITS));
|
|
if (overwrite || ci->force_abbrev_connstr < 0)
|
|
ci->force_abbrev_connstr = (0 != (flag & BIT_FORCEABBREVCONNSTR));
|
|
if (overwrite || ci->fake_mss < 0)
|
|
ci->fake_mss = (0 != (flag & BIT_FAKE_MSS));
|
|
if (overwrite || ci->bde_environment < 0)
|
|
ci->bde_environment = (0 != (flag & BIT_BDE_ENVIRONMENT));
|
|
if (overwrite || ci->cvt_null_date_string < 0)
|
|
ci->cvt_null_date_string = (0 != (flag & BIT_CVT_NULL_DATE));
|
|
if (overwrite || ci->accessible_only < 0)
|
|
ci->accessible_only = (0 != (flag & BIT_ACCESSIBLE_ONLY));
|
|
if (overwrite || ci->ignore_round_trip_time < 0)
|
|
ci->ignore_round_trip_time = (0 != (flag & BIT_IGNORE_ROUND_TRIP_TIME));
|
|
if (overwrite || ci->disable_keepalive < 0)
|
|
ci->disable_keepalive = (0 != (flag & BIT_DISABLE_KEEPALIVE));
|
|
|
|
return (ci->extra_opts = getExtraOptions(ci));
|
|
}
|
|
BOOL setExtraOptions(ConnInfo *ci, const char *optstr, const char *format)
|
|
{
|
|
UInt4 flag = 0;
|
|
|
|
if (!format)
|
|
{
|
|
if ('0' == *optstr)
|
|
{
|
|
switch (optstr[1])
|
|
{
|
|
case '\0':
|
|
format = dec_format;
|
|
break;
|
|
case 'x':
|
|
case 'X':
|
|
optstr += 2;
|
|
format = hex_format;
|
|
break;
|
|
default:
|
|
format = octal_format;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
format = dec_format;
|
|
}
|
|
|
|
if (sscanf(optstr, format, &flag) < 1)
|
|
return FALSE;
|
|
replaceExtraOptions(ci, flag, TRUE);
|
|
return TRUE;
|
|
}
|
|
UInt4 add_removeExtraOptions(ConnInfo *ci, UInt4 aflag, UInt4 dflag)
|
|
{
|
|
ci->extra_opts |= aflag;
|
|
ci->extra_opts &= (~dflag);
|
|
if (0 != (aflag & BIT_FORCEABBREVCONNSTR))
|
|
ci->force_abbrev_connstr = TRUE;
|
|
if (0 != (aflag & BIT_FAKE_MSS))
|
|
ci->fake_mss = TRUE;
|
|
if (0 != (aflag & BIT_BDE_ENVIRONMENT))
|
|
ci->bde_environment = TRUE;
|
|
if (0 != (aflag & BIT_CVT_NULL_DATE))
|
|
ci->cvt_null_date_string = TRUE;
|
|
if (0 != (aflag & BIT_ACCESSIBLE_ONLY))
|
|
ci->accessible_only = TRUE;
|
|
if (0 != (aflag & BIT_IGNORE_ROUND_TRIP_TIME))
|
|
ci->ignore_round_trip_time = TRUE;
|
|
if (0 != (aflag & BIT_DISABLE_KEEPALIVE))
|
|
ci->disable_keepalive = TRUE;
|
|
if (0 != (dflag & BIT_FORCEABBREVCONNSTR))
|
|
ci->force_abbrev_connstr = FALSE;
|
|
if (0 != (dflag & BIT_FAKE_MSS))
|
|
ci->fake_mss =FALSE;
|
|
if (0 != (dflag & BIT_CVT_NULL_DATE))
|
|
ci->cvt_null_date_string = FALSE;
|
|
if (0 != (dflag & BIT_ACCESSIBLE_ONLY))
|
|
ci->accessible_only = FALSE;
|
|
if (0 != (dflag & BIT_IGNORE_ROUND_TRIP_TIME))
|
|
ci->ignore_round_trip_time = FALSE;
|
|
if (0 != (dflag & BIT_DISABLE_KEEPALIVE))
|
|
ci->disable_keepalive = FALSE;
|
|
|
|
return (ci->extra_opts = getExtraOptions(ci));
|
|
}
|
|
|
|
static const char *
|
|
abbrev_sslmode(const char *sslmode, char *abbrevmode, size_t abbrevsize)
|
|
{
|
|
switch (sslmode[0])
|
|
{
|
|
case SSLLBYTE_DISABLE:
|
|
case SSLLBYTE_ALLOW:
|
|
case SSLLBYTE_PREFER:
|
|
case SSLLBYTE_REQUIRE:
|
|
abbrevmode[0] = sslmode[0];
|
|
abbrevmode[1] = '\0';
|
|
break;
|
|
case SSLLBYTE_VERIFY:
|
|
abbrevmode[0] = sslmode[0];
|
|
abbrevmode[2] = '\0';
|
|
switch (sslmode[1])
|
|
{
|
|
case 'f':
|
|
case 'c':
|
|
abbrevmode[1] = sslmode[1];
|
|
break;
|
|
default:
|
|
if (strnicmp(sslmode, "verify_", 7) == 0)
|
|
abbrevmode[1] = sslmode[7];
|
|
else
|
|
strncpy_null(abbrevmode, sslmode, abbrevsize);
|
|
}
|
|
break;
|
|
}
|
|
return abbrevmode;
|
|
}
|
|
|
|
static char *
|
|
makeKeepaliveConnectString(char *target, int buflen, const ConnInfo *ci, BOOL abbrev)
|
|
{
|
|
char *buf = target;
|
|
*buf = '\0';
|
|
|
|
if (ci->disable_keepalive)
|
|
return target;
|
|
|
|
if (ci->keepalive_idle >= 0)
|
|
{
|
|
if (abbrev)
|
|
snprintf(buf, buflen, ABBR_KEEPALIVETIME "=%u;", ci->keepalive_idle);
|
|
else
|
|
snprintf(buf, buflen, INI_KEEPALIVETIME "=%u;", ci->keepalive_idle);
|
|
}
|
|
if (ci->keepalive_interval >= 0)
|
|
{
|
|
if (abbrev)
|
|
snprintfcat(buf, buflen, ABBR_KEEPALIVEINTERVAL "=%u;", ci->keepalive_interval);
|
|
else
|
|
snprintfcat(buf, buflen, INI_KEEPALIVEINTERVAL "=%u;", ci->keepalive_interval);
|
|
}
|
|
return target;
|
|
}
|
|
|
|
#define OPENING_BRACKET '{'
|
|
#define CLOSING_BRACKET '}'
|
|
static const char *
|
|
makeBracketConnectString(char **target, pgNAME item, const char *optname)
|
|
{
|
|
const char *istr, *iptr;
|
|
char *buf, *optr;
|
|
int len;
|
|
|
|
istr = SAFE_NAME(item);
|
|
if (!istr[0])
|
|
return NULL_STRING;
|
|
|
|
for (iptr = istr, len = 0; *iptr; iptr++)
|
|
{
|
|
if (CLOSING_BRACKET == *iptr)
|
|
len++;
|
|
len++;
|
|
}
|
|
len += 30;
|
|
if (buf = (char *) malloc(len), buf == NULL)
|
|
return NULL_STRING;
|
|
snprintf(buf, len, "%s=%c", optname, OPENING_BRACKET);
|
|
optr = strchr(buf, '\0');
|
|
for (iptr = istr; *iptr; iptr++)
|
|
{
|
|
if (CLOSING_BRACKET == *iptr)
|
|
*(optr++) = *iptr;
|
|
*(optr++) = *iptr;
|
|
}
|
|
*(optr++) = CLOSING_BRACKET;
|
|
*(optr++) = ';';
|
|
*optr = '\0';
|
|
*target = buf;
|
|
|
|
return buf;
|
|
}
|
|
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
char *
|
|
makeXaOptConnectString(char *target, int buflen, const ConnInfo *ci, BOOL abbrev)
|
|
{
|
|
char *buf = target;
|
|
*buf = '\0';
|
|
|
|
if (ci->xa_opt < 0)
|
|
return target;
|
|
|
|
if (abbrev)
|
|
{
|
|
if (DEFAULT_XAOPT != ci->xa_opt)
|
|
snprintf(buf, buflen, ABBR_XAOPT "=%u;", ci->xa_opt);
|
|
}
|
|
else
|
|
snprintf(buf, buflen, INI_XAOPT "=%u;", ci->xa_opt);
|
|
return target;
|
|
}
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
|
|
void
|
|
makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
|
|
{
|
|
char got_dsn = (ci->dsn[0] != '\0');
|
|
char encoded_item[LARGE_REGISTRY_LEN];
|
|
char *connsetStr = NULL;
|
|
char *pqoptStr = NULL;
|
|
char keepaliveStr[64];
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
char xaOptStr[16];
|
|
#endif
|
|
ssize_t hlen, nlen, olen;
|
|
/*BOOL abbrev = (len <= 400);*/
|
|
BOOL abbrev = (len < 1024) || 0 < ci->force_abbrev_connstr;
|
|
UInt4 flag;
|
|
|
|
MYLOG(DETAIL_LOG_LEVEL, "force_abbrev=%d abbrev=%d\n", ci->force_abbrev_connstr, abbrev);
|
|
encode(ci->password, encoded_item, sizeof(encoded_item));
|
|
/* fundamental info */
|
|
nlen = MAX_CONNECT_STRING;
|
|
olen = snprintf(connect_string, nlen, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
|
|
got_dsn ? "DSN" : "DRIVER",
|
|
got_dsn ? ci->dsn : ci->drivername,
|
|
ci->database,
|
|
ci->server,
|
|
ci->port,
|
|
ci->username,
|
|
encoded_item);
|
|
if (olen < 0 || olen >= nlen)
|
|
{
|
|
connect_string[0] = '\0';
|
|
return;
|
|
}
|
|
|
|
/* extra info */
|
|
hlen = strlen(connect_string);
|
|
nlen = MAX_CONNECT_STRING - hlen;
|
|
MYLOG(DETAIL_LOG_LEVEL, "hlen=" FORMAT_SSIZE_T "\n", hlen);
|
|
if (!abbrev)
|
|
{
|
|
char protocol_and[16];
|
|
|
|
if (ci->rollback_on_error >= 0)
|
|
SPRINTF_FIXED(protocol_and, "7.4-%d", ci->rollback_on_error);
|
|
else
|
|
STRCPY_FIXED(protocol_and, "7.4");
|
|
olen = snprintf(&connect_string[hlen], nlen, ";"
|
|
INI_SSLMODE "=%s;"
|
|
INI_READONLY "=%s;"
|
|
INI_PROTOCOL "=%s;"
|
|
INI_FAKEOIDINDEX "=%s;"
|
|
INI_SHOWOIDCOLUMN "=%s;"
|
|
INI_ROWVERSIONING "=%s;"
|
|
INI_SHOWSYSTEMTABLES "=%s;"
|
|
"%s" /* INI_CONNSETTINGS */
|
|
INI_FETCH "=%d;"
|
|
INI_UNKNOWNSIZES "=%d;"
|
|
INI_MAXVARCHARSIZE "=%d;"
|
|
INI_MAXLONGVARCHARSIZE "=%d;"
|
|
INI_DEBUG "=%d;"
|
|
INI_COMMLOG "=%d;"
|
|
INI_USEDECLAREFETCH "=%d;"
|
|
INI_FOREXTENSIONCONNECTOR "=%d;"
|
|
INI_TEXTASLONGVARCHAR "=%d;"
|
|
INI_UNKNOWNSASLONGVARCHAR "=%d;"
|
|
INI_BOOLSASCHAR "=%d;"
|
|
INI_PARSE "=%d;"
|
|
INI_EXTRASYSTABLEPREFIXES "=%s;"
|
|
INI_LFCONVERSION "=%d;"
|
|
INI_UPDATABLECURSORS "=%d;"
|
|
INI_TRUEISMINUS1 "=%d;"
|
|
INI_INT8AS "=%d;"
|
|
INI_BYTEAASLONGVARBINARY "=%d;"
|
|
INI_USESERVERSIDEPREPARE "=%d;"
|
|
INI_CONNECTIONEXTRAINFO "=%d;"
|
|
INI_USEBATCHPROTOCOL "=%d;"
|
|
INI_LOWERCASEIDENTIFIER "=%d;"
|
|
"%s" /* INI_PQOPT */
|
|
"%s" /* INIKEEPALIVE TIME/INTERVAL */
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
INI_XAOPT "=%d" /* XAOPT */
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
,ci->sslmode
|
|
,ci->onlyread
|
|
,protocol_and
|
|
,ci->fake_oid_index
|
|
,ci->show_oid_column
|
|
,ci->row_versioning
|
|
,ci->show_system_tables
|
|
,makeBracketConnectString(&connsetStr, ci->conn_settings, INI_CONNSETTINGS)
|
|
,ci->drivers.fetch_max
|
|
,ci->drivers.unknown_sizes
|
|
,ci->drivers.max_varchar_size
|
|
,ci->drivers.max_longvarchar_size
|
|
,ci->drivers.debug
|
|
,ci->drivers.commlog
|
|
,ci->drivers.use_declarefetch
|
|
,ci->drivers.for_extension_connector
|
|
,ci->drivers.text_as_longvarchar
|
|
,ci->drivers.unknowns_as_longvarchar
|
|
,ci->drivers.bools_as_char
|
|
,ci->drivers.parse
|
|
,ci->drivers.extra_systable_prefixes
|
|
,ci->lf_conversion
|
|
,ci->allow_keyset
|
|
,ci->true_is_minus1
|
|
,ci->int8_as
|
|
,ci->bytea_as_longvarbinary
|
|
,ci->use_server_side_prepare
|
|
,ci->connection_extra_info
|
|
,ci->use_batch_protocol
|
|
,ci->lower_case_identifier
|
|
,makeBracketConnectString(&pqoptStr, ci->pqopt, INI_PQOPT)
|
|
,makeKeepaliveConnectString(keepaliveStr, sizeof(keepaliveStr), ci, FALSE)
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
,ci->xa_opt
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
);
|
|
}
|
|
/* Abbreviation is needed ? */
|
|
if (abbrev || olen >= nlen || olen < 0)
|
|
{
|
|
flag = 0;
|
|
if (ci->allow_keyset)
|
|
flag |= BIT_UPDATABLECURSORS;
|
|
if (ci->lf_conversion)
|
|
flag |= BIT_LFCONVERSION;
|
|
if (ci->drivers.unique_index)
|
|
flag |= BIT_UNIQUEINDEX;
|
|
switch (ci->drivers.unknown_sizes)
|
|
{
|
|
case UNKNOWNS_AS_DONTKNOW:
|
|
flag |= BIT_UNKNOWN_DONTKNOW;
|
|
break;
|
|
case UNKNOWNS_AS_MAX:
|
|
flag |= BIT_UNKNOWN_ASMAX;
|
|
break;
|
|
}
|
|
if (ci->drivers.commlog)
|
|
flag |= BIT_COMMLOG;
|
|
if (ci->drivers.debug)
|
|
flag |= BIT_DEBUG;
|
|
if (ci->drivers.parse)
|
|
flag |= BIT_PARSE;
|
|
if (ci->drivers.use_declarefetch)
|
|
flag |= BIT_USEDECLAREFETCH;
|
|
if (ci->onlyread[0] == '1')
|
|
flag |= BIT_READONLY;
|
|
if (ci->drivers.text_as_longvarchar)
|
|
flag |= BIT_TEXTASLONGVARCHAR;
|
|
if (ci->drivers.unknowns_as_longvarchar)
|
|
flag |= BIT_UNKNOWNSASLONGVARCHAR;
|
|
if (ci->drivers.bools_as_char)
|
|
flag |= BIT_BOOLSASCHAR;
|
|
if (ci->row_versioning[0] == '1')
|
|
flag |= BIT_ROWVERSIONING;
|
|
if (ci->show_system_tables[0] == '1')
|
|
flag |= BIT_SHOWSYSTEMTABLES;
|
|
if (ci->show_oid_column[0] == '1')
|
|
flag |= BIT_SHOWOIDCOLUMN;
|
|
if (ci->fake_oid_index[0] == '1')
|
|
flag |= BIT_FAKEOIDINDEX;
|
|
if (ci->true_is_minus1)
|
|
flag |= BIT_TRUEISMINUS1;
|
|
if (ci->bytea_as_longvarbinary)
|
|
flag |= BIT_BYTEAASLONGVARBINARY;
|
|
if (ci->use_server_side_prepare)
|
|
flag |= BIT_USESERVERSIDEPREPARE;
|
|
if (ci->lower_case_identifier)
|
|
flag |= BIT_LOWERCASEIDENTIFIER;
|
|
|
|
if (ci->sslmode[0])
|
|
{
|
|
char abbrevmode[sizeof(ci->sslmode)];
|
|
|
|
(void) snprintf(&connect_string[hlen], nlen, ";"
|
|
ABBR_SSLMODE "=%s", abbrev_sslmode(ci->sslmode, abbrevmode, sizeof(abbrevmode)));
|
|
}
|
|
hlen = strlen(connect_string);
|
|
nlen = MAX_CONNECT_STRING - hlen;
|
|
olen = snprintf(&connect_string[hlen], nlen, ";"
|
|
"%s" /* ABBR_CONNSETTINGS */
|
|
ABBR_FETCH "=%d;"
|
|
ABBR_MAXVARCHARSIZE "=%d;"
|
|
ABBR_MAXLONGVARCHARSIZE "=%d;"
|
|
INI_INT8AS "=%d;"
|
|
ABBR_EXTRASYSTABLEPREFIXES "=%s;"
|
|
"%s" /* ABBR_PQOPT */
|
|
"%s" /* ABBRKEEPALIVE TIME/INTERVAL */
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
"%s"
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
INI_ABBREVIATE "=%02x%x",
|
|
makeBracketConnectString(&connsetStr, ci->conn_settings, ABBR_CONNSETTINGS),
|
|
ci->drivers.fetch_max,
|
|
ci->drivers.max_varchar_size,
|
|
ci->drivers.max_longvarchar_size,
|
|
ci->int8_as,
|
|
ci->drivers.extra_systable_prefixes,
|
|
makeBracketConnectString(&pqoptStr, ci->pqopt, ABBR_PQOPT),
|
|
makeKeepaliveConnectString(keepaliveStr, sizeof(keepaliveStr), ci, TRUE),
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
makeXaOptConnectString(xaOptStr, sizeof(xaOptStr), ci, TRUE),
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
EFFECTIVE_BIT_COUNT, flag);
|
|
if (olen < nlen || ci->rollback_on_error >= 0)
|
|
{
|
|
hlen = strlen(connect_string);
|
|
nlen = MAX_CONNECT_STRING - hlen;
|
|
/*
|
|
* The PROTOCOL setting must be placed after CX flag
|
|
* so that this option can override the CX setting.
|
|
*/
|
|
if (ci->rollback_on_error >= 0)
|
|
olen = snprintf(&connect_string[hlen], nlen, ";"
|
|
ABBR_PROTOCOL "=7.4-%d",
|
|
ci->rollback_on_error);
|
|
else
|
|
olen = snprintf(&connect_string[hlen], nlen, ";"
|
|
ABBR_PROTOCOL "=7.4");
|
|
}
|
|
}
|
|
if (olen < nlen)
|
|
{
|
|
flag = getExtraOptions(ci);
|
|
if (0 != flag)
|
|
{
|
|
hlen = strlen(connect_string);
|
|
nlen = MAX_CONNECT_STRING - hlen;
|
|
olen = snprintf(&connect_string[hlen], nlen, ";"
|
|
INI_EXTRAOPTIONS "=%x;",
|
|
flag);
|
|
}
|
|
}
|
|
if (olen < 0 || olen >= nlen) /* failed */
|
|
connect_string[0] = '\0';
|
|
|
|
if (NULL != connsetStr)
|
|
free(connsetStr);
|
|
if (NULL != pqoptStr)
|
|
free(pqoptStr);
|
|
}
|
|
|
|
static void
|
|
unfoldCXAttribute(ConnInfo *ci, const char *value)
|
|
{
|
|
int count;
|
|
UInt4 flag;
|
|
|
|
if (strlen(value) < 2)
|
|
{
|
|
count = 3;
|
|
sscanf(value, "%x", &flag);
|
|
}
|
|
else
|
|
{
|
|
char cnt[8];
|
|
memcpy(cnt, value, 2);
|
|
cnt[2] = '\0';
|
|
sscanf(cnt, "%x", &count);
|
|
sscanf(value + 2, "%x", &flag);
|
|
}
|
|
ci->allow_keyset = (char)((flag & BIT_UPDATABLECURSORS) != 0);
|
|
ci->lf_conversion = (char)((flag & BIT_LFCONVERSION) != 0);
|
|
if (count < 4)
|
|
return;
|
|
ci->drivers.unique_index = (char)((flag & BIT_UNIQUEINDEX) != 0);
|
|
if ((flag & BIT_UNKNOWN_DONTKNOW) != 0)
|
|
ci->drivers.unknown_sizes = UNKNOWNS_AS_DONTKNOW;
|
|
else if ((flag & BIT_UNKNOWN_ASMAX) != 0)
|
|
ci->drivers.unknown_sizes = UNKNOWNS_AS_MAX;
|
|
else
|
|
ci->drivers.unknown_sizes = UNKNOWNS_AS_LONGEST;
|
|
ci->drivers.commlog = (char)((flag & BIT_COMMLOG) != 0);
|
|
ci->drivers.debug = (char)((flag & BIT_DEBUG) != 0);
|
|
ci->drivers.parse = (char)((flag & BIT_PARSE) != 0);
|
|
ci->drivers.use_declarefetch = (char)((flag & BIT_USEDECLAREFETCH) != 0);
|
|
ITOA_FIXED(ci->onlyread, (char)((flag & BIT_READONLY) != 0));
|
|
ci->drivers.text_as_longvarchar = (char)((flag & BIT_TEXTASLONGVARCHAR) !=0);
|
|
ci->drivers.unknowns_as_longvarchar = (char)((flag & BIT_UNKNOWNSASLONGVARCHAR) !=0);
|
|
ci->drivers.bools_as_char = (char)((flag & BIT_BOOLSASCHAR) != 0);
|
|
ITOA_FIXED(ci->row_versioning, (char)((flag & BIT_ROWVERSIONING) != 0));
|
|
ITOA_FIXED(ci->show_system_tables, (char)((flag & BIT_SHOWSYSTEMTABLES) != 0));
|
|
ITOA_FIXED(ci->show_oid_column, (char)((flag & BIT_SHOWOIDCOLUMN) != 0));
|
|
ITOA_FIXED(ci->fake_oid_index, (char)((flag & BIT_FAKEOIDINDEX) != 0));
|
|
ci->true_is_minus1 = (char)((flag & BIT_TRUEISMINUS1) != 0);
|
|
ci->bytea_as_longvarbinary = (char)((flag & BIT_BYTEAASLONGVARBINARY) != 0);
|
|
ci->use_server_side_prepare = (char)((flag & BIT_USESERVERSIDEPREPARE) != 0);
|
|
ci->lower_case_identifier = (char)((flag & BIT_LOWERCASEIDENTIFIER) != 0);
|
|
}
|
|
|
|
BOOL
|
|
get_DSN_or_Driver(ConnInfo *ci, const char *attribute, char *value)
|
|
{
|
|
BOOL found = TRUE;
|
|
|
|
if (stricmp(attribute, "DSN") == 0)
|
|
STRCPY_FIXED(ci->dsn, value);
|
|
else if (stricmp(attribute, "driver") == 0)
|
|
STRCPY_FIXED(ci->drivername, value);
|
|
else
|
|
found = FALSE;
|
|
|
|
return found;
|
|
}
|
|
|
|
BOOL
|
|
copyConnAttributes(ConnInfo *ci, const char *attribute, char *value)
|
|
{
|
|
BOOL found = TRUE, printed = FALSE;
|
|
|
|
if (stricmp(attribute, "DSN") == 0)
|
|
STRCPY_FIXED(ci->dsn, value);
|
|
else if (stricmp(attribute, "driver") == 0)
|
|
STRCPY_FIXED(ci->drivername, value);
|
|
else if (stricmp(attribute, INI_KDESC) == 0)
|
|
STRCPY_FIXED(ci->desc, value);
|
|
else if (stricmp(attribute, INI_DATABASE) == 0)
|
|
STRCPY_FIXED(ci->database, value);
|
|
else if (stricmp(attribute, INI_SERVER) == 0 || stricmp(attribute, SPEC_SERVER) == 0)
|
|
STRCPY_FIXED(ci->server, value);
|
|
else if (stricmp(attribute, INI_USERNAME) == 0 || stricmp(attribute, INI_UID) == 0)
|
|
STRCPY_FIXED(ci->username, value);
|
|
else if (stricmp(attribute, INI_PASSWORD) == 0 || stricmp(attribute, "pwd") == 0)
|
|
{
|
|
ci->password = decode_or_remove_braces(value);
|
|
#ifndef FORCE_PASSWORDE_DISPLAY
|
|
MYLOG(0, "key='%s' value='xxxxxxxx'\n", attribute);
|
|
printed = TRUE;
|
|
#endif
|
|
if (strlen(value))
|
|
memset(value, 0, strlen(value));
|
|
}
|
|
else if (stricmp(attribute, INI_PORT) == 0)
|
|
STRCPY_FIXED(ci->port, value);
|
|
else if (stricmp(attribute, INI_READONLY) == 0 || stricmp(attribute, ABBR_READONLY) == 0)
|
|
STRCPY_FIXED(ci->onlyread, value);
|
|
else if (stricmp(attribute, INI_PROTOCOL) == 0 || stricmp(attribute, ABBR_PROTOCOL) == 0)
|
|
{
|
|
char *ptr;
|
|
/*
|
|
* The first part of the Protocol used to be "6.2", "6.3" or
|
|
* "7.4" to denote which protocol version to use. Nowadays we
|
|
* only support the 7.4 protocol, also known as the protocol
|
|
* version 3. So just ignore the first part of the string,
|
|
* parsing only the rollback_on_error value.
|
|
*/
|
|
ptr = strchr(value, '-');
|
|
if (ptr)
|
|
{
|
|
if ('-' != *value)
|
|
{
|
|
*ptr = '\0';
|
|
/* ignore first part */
|
|
}
|
|
ci->rollback_on_error = atoi(ptr + 1);
|
|
MYLOG(0, "key='%s' value='%s' rollback_on_error=%d\n",
|
|
attribute, value, ci->rollback_on_error);
|
|
printed = TRUE;
|
|
}
|
|
}
|
|
else if (stricmp(attribute, INI_SHOWOIDCOLUMN) == 0 || stricmp(attribute, ABBR_SHOWOIDCOLUMN) == 0)
|
|
STRCPY_FIXED(ci->show_oid_column, value);
|
|
else if (stricmp(attribute, INI_FAKEOIDINDEX) == 0 || stricmp(attribute, ABBR_FAKEOIDINDEX) == 0)
|
|
STRCPY_FIXED(ci->fake_oid_index, value);
|
|
else if (stricmp(attribute, INI_ROWVERSIONING) == 0 || stricmp(attribute, ABBR_ROWVERSIONING) == 0)
|
|
STRCPY_FIXED(ci->row_versioning, value);
|
|
else if (stricmp(attribute, INI_SHOWSYSTEMTABLES) == 0 || stricmp(attribute, ABBR_SHOWSYSTEMTABLES) == 0)
|
|
STRCPY_FIXED(ci->show_system_tables, value);
|
|
else if (stricmp(attribute, INI_CONNSETTINGS) == 0 || stricmp(attribute, ABBR_CONNSETTINGS) == 0)
|
|
{
|
|
/* We can use the conn_settings directly when they are enclosed with braces */
|
|
ci->conn_settings = decode_or_remove_braces(value);
|
|
}
|
|
else if (stricmp(attribute, INI_PQOPT) == 0 || stricmp(attribute, ABBR_PQOPT) == 0)
|
|
{
|
|
ci->pqopt = decode_or_remove_braces(value);
|
|
}
|
|
else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, ABBR_UPDATABLECURSORS) == 0)
|
|
ci->allow_keyset = atoi(value);
|
|
else if (stricmp(attribute, INI_LFCONVERSION) == 0 || stricmp(attribute, ABBR_LFCONVERSION) == 0)
|
|
ci->lf_conversion = atoi(value);
|
|
else if (stricmp(attribute, INI_TRUEISMINUS1) == 0 || stricmp(attribute, ABBR_TRUEISMINUS1) == 0)
|
|
ci->true_is_minus1 = atoi(value);
|
|
else if (stricmp(attribute, INI_INT8AS) == 0)
|
|
ci->int8_as = atoi(value);
|
|
else if (stricmp(attribute, INI_BYTEAASLONGVARBINARY) == 0 || stricmp(attribute, ABBR_BYTEAASLONGVARBINARY) == 0)
|
|
ci->bytea_as_longvarbinary = atoi(value);
|
|
else if (stricmp(attribute, INI_USESERVERSIDEPREPARE) == 0 || stricmp(attribute, ABBR_USESERVERSIDEPREPARE) == 0)
|
|
ci->use_server_side_prepare = atoi(value);
|
|
else if (stricmp(attribute, INI_USEBATCHPROTOCOL) == 0)
|
|
ci->use_batch_protocol = atoi(value);
|
|
else if (stricmp(attribute, INI_LOWERCASEIDENTIFIER) == 0 || stricmp(attribute, ABBR_LOWERCASEIDENTIFIER) == 0)
|
|
ci->lower_case_identifier = atoi(value);
|
|
else if (stricmp(attribute, INI_KEEPALIVETIME) == 0 || stricmp(attribute, ABBR_KEEPALIVETIME) == 0)
|
|
ci->keepalive_idle = atoi(value);
|
|
else if (stricmp(attribute, INI_KEEPALIVEINTERVAL) == 0 || stricmp(attribute, ABBR_KEEPALIVEINTERVAL) == 0)
|
|
ci->keepalive_interval = atoi(value);
|
|
else if (stricmp(attribute, INI_AUTOBALANCE) == 0 || stricmp(attribute, ABBR_AUTOBALANCE) == 0)
|
|
ci->autobalance = atoi(value);
|
|
else if (stricmp(attribute, INI_REFRESHCNLISTTIME) == 0 || stricmp(attribute, ABBR_REFRESHCNLISTTIME) == 0)
|
|
ci->refreshcnlisttime = atoi(value);
|
|
else if (stricmp(attribute, INI_PRIORITY) == 0 || stricmp(attribute, ABBR_PRIORITY) == 0)
|
|
ci->priority = atoi(value);
|
|
else if (stricmp(attribute, INI_SSLMODE) == 0 || stricmp(attribute, ABBR_SSLMODE) == 0)
|
|
{
|
|
switch (value[0])
|
|
{
|
|
case SSLLBYTE_ALLOW:
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_ALLOW);
|
|
break;
|
|
case SSLLBYTE_PREFER:
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_PREFER);
|
|
break;
|
|
case SSLLBYTE_REQUIRE:
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_REQUIRE);
|
|
break;
|
|
case SSLLBYTE_VERIFY:
|
|
switch (value[1])
|
|
{
|
|
case 'f':
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_VERIFY_FULL);
|
|
break;
|
|
case 'c':
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_VERIFY_CA);
|
|
break;
|
|
default:
|
|
STRCPY_FIXED(ci->sslmode, value);
|
|
}
|
|
break;
|
|
case SSLLBYTE_DISABLE:
|
|
default:
|
|
STRCPY_FIXED(ci->sslmode, SSLMODE_DISABLE);
|
|
break;
|
|
}
|
|
MYLOG(0, "key='%s' value='%s' set to '%s'\n",
|
|
attribute, value, ci->sslmode);
|
|
printed = TRUE;
|
|
}
|
|
else if (stricmp(attribute, INI_ABBREVIATE) == 0)
|
|
unfoldCXAttribute(ci, value);
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
else if (stricmp(attribute, INI_XAOPT) == 0)
|
|
ci->xa_opt = atoi(value);
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
else if (stricmp(attribute, INI_EXTRAOPTIONS) == 0)
|
|
{
|
|
UInt4 val1 = 0, val2 = 0;
|
|
|
|
if ('+' == value[0])
|
|
{
|
|
sscanf(value + 1, "%x-%x", &val1, &val2);
|
|
add_removeExtraOptions(ci, val1, val2);
|
|
}
|
|
else if ('-' == value[0])
|
|
{
|
|
sscanf(value + 1, "%x", &val2);
|
|
add_removeExtraOptions(ci, 0, val2);
|
|
}
|
|
else
|
|
{
|
|
setExtraOptions(ci, value, hex_format);
|
|
}
|
|
MYLOG(0, "key='%s' value='%s'(force_abbrev=%d bde=%d cvt_null_date=%x)\n",
|
|
attribute, value, ci->force_abbrev_connstr, ci->bde_environment, ci->cvt_null_date_string);
|
|
printed = TRUE;
|
|
}
|
|
|
|
else if (stricmp(attribute, INI_FETCH) == 0 || stricmp(attribute, ABBR_FETCH) == 0)
|
|
ci->drivers.fetch_max = atoi(value);
|
|
else if (stricmp(attribute, INI_DEBUG) == 0 || stricmp(attribute, ABBR_DEBUG) == 0)
|
|
ci->drivers.debug = atoi(value);
|
|
else if (stricmp(attribute, INI_COMMLOG) == 0 || stricmp(attribute, ABBR_COMMLOG) == 0)
|
|
ci->drivers.commlog = atoi(value);
|
|
/*
|
|
* else if (stricmp(attribute, INI_UNIQUEINDEX) == 0 ||
|
|
* stricmp(attribute, "UIX") == 0) ci->drivers.unique_index =
|
|
* atoi(value);
|
|
*/
|
|
else if (stricmp(attribute, INI_UNKNOWNSIZES) == 0 || stricmp(attribute, ABBR_UNKNOWNSIZES) == 0)
|
|
ci->drivers.unknown_sizes = atoi(value);
|
|
else if (stricmp(attribute, INI_LIE) == 0)
|
|
ci->drivers.lie = atoi(value);
|
|
else if (stricmp(attribute, INI_PARSE) == 0 || stricmp(attribute, ABBR_PARSE) == 0)
|
|
ci->drivers.parse = atoi(value);
|
|
else if (stricmp(attribute, INI_USEDECLAREFETCH) == 0 || stricmp(attribute, ABBR_USEDECLAREFETCH) == 0)
|
|
ci->drivers.use_declarefetch = atoi(value);
|
|
else if (stricmp(attribute, INI_MAXVARCHARSIZE) == 0 || stricmp(attribute, ABBR_MAXVARCHARSIZE) == 0)
|
|
ci->drivers.max_varchar_size = atoi(value);
|
|
else if (stricmp(attribute, INI_MAXLONGVARCHARSIZE) == 0 || stricmp(attribute, ABBR_MAXLONGVARCHARSIZE) == 0)
|
|
ci->drivers.max_longvarchar_size = atoi(value);
|
|
else if (stricmp(attribute, INI_TEXTASLONGVARCHAR) == 0 || stricmp(attribute, ABBR_TEXTASLONGVARCHAR) == 0)
|
|
ci->drivers.text_as_longvarchar = atoi(value);
|
|
else if (stricmp(attribute, INI_UNKNOWNSASLONGVARCHAR) == 0 || stricmp(attribute, ABBR_UNKNOWNSASLONGVARCHAR) == 0)
|
|
ci->drivers.unknowns_as_longvarchar = atoi(value);
|
|
else if (stricmp(attribute, INI_BOOLSASCHAR) == 0 || stricmp(attribute, ABBR_BOOLSASCHAR) == 0)
|
|
ci->drivers.bools_as_char = atoi(value);
|
|
else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, ABBR_EXTRASYSTABLEPREFIXES) == 0)
|
|
STRCPY_FIXED(ci->drivers.extra_systable_prefixes, value);
|
|
else if (stricmp(attribute, INI_FOREXTENSIONCONNECTOR) == 0)
|
|
ci->drivers.for_extension_connector = atoi(value);
|
|
else if (stricmp(attribute, INI_CONNECTIONEXTRAINFO) == 0)
|
|
ci->connection_extra_info = atoi(value);
|
|
else
|
|
found = FALSE;
|
|
|
|
if (!printed)
|
|
MYLOG(0, "key='%s' value='%s'%s\n", attribute,
|
|
value, found ? NULL_STRING : " not found");
|
|
|
|
return found;
|
|
}
|
|
|
|
|
|
static void
|
|
getCiDefaults(ConnInfo *ci)
|
|
{
|
|
MYLOG(0, "entering\n");
|
|
|
|
ci->drivers.debug = DEFAULT_DEBUG;
|
|
ci->drivers.commlog = DEFAULT_COMMLOG;
|
|
ITOA_FIXED(ci->onlyread, DEFAULT_READONLY);
|
|
ITOA_FIXED(ci->fake_oid_index, DEFAULT_FAKEOIDINDEX);
|
|
ITOA_FIXED(ci->show_oid_column, DEFAULT_SHOWOIDCOLUMN);
|
|
ITOA_FIXED(ci->show_system_tables, DEFAULT_SHOWSYSTEMTABLES);
|
|
ITOA_FIXED(ci->row_versioning, DEFAULT_ROWVERSIONING);
|
|
ci->allow_keyset = DEFAULT_UPDATABLECURSORS;
|
|
ci->lf_conversion = DEFAULT_LFCONVERSION;
|
|
ci->true_is_minus1 = DEFAULT_TRUEISMINUS1;
|
|
ci->int8_as = DEFAULT_INT8AS;
|
|
ci->bytea_as_longvarbinary = DEFAULT_BYTEAASLONGVARBINARY;
|
|
ci->use_server_side_prepare = DEFAULT_USESERVERSIDEPREPARE;
|
|
ci->use_batch_protocol = DEFAULT_USEBATCHPROTOCOL;
|
|
ci->lower_case_identifier = DEFAULT_LOWERCASEIDENTIFIER;
|
|
STRCPY_FIXED(ci->sslmode, DEFAULT_SSLMODE);
|
|
ci->force_abbrev_connstr = 0;
|
|
ci->fake_mss = 0;
|
|
ci->bde_environment = 0;
|
|
ci->cvt_null_date_string = 0;
|
|
ci->accessible_only = 0;
|
|
ci->ignore_round_trip_time = 0;
|
|
ci->disable_keepalive = 0;
|
|
{
|
|
const char *p;
|
|
|
|
ci->wcs_debug = 0;
|
|
if (NULL != (p = getenv("PSQLODBC_WCS_DEBUG")))
|
|
if (strcmp(p, "1") == 0)
|
|
ci->wcs_debug = 1;
|
|
}
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
ci->xa_opt = DEFAULT_XAOPT;
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
ci->connection_extra_info = DEFAULT_CONNECTIONEXTRAINFO;
|
|
}
|
|
|
|
int
|
|
getDriverNameFromDSN(const char *dsn, char *driver_name, int namelen)
|
|
{
|
|
#ifdef WIN32
|
|
return SQLGetPrivateProfileString(ODBC_DATASOURCES, dsn, NULL_STRING, driver_name, namelen, ODBC_INI);
|
|
#else /* WIN32 */
|
|
int cnt;
|
|
|
|
cnt = SQLGetPrivateProfileString(dsn, "Driver", NULL_STRING, driver_name, namelen, ODBC_INI);
|
|
if (!driver_name[0])
|
|
return cnt;
|
|
if (strchr(driver_name, '/') || /* path to the driver */
|
|
strchr(driver_name, '.'))
|
|
{
|
|
driver_name[0] = '\0';
|
|
return 0;
|
|
}
|
|
return cnt;
|
|
#endif /* WIN32 */
|
|
}
|
|
|
|
static void Global_defset(GLOBAL_VALUES *comval)
|
|
{
|
|
comval->fetch_max = FETCH_MAX;
|
|
comval->unique_index = DEFAULT_UNIQUEINDEX;
|
|
comval->unknown_sizes = DEFAULT_UNKNOWNSIZES;
|
|
comval->lie = DEFAULT_LIE;
|
|
comval->parse = DEFAULT_PARSE;
|
|
comval->use_declarefetch = DEFAULT_USEDECLAREFETCH;
|
|
comval->max_varchar_size = MAX_VARCHAR_SIZE;
|
|
comval->max_longvarchar_size = TEXT_FIELD_SIZE;
|
|
comval->text_as_longvarchar = DEFAULT_TEXTASLONGVARCHAR;
|
|
comval->unknowns_as_longvarchar = DEFAULT_UNKNOWNSASLONGVARCHAR;
|
|
comval->bools_as_char = DEFAULT_BOOLSASCHAR;
|
|
STRCPY_FIXED(comval->extra_systable_prefixes, DEFAULT_EXTRASYSTABLEPREFIXES);
|
|
STRCPY_FIXED(comval->protocol, DEFAULT_PROTOCOL);
|
|
comval->for_extension_connector = DEFAULT_FOREXTENSIONCONNECTOR;
|
|
}
|
|
|
|
static void
|
|
get_Ci_Drivers(const char *section, const char *filename, GLOBAL_VALUES *comval);
|
|
|
|
void getDriversDefaults(const char *drivername, GLOBAL_VALUES *comval)
|
|
{
|
|
MYLOG(0, "%p of the driver %s\n", comval, NULL_IF_NULL(drivername));
|
|
get_Ci_Drivers(drivername, ODBCINST_INI, comval);
|
|
if (NULL != drivername)
|
|
STR_TO_NAME(comval->drivername, drivername);
|
|
}
|
|
|
|
void
|
|
getCiAllDefaults(ConnInfo *ci)
|
|
{
|
|
Global_defset(&(ci->drivers));
|
|
getCiDefaults(ci);
|
|
}
|
|
|
|
void
|
|
getDSNinfo(ConnInfo *ci, const char *configDrvrname)
|
|
{
|
|
char *DSN = ci->dsn;
|
|
char temp[LARGE_REGISTRY_LEN];
|
|
const char *drivername;
|
|
|
|
/*
|
|
* If a driver keyword was present, then dont use a DSN and return.
|
|
* If DSN is null and no driver, then use the default datasource.
|
|
*/
|
|
MYLOG(0, "entering DSN=%s driver=%s&%s\n", DSN,
|
|
ci->drivername, NULL_IF_NULL(configDrvrname));
|
|
|
|
getCiDefaults(ci);
|
|
drivername = ci->drivername;
|
|
if (DSN[0] == '\0')
|
|
{
|
|
if (drivername[0] == '\0') /* adding new DSN via configDSN */
|
|
{
|
|
if (configDrvrname)
|
|
drivername = configDrvrname;
|
|
strncpy_null(DSN, INI_DSN, sizeof(ci->dsn));
|
|
}
|
|
/* else dns-less connections */
|
|
}
|
|
|
|
/* brute-force chop off trailing blanks... */
|
|
while (*(DSN + strlen(DSN) - 1) == ' ')
|
|
*(DSN + strlen(DSN) - 1) = '\0';
|
|
|
|
if (!drivername[0] && DSN[0])
|
|
getDriverNameFromDSN(DSN, (char *) drivername, sizeof(ci->drivername));
|
|
MYLOG(0, "drivername=%s\n", drivername);
|
|
if (!drivername[0])
|
|
drivername = INVALID_DRIVER;
|
|
getDriversDefaults(drivername, &(ci->drivers));
|
|
|
|
if (DSN[0] == '\0')
|
|
return;
|
|
|
|
/* Proceed with getting info for the given DSN. */
|
|
|
|
SQLGetPrivateProfileString(DSN, INI_KDESC, NULL_STRING, ci->desc, sizeof(ci->desc), ODBC_INI);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_SERVER, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->server, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_DATABASE, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->database, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_USERNAME, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->username, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_PASSWORD, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
{
|
|
ci->password = decode(temp);
|
|
if (strlen(temp))
|
|
memset(temp, 0, strlen(temp));
|
|
}
|
|
if (SQLGetPrivateProfileString(DSN, INI_PORT, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->port, temp);
|
|
|
|
/* It's appropriate to handle debug and commlog here */
|
|
if (SQLGetPrivateProfileString(DSN, INI_DEBUG, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->drivers.debug = atoi(temp);
|
|
if (SQLGetPrivateProfileString(DSN, INI_COMMLOG, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->drivers.commlog = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_READONLY, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->onlyread, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_SHOWOIDCOLUMN, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->show_oid_column, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_FAKEOIDINDEX, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->fake_oid_index, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_ROWVERSIONING, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->row_versioning, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_SHOWSYSTEMTABLES, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->show_system_tables, temp);
|
|
|
|
SQLGetPrivateProfileString(DSN, INI_PROTOCOL, ENTRY_TEST, temp, sizeof(temp), ODBC_INI);
|
|
if (strcmp(temp, ENTRY_TEST)) /* entry exists */
|
|
{
|
|
char *ptr;
|
|
|
|
if (ptr = strchr(temp, '-'), NULL != ptr)
|
|
{
|
|
*ptr = '\0';
|
|
ci->rollback_on_error = atoi(ptr + 1);
|
|
MYLOG(0, "rollback_on_error=%d\n", ci->rollback_on_error);
|
|
}
|
|
}
|
|
|
|
SQLGetPrivateProfileString(DSN, INI_CONNSETTINGS, ENTRY_TEST, temp, sizeof(temp), ODBC_INI);
|
|
if (strcmp(temp, ENTRY_TEST)) /* entry exists */
|
|
{
|
|
const UCHAR *ptr;
|
|
BOOL percent_encoded = TRUE, pspace;
|
|
int nspcnt;
|
|
|
|
/*
|
|
* percent-encoding was used before.
|
|
* Note that there's no space in percent-encoding.
|
|
*/
|
|
for (ptr = (UCHAR *) temp, pspace = TRUE, nspcnt = 0; *ptr; ptr++)
|
|
{
|
|
if (isspace(*ptr))
|
|
pspace = TRUE;
|
|
else
|
|
{
|
|
if (pspace)
|
|
{
|
|
if (nspcnt++ > 1)
|
|
{
|
|
percent_encoded = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
pspace = FALSE;
|
|
}
|
|
}
|
|
if (percent_encoded)
|
|
ci->conn_settings = decode(temp);
|
|
else
|
|
STRX_TO_NAME(ci->conn_settings, temp);
|
|
}
|
|
SQLGetPrivateProfileString(DSN, INI_PQOPT, ENTRY_TEST, temp, sizeof(temp), ODBC_INI);
|
|
if (strcmp(temp, ENTRY_TEST)) /* entry exists */
|
|
STRX_TO_NAME(ci->pqopt, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_TRANSLATIONDLL, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->translation_dll, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->translation_option, temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->allow_keyset = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_LFCONVERSION, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->lf_conversion = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_TRUEISMINUS1, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->true_is_minus1 = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_INT8AS, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->int8_as = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_BYTEAASLONGVARBINARY, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->bytea_as_longvarbinary = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_USESERVERSIDEPREPARE, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->use_server_side_prepare = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_CONNECTIONEXTRAINFO, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->connection_extra_info = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_USEBATCHPROTOCOL, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->use_batch_protocol = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_LOWERCASEIDENTIFIER, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->lower_case_identifier = atoi(temp);
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_KEEPALIVETIME, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
if (0 == (ci->keepalive_idle = atoi(temp)))
|
|
ci->keepalive_idle = -1;
|
|
if (SQLGetPrivateProfileString(DSN, INI_KEEPALIVEINTERVAL, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
if (0 == (ci->keepalive_interval = atoi(temp)))
|
|
ci->keepalive_interval = -1;
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_SSLMODE, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
STRCPY_FIXED(ci->sslmode, temp);
|
|
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
if (SQLGetPrivateProfileString(DSN, INI_XAOPT, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0)
|
|
ci->xa_opt = atoi(temp);
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
|
|
/* Force abbrev connstr or bde */
|
|
if (SQLGetPrivateProfileString(DSN, INI_EXTRAOPTIONS, NULL_STRING,
|
|
temp, sizeof(temp), ODBC_INI) > 0)
|
|
{
|
|
UInt4 val = 0;
|
|
|
|
sscanf(temp, "%x", &val);
|
|
replaceExtraOptions(ci, val, TRUE);
|
|
MYLOG(0, "force_abbrev=%d bde=%d cvt_null_date=%d\n", ci->force_abbrev_connstr, ci->bde_environment, ci->cvt_null_date_string);
|
|
}
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_AUTOBALANCE, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0) {
|
|
ci->autobalance = atoi(temp);
|
|
}
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_REFRESHCNLISTTIME, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0) {
|
|
ci->refreshcnlisttime = atoi(temp);
|
|
}
|
|
|
|
if (SQLGetPrivateProfileString(DSN, INI_PRIORITY, NULL_STRING, temp, sizeof(temp), ODBC_INI) > 0) {
|
|
ci->priority = atoi(temp);
|
|
if (ci->priority != 1) {
|
|
ci->priority = 0;
|
|
}
|
|
}
|
|
|
|
/* Allow override of odbcinst.ini parameters here */
|
|
get_Ci_Drivers(DSN, ODBC_INI, &(ci->drivers));
|
|
STR_TO_NAME(ci->drivers.drivername, drivername);
|
|
|
|
MYLOG(DETAIL_LOG_LEVEL, "DSN info: DSN='%s',server='%s',port='%s',dbase='%s',user='%s',passwd='%s'\n",
|
|
DSN,
|
|
ci->server,
|
|
ci->port,
|
|
ci->database,
|
|
ci->username,
|
|
NAME_IS_VALID(ci->password) ? "xxxxx" : "");
|
|
MYLOG(DETAIL_LOG_LEVEL, " onlyread='%s',showoid='%s',fakeoidindex='%s',showsystable='%s'\n",
|
|
ci->onlyread,
|
|
ci->show_oid_column,
|
|
ci->fake_oid_index,
|
|
ci->show_system_tables);
|
|
|
|
{
|
|
#ifdef NOT_USED
|
|
char *enc = (char *) check_client_encoding(ci->conn_settings);
|
|
|
|
MYLOG(DETAIL_LOG_LEVEL, " conn_settings='%s', conn_encoding='%s'\n", ci->conn_settings,
|
|
NULL != enc ? enc : "(null)");
|
|
if (NULL != enc)
|
|
free(enc);
|
|
#endif /* NOT_USED */
|
|
MYLOG(DETAIL_LOG_LEVEL, " translation_dll='%s',translation_option='%s'\n",
|
|
ci->translation_dll,
|
|
ci->translation_option);
|
|
}
|
|
}
|
|
/*
|
|
* This function writes any global parameters (that can be manipulated)
|
|
* to the ODBCINST.INI portion of the registry
|
|
*/
|
|
int
|
|
write_Ci_Drivers(const char *fileName, const char *sectionName,
|
|
const GLOBAL_VALUES *comval)
|
|
{
|
|
char tmp[128];
|
|
int errc = 0;
|
|
|
|
if (stricmp(ODBCINST_INI, fileName) == 0)
|
|
{
|
|
if (NULL == sectionName)
|
|
sectionName = DBMS_NAME;
|
|
}
|
|
|
|
if (stricmp(ODBCINST_INI, fileName) == 0)
|
|
return errc;
|
|
|
|
ITOA_FIXED(tmp, comval->commlog);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_COMMLOG, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->debug);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_DEBUG, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->fetch_max);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_FETCH, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->unique_index);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_UNIQUEINDEX, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->use_declarefetch);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_USEDECLAREFETCH, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->for_extension_connector);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_FOREXTENSIONCONNECTOR, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->unknown_sizes);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_UNKNOWNSIZES, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->text_as_longvarchar);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_TEXTASLONGVARCHAR, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->unknowns_as_longvarchar);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_UNKNOWNSASLONGVARCHAR, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->bools_as_char);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_BOOLSASCHAR, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->parse);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_PARSE, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->max_varchar_size);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_MAXVARCHARSIZE, tmp, fileName))
|
|
errc--;
|
|
|
|
ITOA_FIXED(tmp, comval->max_longvarchar_size);
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_MAXLONGVARCHARSIZE, tmp, fileName))
|
|
errc--;
|
|
|
|
if (!SQLWritePrivateProfileString(sectionName, INI_EXTRASYSTABLEPREFIXES, comval->extra_systable_prefixes, fileName))
|
|
errc--;
|
|
|
|
/*
|
|
* Never update the conn_setting from this module
|
|
* SQLWritePrivateProfileString(sectionName, INI_CONNSETTINGS,
|
|
* comval->conn_settings, fileName);
|
|
*/
|
|
|
|
return errc;
|
|
}
|
|
|
|
int
|
|
writeDriversDefaults(const char *drivername, const GLOBAL_VALUES *comval)
|
|
{
|
|
return write_Ci_Drivers(ODBCINST_INI, drivername, comval);
|
|
}
|
|
|
|
/* This is for datasource based options only */
|
|
void
|
|
writeDSNinfo(const ConnInfo *ci)
|
|
{
|
|
const char *DSN = ci->dsn;
|
|
char encoded_item[MEDIUM_REGISTRY_LEN],
|
|
temp[SMALL_REGISTRY_LEN];
|
|
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_KDESC,
|
|
ci->desc,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_DATABASE,
|
|
ci->database,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_SERVER,
|
|
ci->server,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_PORT,
|
|
ci->port,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_USERNAME,
|
|
ci->username,
|
|
ODBC_INI);
|
|
SQLWritePrivateProfileString(DSN, INI_UID, ci->username, ODBC_INI);
|
|
|
|
encode(ci->password, encoded_item, sizeof(encoded_item));
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_PASSWORD,
|
|
encoded_item,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_READONLY,
|
|
ci->onlyread,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_SHOWOIDCOLUMN,
|
|
ci->show_oid_column,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_FAKEOIDINDEX,
|
|
ci->fake_oid_index,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_ROWVERSIONING,
|
|
ci->row_versioning,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_SHOWSYSTEMTABLES,
|
|
ci->show_system_tables,
|
|
ODBC_INI);
|
|
|
|
if (ci->rollback_on_error >= 0)
|
|
SPRINTF_FIXED(temp, "7.4-%d", ci->rollback_on_error);
|
|
else
|
|
STRCPY_FIXED(temp, NULL_STRING);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_PROTOCOL,
|
|
temp,
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_CONNSETTINGS,
|
|
SAFE_NAME(ci->conn_settings),
|
|
ODBC_INI);
|
|
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_PQOPT,
|
|
SAFE_NAME(ci->pqopt),
|
|
ODBC_INI);
|
|
|
|
ITOA_FIXED(temp, ci->allow_keyset);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_UPDATABLECURSORS,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->lf_conversion);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_LFCONVERSION,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->true_is_minus1);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_TRUEISMINUS1,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->int8_as);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_INT8AS,
|
|
temp,
|
|
ODBC_INI);
|
|
SPRINTF_FIXED(temp, "%x", getExtraOptions(ci));
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_EXTRAOPTIONS,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->bytea_as_longvarbinary);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_BYTEAASLONGVARBINARY,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->use_server_side_prepare);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_USESERVERSIDEPREPARE,
|
|
temp,
|
|
ODBC_INI);
|
|
|
|
ITOA_FIXED(temp, ci->connection_extra_info);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_CONNECTIONEXTRAINFO,
|
|
temp,
|
|
ODBC_INI);
|
|
|
|
ITOA_FIXED(temp, ci->use_batch_protocol);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_USEBATCHPROTOCOL,
|
|
temp,
|
|
ODBC_INI);
|
|
|
|
ITOA_FIXED(temp, ci->lower_case_identifier);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_LOWERCASEIDENTIFIER,
|
|
temp,
|
|
ODBC_INI);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_SSLMODE,
|
|
ci->sslmode,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->keepalive_idle);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_KEEPALIVETIME,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->keepalive_interval);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_KEEPALIVEINTERVAL,
|
|
temp,
|
|
ODBC_INI);
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
ITOA_FIXED(temp, ci->xa_opt);
|
|
SQLWritePrivateProfileString(DSN, INI_XAOPT, temp, ODBC_INI);
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
|
|
ITOA_FIXED(temp, ci->autobalance);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_AUTOBALANCE,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->refreshcnlisttime);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_REFRESHCNLISTTIME,
|
|
temp,
|
|
ODBC_INI);
|
|
ITOA_FIXED(temp, ci->priority);
|
|
SQLWritePrivateProfileString(DSN,
|
|
INI_PRIORITY,
|
|
temp,
|
|
ODBC_INI);
|
|
}
|
|
|
|
|
|
/*
|
|
* This function reads the ODBCINST.INI portion of
|
|
* the registry and gets any driver defaults.
|
|
*/
|
|
static void
|
|
get_Ci_Drivers(const char *section, const char *filename, GLOBAL_VALUES *comval)
|
|
{
|
|
char temp[256];
|
|
BOOL inst_position = (stricmp(filename, ODBCINST_INI) == 0);
|
|
|
|
if (0 != strcmp(ODBCINST_INI, filename))
|
|
MYLOG(0, "setting %s position of %s(%p)\n", filename, section, comval);
|
|
|
|
/*
|
|
* It's not appropriate to handle debug or commlog here.
|
|
* Now they are handled in getDSNinfo().
|
|
*/
|
|
|
|
if (inst_position)
|
|
Global_defset(comval);
|
|
if (NULL == section || strcmp(section, INVALID_DRIVER) == 0)
|
|
return;
|
|
/*
|
|
* If inst_position of xxxxxx is present(usually not present),
|
|
* it is the default of ci->drivers.xxxxxx .
|
|
*/
|
|
/* Fetch Count is stored in driver section */
|
|
if (SQLGetPrivateProfileString(section, INI_FETCH, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
{
|
|
if (atoi(temp) > 0)
|
|
comval->fetch_max = atoi(temp);
|
|
}
|
|
|
|
/* Recognize Unique Index is stored in the driver section only */
|
|
if (SQLGetPrivateProfileString(section, INI_UNIQUEINDEX, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->unique_index = atoi(temp);
|
|
|
|
/* Unknown Sizes is stored in the driver section only */
|
|
if (SQLGetPrivateProfileString(section, INI_UNKNOWNSIZES, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->unknown_sizes = atoi(temp);
|
|
|
|
/* Lie about supported functions? */
|
|
if (SQLGetPrivateProfileString(section, INI_LIE, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->lie = atoi(temp);
|
|
|
|
/* Parse statements */
|
|
if (SQLGetPrivateProfileString(section, INI_PARSE, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->parse = atoi(temp);
|
|
|
|
/* UseDeclareFetch is stored in the driver section only */
|
|
if (SQLGetPrivateProfileString(section, INI_USEDECLAREFETCH, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->use_declarefetch = atoi(temp);
|
|
|
|
/* ForExtensionConnector is stored in the driver section only */
|
|
if (SQLGetPrivateProfileString(section, INI_FOREXTENSIONCONNECTOR, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->for_extension_connector= atoi(temp);
|
|
|
|
/* Max Varchar Size */
|
|
if (SQLGetPrivateProfileString(section, INI_MAXVARCHARSIZE, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->max_varchar_size = atoi(temp);
|
|
|
|
/* Max TextField Size */
|
|
if (SQLGetPrivateProfileString(section, INI_MAXLONGVARCHARSIZE, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->max_longvarchar_size = atoi(temp);
|
|
|
|
/* Text As LongVarchar */
|
|
if (SQLGetPrivateProfileString(section, INI_TEXTASLONGVARCHAR, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->text_as_longvarchar = atoi(temp);
|
|
|
|
/* Unknowns As LongVarchar */
|
|
if (SQLGetPrivateProfileString(section, INI_UNKNOWNSASLONGVARCHAR, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->unknowns_as_longvarchar = atoi(temp);
|
|
|
|
/* Bools As Char */
|
|
if (SQLGetPrivateProfileString(section, INI_BOOLSASCHAR, NULL_STRING,
|
|
temp, sizeof(temp), filename) > 0)
|
|
comval->bools_as_char = atoi(temp);
|
|
|
|
/* Extra Systable prefixes */
|
|
|
|
/*
|
|
* Use ENTRY_TEST to distinguish between blank extra prefixes and no key
|
|
* entry
|
|
*/
|
|
SQLGetPrivateProfileString(section, INI_EXTRASYSTABLEPREFIXES, ENTRY_TEST,
|
|
temp, sizeof(temp), filename);
|
|
if (strcmp(temp, ENTRY_TEST))
|
|
STRCPY_FIXED(comval->extra_systable_prefixes, temp);
|
|
|
|
MYLOG(0, "comval=%p comval->extra_systable_prefixes = '%s'\n", comval, comval->extra_systable_prefixes);
|
|
|
|
|
|
/* Dont allow override of an override! */
|
|
if (inst_position)
|
|
{
|
|
/*
|
|
* Default state for future DSN's protocol attribute This isn't a
|
|
* real driver option YET. This is more intended for
|
|
* customization from the install.
|
|
*/
|
|
SQLGetPrivateProfileString(section, INI_PROTOCOL, ENTRY_TEST,
|
|
temp, sizeof(temp), filename);
|
|
if (strcmp(temp, ENTRY_TEST))
|
|
STRCPY_FIXED(comval->protocol, temp);
|
|
}
|
|
}
|
|
|
|
static void
|
|
encode(const pgNAME in, char *out, int outlen)
|
|
{
|
|
size_t i, ilen, o = 0;
|
|
char inc, *ins;
|
|
|
|
if (NAME_IS_NULL(in))
|
|
{
|
|
out[0] = '\0';
|
|
return;
|
|
}
|
|
ins = GET_NAME(in);
|
|
ilen = strlen(ins);
|
|
for (i = 0; i < ilen && o < outlen - 1; i++)
|
|
{
|
|
inc = ins[i];
|
|
if (inc == '+')
|
|
{
|
|
if (o + 2 >= outlen)
|
|
break;
|
|
snprintf(&out[o], outlen - o, "%%2B");
|
|
o += 3;
|
|
}
|
|
else if (isspace((unsigned char) inc))
|
|
out[o++] = '+';
|
|
else if (!isalnum((unsigned char) inc))
|
|
{
|
|
if (o + 2 >= outlen)
|
|
break;
|
|
snprintf(&out[o], outlen - o, "%%%02x", inc);
|
|
o += 3;
|
|
}
|
|
else
|
|
out[o++] = inc;
|
|
}
|
|
out[o++] = '\0';
|
|
}
|
|
|
|
static unsigned int
|
|
conv_from_hex(const char *s)
|
|
{
|
|
int i,
|
|
y = 0,
|
|
val;
|
|
|
|
for (i = 1; i <= 2; i++)
|
|
{
|
|
if (s[i] >= 'a' && s[i] <= 'f')
|
|
val = s[i] - 'a' + 10;
|
|
else if (s[i] >= 'A' && s[i] <= 'F')
|
|
val = s[i] - 'A' + 10;
|
|
else
|
|
val = s[i] - '0';
|
|
|
|
y += val << (4 * (2 - i));
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
static pgNAME
|
|
decode(const char *in)
|
|
{
|
|
size_t i, ilen = strlen(in), o = 0;
|
|
char inc, *outs;
|
|
pgNAME out;
|
|
|
|
INIT_NAME(out);
|
|
if (0 == ilen)
|
|
{
|
|
return out;
|
|
}
|
|
outs = (char *) malloc(ilen + 1);
|
|
if (!outs)
|
|
return out;
|
|
for (i = 0; i < ilen; i++)
|
|
{
|
|
inc = in[i];
|
|
if (inc == '+')
|
|
outs[o++] = ' ';
|
|
else if (inc == '%')
|
|
{
|
|
snprintf(&outs[o], ilen + 1 - o, "%c", conv_from_hex(&in[i]));
|
|
o++;
|
|
i += 2;
|
|
}
|
|
else
|
|
outs[o++] = inc;
|
|
}
|
|
outs[o++] = '\0';
|
|
STR_TO_NAME(out, outs);
|
|
free(outs);
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
* Remove braces if the input value is enclosed by braces({}).
|
|
* Othewise decode the input value.
|
|
*/
|
|
static pgNAME
|
|
decode_or_remove_braces(const char *in)
|
|
{
|
|
if (OPENING_BRACKET == in[0])
|
|
{
|
|
size_t inlen = strlen(in);
|
|
if (CLOSING_BRACKET == in[inlen - 1]) /* enclosed with braces */
|
|
{
|
|
int i;
|
|
const char *istr, *eptr;
|
|
char *ostr;
|
|
pgNAME out;
|
|
|
|
INIT_NAME(out);
|
|
if (NULL == (ostr = (char *) malloc(inlen)))
|
|
return out;
|
|
eptr = in + inlen - 1;
|
|
for (istr = in + 1, i = 0; *istr && istr < eptr; i++)
|
|
{
|
|
if (CLOSING_BRACKET == istr[0] &&
|
|
CLOSING_BRACKET == istr[1])
|
|
istr++;
|
|
ostr[i] = *(istr++);
|
|
}
|
|
ostr[i] = '\0';
|
|
SET_NAME_DIRECTLY(out, ostr);
|
|
return out;
|
|
}
|
|
}
|
|
return decode(in);
|
|
}
|
|
|
|
/*
|
|
* extract the specified attribute from the comment part.
|
|
* attribute=[']value[']
|
|
*/
|
|
char *extract_extra_attribute_setting(const pgNAME setting, const char *attr)
|
|
{
|
|
const char *str = SAFE_NAME(setting);
|
|
const char *cptr, *sptr = NULL;
|
|
char *rptr;
|
|
BOOL allowed_cmd = FALSE, in_quote = FALSE, in_comment = FALSE;
|
|
int step = 0, step_last = 2;
|
|
size_t len = 0, attrlen = strlen(attr);
|
|
|
|
for (cptr = str; *cptr; cptr++)
|
|
{
|
|
if (in_quote)
|
|
{
|
|
if (LITERAL_QUOTE == *cptr)
|
|
{
|
|
if (step_last == step)
|
|
{
|
|
len = cptr - sptr;
|
|
step = 0;
|
|
}
|
|
in_quote = FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
else if (in_comment)
|
|
{
|
|
if ('*' == *cptr &&
|
|
'/' == cptr[1])
|
|
{
|
|
if (step_last == step)
|
|
{
|
|
len = cptr - sptr;
|
|
step = 0;
|
|
}
|
|
in_comment = FALSE;
|
|
allowed_cmd = FALSE;
|
|
cptr++;
|
|
continue;
|
|
}
|
|
}
|
|
else if ('/' == *cptr &&
|
|
'*' == cptr[1])
|
|
{
|
|
in_comment = TRUE;
|
|
allowed_cmd = TRUE;
|
|
cptr++;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (LITERAL_QUOTE == *cptr)
|
|
in_quote = TRUE;
|
|
continue;
|
|
}
|
|
/* now in comment */
|
|
if (';' == *cptr ||
|
|
isspace((unsigned char) *cptr))
|
|
{
|
|
if (step_last == step)
|
|
len = cptr - sptr;
|
|
allowed_cmd = TRUE;
|
|
step = 0;
|
|
continue;
|
|
}
|
|
if (!allowed_cmd)
|
|
continue;
|
|
switch (step)
|
|
{
|
|
case 0:
|
|
if (0 != strnicmp(cptr, attr, attrlen))
|
|
{
|
|
allowed_cmd = FALSE;
|
|
continue;
|
|
}
|
|
if (cptr[attrlen] != '=')
|
|
{
|
|
allowed_cmd = FALSE;
|
|
continue;
|
|
}
|
|
step++;
|
|
cptr += attrlen;
|
|
break;
|
|
case 1:
|
|
if (LITERAL_QUOTE == *cptr)
|
|
{
|
|
in_quote = TRUE;
|
|
cptr++;
|
|
sptr = cptr;
|
|
}
|
|
else
|
|
sptr = cptr;
|
|
step++;
|
|
break;
|
|
}
|
|
}
|
|
if (!sptr)
|
|
return NULL;
|
|
rptr = malloc(len + 1);
|
|
if (!rptr)
|
|
return NULL;
|
|
memcpy(rptr, sptr, len);
|
|
rptr[len] = '\0';
|
|
MYLOG(0, "extracted a %s '%s' from %s\n", attr, rptr, str);
|
|
return rptr;
|
|
}
|
|
|
|
signed char ci_updatable_cursors_set(ConnInfo *ci)
|
|
{
|
|
ci->updatable_cursors = DISALLOW_UPDATABLE_CURSORS;
|
|
if (ci->allow_keyset)
|
|
{
|
|
if (ci->drivers.lie || !ci->drivers.use_declarefetch)
|
|
ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | ALLOW_KEYSET_DRIVEN_CURSORS | ALLOW_BULK_OPERATIONS | SENSE_SELF_OPERATIONS);
|
|
else
|
|
ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | ALLOW_BULK_OPERATIONS | SENSE_SELF_OPERATIONS);
|
|
}
|
|
return ci->updatable_cursors;
|
|
}
|
|
|
|
void
|
|
CC_conninfo_release(ConnInfo *conninfo)
|
|
{
|
|
NULL_THE_NAME(conninfo->password);
|
|
NULL_THE_NAME(conninfo->conn_settings);
|
|
NULL_THE_NAME(conninfo->pqopt);
|
|
finalize_globals(&conninfo->drivers);
|
|
}
|
|
|
|
void
|
|
CC_conninfo_init(ConnInfo *conninfo, UInt4 option)
|
|
{
|
|
MYLOG(0, "entering opt=%d\n", option);
|
|
|
|
if (0 != (CLEANUP_FOR_REUSE & option))
|
|
CC_conninfo_release(conninfo);
|
|
memset(conninfo, 0, sizeof(ConnInfo));
|
|
|
|
conninfo->allow_keyset = -1;
|
|
conninfo->lf_conversion = -1;
|
|
conninfo->true_is_minus1 = -1;
|
|
conninfo->int8_as = -101;
|
|
conninfo->bytea_as_longvarbinary = -1;
|
|
conninfo->use_server_side_prepare = -1;
|
|
conninfo->use_batch_protocol = -1;
|
|
conninfo->backend_support_batch_proto = -1;
|
|
conninfo->lower_case_identifier = -1;
|
|
conninfo->rollback_on_error = -1;
|
|
conninfo->force_abbrev_connstr = -1;
|
|
conninfo->bde_environment = -1;
|
|
conninfo->fake_mss = -1;
|
|
conninfo->cvt_null_date_string = -1;
|
|
conninfo->accessible_only = -1;
|
|
conninfo->ignore_round_trip_time = -1;
|
|
conninfo->disable_keepalive = -1;
|
|
conninfo->keepalive_idle = -1;
|
|
conninfo->keepalive_interval = -1;
|
|
conninfo->wcs_debug = -1;
|
|
conninfo->connection_extra_info = -1;
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
conninfo->xa_opt = -1;
|
|
#endif /* _HANDLE_ENLIST_IN_DTC_ */
|
|
if (0 != (INIT_GLOBALS & option))
|
|
init_globals(&(conninfo->drivers));
|
|
}
|
|
|
|
void init_globals(GLOBAL_VALUES *glbv)
|
|
{
|
|
memset(glbv, 0, sizeof(*glbv));
|
|
glbv->debug = -1;
|
|
glbv->commlog = -1;
|
|
}
|
|
|
|
#define CORR_STRCPY(item) strncpy_null(to->item, from->item, sizeof(to->item))
|
|
#define CORR_VALCPY(item) (to->item = from->item)
|
|
|
|
void copy_globals(GLOBAL_VALUES *to, const GLOBAL_VALUES *from)
|
|
{
|
|
memset(to, 0, sizeof(*to));
|
|
/***
|
|
memcpy(to, from, sizeof(GLOBAL_VALUES));
|
|
SET_NAME_DIRECTLY(to->drivername, NULL);
|
|
***/
|
|
NAME_TO_NAME(to->drivername, from->drivername);
|
|
CORR_VALCPY(fetch_max);
|
|
CORR_VALCPY(unknown_sizes);
|
|
CORR_VALCPY(max_varchar_size);
|
|
CORR_VALCPY(max_longvarchar_size);
|
|
CORR_VALCPY(debug);
|
|
CORR_VALCPY(commlog);
|
|
CORR_VALCPY(unique_index);
|
|
CORR_VALCPY(use_declarefetch);
|
|
CORR_VALCPY(text_as_longvarchar);
|
|
CORR_VALCPY(unknowns_as_longvarchar);
|
|
CORR_VALCPY(bools_as_char);
|
|
CORR_VALCPY(lie);
|
|
CORR_VALCPY(parse);
|
|
CORR_STRCPY(extra_systable_prefixes);
|
|
CORR_STRCPY(protocol);
|
|
|
|
MYLOG(0, "driver=%s\n", SAFE_NAME(to->drivername));
|
|
}
|
|
|
|
void finalize_globals(GLOBAL_VALUES *glbv)
|
|
{
|
|
NULL_THE_NAME(glbv->drivername);
|
|
}
|
|
|
|
#undef CORR_STRCPY
|
|
#undef CORR_VALCPY
|
|
#define CORR_STRCPY(item) strncpy_null(ci->item, sci->item, sizeof(ci->item))
|
|
#define CORR_VALCPY(item) (ci->item = sci->item)
|
|
|
|
void
|
|
CC_copy_conninfo(ConnInfo *ci, const ConnInfo *sci)
|
|
{
|
|
memset(ci, 0,sizeof(ConnInfo));
|
|
|
|
CORR_STRCPY(dsn);
|
|
CORR_STRCPY(desc);
|
|
CORR_STRCPY(drivername);
|
|
CORR_STRCPY(server);
|
|
CORR_STRCPY(database);
|
|
CORR_STRCPY(username);
|
|
NAME_TO_NAME(ci->password, sci->password);
|
|
CORR_STRCPY(port);
|
|
CORR_STRCPY(sslmode);
|
|
CORR_STRCPY(onlyread);
|
|
CORR_STRCPY(fake_oid_index);
|
|
CORR_STRCPY(show_oid_column);
|
|
CORR_STRCPY(row_versioning);
|
|
CORR_STRCPY(show_system_tables);
|
|
CORR_STRCPY(translation_dll);
|
|
CORR_STRCPY(translation_option);
|
|
CORR_VALCPY(password_required);
|
|
NAME_TO_NAME(ci->conn_settings, sci->conn_settings);
|
|
CORR_VALCPY(allow_keyset);
|
|
CORR_VALCPY(updatable_cursors);
|
|
CORR_VALCPY(lf_conversion);
|
|
CORR_VALCPY(true_is_minus1);
|
|
CORR_VALCPY(int8_as);
|
|
CORR_VALCPY(bytea_as_longvarbinary);
|
|
CORR_VALCPY(use_server_side_prepare);
|
|
CORR_VALCPY(lower_case_identifier);
|
|
CORR_VALCPY(rollback_on_error);
|
|
CORR_VALCPY(force_abbrev_connstr);
|
|
CORR_VALCPY(bde_environment);
|
|
CORR_VALCPY(fake_mss);
|
|
CORR_VALCPY(cvt_null_date_string);
|
|
CORR_VALCPY(accessible_only);
|
|
CORR_VALCPY(ignore_round_trip_time);
|
|
CORR_VALCPY(disable_keepalive);
|
|
CORR_VALCPY(extra_opts);
|
|
CORR_VALCPY(keepalive_idle);
|
|
CORR_VALCPY(keepalive_interval);
|
|
CORR_VALCPY(autobalance);
|
|
CORR_VALCPY(refreshcnlisttime);
|
|
CORR_VALCPY(priority);
|
|
#ifdef _HANDLE_ENLIST_IN_DTC_
|
|
CORR_VALCPY(xa_opt);
|
|
#endif
|
|
copy_globals(&(ci->drivers), &(sci->drivers)); /* moved from driver's option */
|
|
}
|
|
#undef CORR_STRCPY
|
|
#undef CORR_VALCPY
|