Skip to content

Commit 1a886b0

Browse files
committed
Code sharing for common ODBC functions
As of right now, only the connection string quoting rules, but perhaps other functionality can be moved in as needed. I'm not sure if main/ is the best place, but it seems other functionality only really used by extensions is here, so it makes sense.
1 parent 4e690b9 commit 1a886b0

File tree

6 files changed

+161
-196
lines changed

6 files changed

+161
-196
lines changed

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \
16121612
fopen_wrappers.c alloca.c php_scandir.c \
16131613
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16141614
strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \
1615-
network.c php_open_temporary_file.c \
1615+
network.c php_open_temporary_file.c php_odbc_utils.c \
16161616
output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
16171617

16181618
PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no)

ext/odbc/php_odbc.c

Lines changed: 9 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include "php_globals.h"
3535
#include "odbc_arginfo.h"
3636

37+
/* actually lives in main/ */
38+
#include "php_odbc_utils.h"
39+
3740
#ifdef HAVE_UODBC
3841

3942
#include <fcntl.h>
@@ -48,97 +51,6 @@
4851

4952
#endif
5053

51-
/**
52-
* Determines if a string matches the ODBC quoting rules.
53-
*
54-
* A valid quoted string begins with a '{', ends with a '}', and has no '}'
55-
* inside of the string that aren't repeated (as to be escaped).
56-
*
57-
* These rules are what .NET also follows.
58-
*/
59-
static bool is_odbc_quoted(const char *str)
60-
{
61-
if (!str) {
62-
return false;
63-
}
64-
/* ODBC quotes are curly braces */
65-
if (str[0] != '{') {
66-
return false;
67-
}
68-
/* Check for } that aren't doubled up or at the end of the string */
69-
size_t length = strlen(str);
70-
for (size_t i = 0; i < length; i++) {
71-
if (str[i] == '}' && str[i + 1] == '}') {
72-
/* Skip over so we don't count it again */
73-
i++;
74-
} else if (str[i] == '}' && str[i + 1] != '\0') {
75-
/* If not at the end, not quoted */
76-
return false;
77-
}
78-
}
79-
return true;
80-
}
81-
82-
/**
83-
* Determines if a value for a connection string should be quoted.
84-
*
85-
* The ODBC specification mentions:
86-
* "Because of connection string and initialization file grammar, keywords and
87-
* and attribute values that contain the characters []{}(),;?*=!@ not enclosed
88-
* with braces should be avoided."
89-
*
90-
* Note that it assumes that the string is *not* already quoted. You should
91-
* check beforehand.
92-
*/
93-
static bool should_odbc_quote(const char *str)
94-
{
95-
return strpbrk(str, "[]{}(),;?*=!@") != NULL;
96-
}
97-
98-
/**
99-
* Estimates the worst-case scenario for a quoted version of a string's size.
100-
*/
101-
static size_t estimate_odbc_quote_length(const char *in_str)
102-
{
103-
/* Assume all '}'. Include '{,' '}', and the null terminator too */
104-
return (strlen(in_str) * 2) + 3;
105-
}
106-
107-
/**
108-
* Quotes a string with ODBC rules.
109-
*
110-
* Some characters (curly braces, semicolons) are special and must be quoted.
111-
* In the case of '}' in a quoted string, they must be escaped SQL style; that
112-
* is, repeated.
113-
*/
114-
static size_t odbc_quote(char *out_str, const char *in_str, size_t out_str_size)
115-
{
116-
*out_str++ = '{';
117-
out_str_size--;
118-
while (out_str_size > 2) {
119-
if (*in_str == '\0') {
120-
break;
121-
} else if (*in_str == '}' && out_str_size - 1 > 2) {
122-
/* enough room to append */
123-
*out_str++ = '}';
124-
*out_str++ = *in_str++;
125-
out_str_size -= 2;
126-
} else if (*in_str == '}') {
127-
/* not enough, truncate here */
128-
break;
129-
} else {
130-
*out_str++ = *in_str++;
131-
out_str_size--;
132-
}
133-
}
134-
/* append termination */
135-
*out_str++ = '}';
136-
*out_str++ = '\0';
137-
out_str_size -= 2;
138-
/* return how many characters were left */
139-
return strlen(in_str);
140-
}
141-
14254
/*
14355
* not defined elsewhere
14456
*/
@@ -2269,28 +2181,28 @@ int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int
22692181
&& !strstr(db, "PWD=");
22702182
if (is_uid_set && is_pwd_set) {
22712183
char *uid_quoted = NULL, *pwd_quoted = NULL;
2272-
bool should_quote_uid = !is_odbc_quoted(uid) && should_odbc_quote(uid);
2273-
bool should_quote_pwd = !is_odbc_quoted(pwd) && should_odbc_quote(pwd);
2184+
bool should_quote_uid = !php_odbc_connstr_is_quoted(uid) && php_odbc_connstr_should_quote(uid);
2185+
bool should_quote_pwd = !php_odbc_connstr_is_quoted(pwd) && php_odbc_connstr_should_quote(pwd);
22742186
bool connection_string_fail = false;
22752187
if (should_quote_uid) {
2276-
size_t estimated_length = estimate_odbc_quote_length(uid);
2188+
size_t estimated_length = php_odbc_connstr_estimate_quote_length(uid);
22772189
uid_quoted = emalloc(estimated_length);
22782190
if (!uid_quoted) {
22792191
connection_string_fail = true;
22802192
goto connection_string_fail;
22812193
}
2282-
odbc_quote(uid_quoted, uid, estimated_length);
2194+
php_odbc_connstr_quote(uid_quoted, uid, estimated_length);
22832195
} else {
22842196
uid_quoted = uid;
22852197
}
22862198
if (should_quote_pwd) {
2287-
size_t estimated_length = estimate_odbc_quote_length(pwd);
2199+
size_t estimated_length = php_odbc_connstr_estimate_quote_length(pwd);
22882200
pwd_quoted = emalloc(estimated_length);
22892201
if (!pwd_quoted) {
22902202
connection_string_fail = true;
22912203
goto connection_string_fail;
22922204
}
2293-
odbc_quote(pwd_quoted, pwd, estimated_length);
2205+
php_odbc_connstr_quote(pwd_quoted, pwd, estimated_length);
22942206
} else {
22952207
pwd_quoted = pwd;
22962208
}

ext/pdo_odbc/odbc_driver.c

Lines changed: 8 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "ext/standard/info.h"
2424
#include "pdo/php_pdo.h"
2525
#include "pdo/php_pdo_driver.h"
26+
/* this file actually lives in main/ */
27+
#include "php_odbc_utils.h"
2628
#include "php_pdo_odbc.h"
2729
#include "php_pdo_odbc_int.h"
2830
#include "zend_exceptions.h"
@@ -428,97 +430,6 @@ static const struct pdo_dbh_methods odbc_methods = {
428430
NULL /* get_gc */
429431
};
430432

431-
/**
432-
* Determines if a string matches the ODBC quoting rules.
433-
*
434-
* A valid quoted string begins with a '{', ends with a '}', and has no '}'
435-
* inside of the string that aren't repeated (as to be escaped).
436-
*
437-
* These rules are what .NET also follows.
438-
*/
439-
static bool is_odbc_quoted(const char *str)
440-
{
441-
if (!str) {
442-
return false;
443-
}
444-
/* ODBC quotes are curly braces */
445-
if (str[0] != '{') {
446-
return false;
447-
}
448-
/* Check for } that aren't doubled up or at the end of the string */
449-
size_t length = strlen(str);
450-
for (size_t i = 0; i < length; i++) {
451-
if (str[i] == '}' && str[i + 1] == '}') {
452-
/* Skip over so we don't count it again */
453-
i++;
454-
} else if (str[i] == '}' && str[i + 1] != '\0') {
455-
/* If not at the end, not quoted */
456-
return false;
457-
}
458-
}
459-
return true;
460-
}
461-
462-
/**
463-
* Determines if a value for a connection string should be quoted.
464-
*
465-
* The ODBC specification mentions:
466-
* "Because of connection string and initialization file grammar, keywords and
467-
* and attribute values that contain the characters []{}(),;?*=!@ not enclosed
468-
* with braces should be avoided."
469-
*
470-
* Note that it assumes that the string is *not* already quoted. You should
471-
* check beforehand.
472-
*/
473-
static bool should_odbc_quote(const char *str)
474-
{
475-
return strpbrk(str, "[]{}(),;?*=!@") != NULL;
476-
}
477-
478-
/**
479-
* Estimates the worst-case scenario for a quoted version of a string's size.
480-
*/
481-
static size_t estimate_odbc_quote_length(const char *in_str)
482-
{
483-
/* Assume all '}'. Include '{,' '}', and the null terminator too */
484-
return (strlen(in_str) * 2) + 3;
485-
}
486-
487-
/**
488-
* Quotes a string with ODBC rules.
489-
*
490-
* Some characters (curly braces, semicolons) are special and must be quoted.
491-
* In the case of '}' in a quoted string, they must be escaped SQL style; that
492-
* is, repeated.
493-
*/
494-
static size_t odbc_quote(char *out_str, const char *in_str, size_t out_str_size)
495-
{
496-
*out_str++ = '{';
497-
out_str_size--;
498-
while (out_str_size > 2) {
499-
if (*in_str == '\0') {
500-
break;
501-
} else if (*in_str == '}' && out_str_size - 1 > 2) {
502-
/* enough room to append */
503-
*out_str++ = '}';
504-
*out_str++ = *in_str++;
505-
out_str_size -= 2;
506-
} else if (*in_str == '}') {
507-
/* not enough, truncate here */
508-
break;
509-
} else {
510-
*out_str++ = *in_str++;
511-
out_str_size--;
512-
}
513-
}
514-
/* append termination */
515-
*out_str++ = '}';
516-
*out_str++ = '\0';
517-
out_str_size -= 2;
518-
/* return how many characters were left */
519-
return strlen(in_str);
520-
}
521-
522433
static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */
523434
{
524435
pdo_odbc_db_handle *H;
@@ -584,28 +495,28 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{
584495
&& !strstr(dbh->data_source, "PWD=");
585496
if (is_uid_set && is_pwd_set) {
586497
char *uid = NULL, *pwd = NULL;
587-
bool should_quote_uid = !is_odbc_quoted(dbh->username) && should_odbc_quote(dbh->username);
588-
bool should_quote_pwd = !is_odbc_quoted(dbh->password) && should_odbc_quote(dbh->password);
498+
bool should_quote_uid = !php_odbc_connstr_is_quoted(dbh->username) && php_odbc_connstr_should_quote(dbh->username);
499+
bool should_quote_pwd = !php_odbc_connstr_is_quoted(dbh->password) && php_odbc_connstr_should_quote(dbh->password);
589500
bool connection_string_fail = false;
590501
if (should_quote_uid) {
591-
size_t estimated_length = estimate_odbc_quote_length(dbh->username);
502+
size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->username);
592503
uid = emalloc(estimated_length);
593504
if (!uid) {
594505
connection_string_fail = true;
595506
goto connection_string_fail;
596507
}
597-
odbc_quote(uid, dbh->username, estimated_length);
508+
php_odbc_connstr_quote(uid, dbh->username, estimated_length);
598509
} else {
599510
uid = dbh->username;
600511
}
601512
if (should_quote_pwd) {
602-
size_t estimated_length = estimate_odbc_quote_length(dbh->password);
513+
size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->password);
603514
pwd = emalloc(estimated_length);
604515
if (!pwd) {
605516
connection_string_fail = true;
606517
goto connection_string_fail;
607518
}
608-
odbc_quote(pwd, dbh->password, estimated_length);
519+
php_odbc_connstr_quote(pwd, dbh->password, estimated_length);
609520
} else {
610521
pwd = dbh->password;
611522
}

0 commit comments

Comments
 (0)