Skip to content

Commit a7881df

Browse files
SjonHortensiusnikic
authored andcommitted
PDO: support username & password specified in DSN
1 parent 7f1fef9 commit a7881df

File tree

7 files changed

+107
-8
lines changed

7 files changed

+107
-8
lines changed

UPGRADING

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ PHP 7.4 UPGRADE NOTES
250250
PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL flags. This influences the
251251
format of the matches array passed to to the callback function.
252252

253+
- PDO:
254+
. The username and password can now be specified as part of the PDO DSN for
255+
the mysql, mssql, sybase, dblib, firebird and oci drivers. Previously this
256+
was only supported by the pgsql driver. If a username/password is specified
257+
both in the constructor and the DSN, the constructor takes precedence.
258+
259+
new PDO("mysql:host=xxx;port=xxx;dbname=xxx;user=xxx;password=xxx");
260+
253261
- PDO_OCI:
254262
. PDOStatement::getColumnMeta() is now available
255263

appveyor/test_task.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ set PDO_MYSQL_TEST_USER=%MYSQL_TEST_USER%
2727
set PDO_MYSQL_TEST_PASS=%MYSQL_PWD%
2828
set PDO_MYSQL_TEST_HOST=%MYSQL_TEST_HOST%
2929
set PDO_MYSQL_TEST_PORT=%MYSQL_TEST_PORT%
30-
set PDO_MYSQL_TEST_DSN=mysql:host=%PDO_MYSQL_TEST_HOST%;port=%PDO_MYSQL_TEST_PORT%;dbname=test;user=%PDO_MYSQL_TEST_USER%;password=%MYSQL_PW%
30+
set PDO_MYSQL_TEST_DSN=mysql:host=%PDO_MYSQL_TEST_HOST%;port=%PDO_MYSQL_TEST_PORT%;dbname=test
3131
"C:\Program Files\MySql\MySQL Server 5.7\bin\mysql.exe" --user=%MYSQL_TEST_USER% -e "CREATE DATABASE IF NOT EXISTS test"
3232
if %errorlevel% neq 0 exit /b 3
3333

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
PDO Common: Pass credentials in dsn instead of constructor params
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo')) die('skip');
6+
$dir = getenv('REDIR_TEST_DIR');
7+
if (false == $dir) die('skip no driver');
8+
9+
$driver = substr(getenv('PDOTEST_DSN'), 0, strpos(getenv('PDOTEST_DSN'), ':'));
10+
if (!in_array($driver, array('mssql','sybase','dblib','firebird','mysql','oci')))
11+
die('skip not supported');
12+
13+
require_once $dir . 'pdo_test.inc';
14+
PDOTest::skip();
15+
?>
16+
--FILE--
17+
<?php
18+
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
19+
20+
$orgDsn = getenv('PDOTEST_DSN');
21+
$orgUser = getenv('PDOTEST_USER');
22+
$orgPass = getenv('PDOTEST_PASS');
23+
24+
try
25+
{
26+
putenv("PDOTEST_DSN=$orgDsn;user=$orgUser;password=$orgPass");
27+
putenv("PDOTEST_USER");
28+
putenv("PDOTEST_PASS");
29+
30+
$link = PDOTest::factory();
31+
echo "using credentials in dsn: done\n";
32+
33+
34+
// test b/c - credentials in DSN are ignored when user/pass passed as separate params
35+
putenv("PDOTEST_DSN=$orgDsn;user=incorrect;password=ignored");
36+
putenv("PDOTEST_USER=$orgUser");
37+
putenv("PDOTEST_PASS=$orgPass");
38+
39+
$link = PDOTest::factory();
40+
echo "ignoring credentials in dsn: done\n";
41+
}
42+
finally
43+
{
44+
putenv("PDOTEST_DSN=$orgDsn");
45+
putenv("PDOTEST_USER=$orgUser");
46+
putenv("PDOTEST_PASS=$orgPass");
47+
}
48+
?>
49+
--EXPECTF--
50+
using credentials in dsn: done
51+
ignoring credentials in dsn: done

ext/pdo_dblib/dblib_driver.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,8 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
458458
,{ "dbname", NULL, 0 }
459459
,{ "secure", NULL, 0 } /* DBSETLSECURE */
460460
,{ "version", NULL, 0 } /* DBSETLVERSION */
461+
,{ "user", NULL, 0 }
462+
,{ "password", NULL, 0 }
461463
};
462464

463465
nvars = sizeof(vars)/sizeof(vars[0]);
@@ -519,12 +521,20 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
519521
}
520522
}
521523

524+
if (!dbh->username && vars[6].optval) {
525+
dbh->username = vars[6].optval;
526+
}
527+
522528
if (dbh->username) {
523529
if(FAIL == DBSETLUSER(H->login, dbh->username)) {
524530
goto cleanup;
525531
}
526532
}
527533

534+
if (!dbh->password && vars[7].optval) {
535+
dbh->password = vars[7].optval;
536+
}
537+
528538
if (dbh->password) {
529539
if(FAIL == DBSETLPWD(H->login, dbh->password)) {
530540
goto cleanup;

ext/pdo_firebird/firebird_driver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,14 +623,24 @@ static int pdo_firebird_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /*
623623
struct pdo_data_src_parser vars[] = {
624624
{ "dbname", NULL, 0 },
625625
{ "charset", NULL, 0 },
626-
{ "role", NULL, 0 }
626+
{ "role", NULL, 0 },
627+
{ "user", NULL, 0 },
628+
{ "password", NULL, 0 }
627629
};
628630
int i, ret = 0;
629631
short buf_len = 256, dpb_len;
630632

631633
pdo_firebird_db_handle *H = dbh->driver_data = pecalloc(1,sizeof(*H),dbh->is_persistent);
632634

633-
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 3);
635+
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
636+
637+
if (!dbh->username && vars[3].optval) {
638+
dbh->username = vars[3].optval;
639+
}
640+
641+
if (!dbh->password && vars[4].optval) {
642+
dbh->password = vars[4].optval;
643+
}
634644

635645
do {
636646
static char const dpb_flags[] = {

ext/pdo_mysql/mysql_driver.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -568,9 +568,11 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
568568
struct pdo_data_src_parser vars[] = {
569569
{ "charset", NULL, 0 },
570570
{ "dbname", "", 0 },
571-
{ "host", "localhost", 0 },
572-
{ "port", "3306", 0 },
571+
{ "host", "localhost", 0 },
572+
{ "port", "3306", 0 },
573573
{ "unix_socket", PDO_DEFAULT_MYSQL_UNIX_ADDR, 0 },
574+
{ "user", NULL, 0 },
575+
{ "password", NULL, 0 },
574576
};
575577
int connect_opts = 0
576578
#ifdef CLIENT_MULTI_RESULTS
@@ -596,7 +598,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
596598
PDO_DBG_INF("multi results");
597599
#endif
598600

599-
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
601+
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 7);
600602

601603
H = pecalloc(1, sizeof(pdo_mysql_db_handle), dbh->is_persistent);
602604

@@ -808,6 +810,14 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
808810
unix_socket = vars[4].optval;
809811
}
810812

813+
if (!dbh->username && vars[5].optval) {
814+
dbh->username = vars[5].optval;
815+
}
816+
817+
if (!dbh->password && vars[6].optval) {
818+
dbh->password = vars[6].optval;
819+
}
820+
811821
/* TODO: - Check zval cache + ZTS */
812822
#ifdef PDO_USE_MYSQLND
813823
if (dbname) {

ext/pdo_oci/oci_driver.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,10 +678,12 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
678678
int i, ret = 0;
679679
struct pdo_data_src_parser vars[] = {
680680
{ "charset", NULL, 0 },
681-
{ "dbname", "", 0 }
681+
{ "dbname", "", 0 },
682+
{ "user", NULL, 0 },
683+
{ "password", NULL, 0 }
682684
};
683685

684-
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 2);
686+
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 4);
685687

686688
H = pecalloc(1, sizeof(*H), dbh->is_persistent);
687689
dbh->driver_data = H;
@@ -745,6 +747,10 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
745747
}
746748

747749
/* username */
750+
if (!dbh->username && vars[2].optval) {
751+
dbh->username = vars[2].optval;
752+
}
753+
748754
if (dbh->username) {
749755
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
750756
dbh->username, (ub4) strlen(dbh->username),
@@ -756,6 +762,10 @@ static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ *
756762
}
757763

758764
/* password */
765+
if (!dbh->password && vars[3].optval) {
766+
dbh->password = vars[3].optval;
767+
}
768+
759769
if (dbh->password) {
760770
H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
761771
dbh->password, (ub4) strlen(dbh->password),

0 commit comments

Comments
 (0)