Skip to content

PHPC-229: Support options array as 2nd argument to Manager ctor #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 85 additions & 29 deletions php_phongo.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "mongoc-read-prefs-private.h"
#include "mongoc-bulk-operation-private.h"
#include "mongoc-write-concern-private.h"
#include "mongoc-uri-private.h"
#include "mongoc-trace.h"


Expand Down Expand Up @@ -1495,41 +1496,62 @@ void php_phongo_cursor_to_zval(zval *retval, php_phongo_cursor_t *cursor) /* {{{
/* }}} */


mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptions TSRMLS_DC) /* {{{ */
mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS_DC) /* {{{ */
{
zval **tmp;
php_stream_context *ctx;
const char *mech;
const mongoc_uri_t *muri;
mongoc_client_t *client = mongoc_client_new(uri);

bson_iter_t iter;
mongoc_uri_t *uri;

ENTRY;
uri = mongoc_uri_new(uri_string);
MONGOC_DEBUG("Connection string: '%s'", uri_string);

if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
convert_to_string(*tmp);
if (options && bson_iter_init(&iter, options)) {
while (bson_iter_next (&iter)) {
const char *key = bson_iter_key(&iter);

zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
}

MONGOC_DEBUG("Creating Manager, phongo-%s[%s] - mongoc-%s, libbson-%s", MONGODB_VERSION_S, MONGODB_STABILITY_S, MONGOC_VERSION_S, BSON_VERSION_S);
MONGOC_DEBUG("Connecting to '%s'", uri);

if (!client) {
RETURN(false);
if (mongoc_uri_option_is_bool(key)) {
mongoc_uri_set_option_as_bool (uri, key, bson_iter_as_bool(&iter));
}
else if (mongoc_uri_option_is_int32(key) && BSON_ITER_HOLDS_INT32(&iter)) {
mongoc_uri_set_option_as_int32 (uri, key, bson_iter_int32 (&iter));
}
else if (mongoc_uri_option_is_utf8(key) && BSON_ITER_HOLDS_UTF8(&iter)) {
mongoc_uri_set_option_as_utf8(uri, key, bson_iter_utf8 (&iter, NULL));
}
else if (BSON_ITER_HOLDS_ARRAY(&iter) && !strcasecmp(key, "hosts")) {
bson_iter_t sub;

bson_iter_recurse(&iter, &sub);
while (bson_iter_next (&sub)) {
if (BSON_ITER_HOLDS_UTF8(&sub)) {
mongoc_uri_parse_host(uri, bson_iter_utf8(&sub, NULL));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler warning:

./php_phongo.c: In function ‘php_phongo_make_uri’:
./php_phongo.c:1526:7: warning: implicit declaration of function ‘mongoc_uri_parse_host’ [-Wimplicit-function-declaration]
       mongoc_uri_parse_host(uri, bson_iter_utf8(&sub, NULL));

I opened mongodb/mongo-c-driver#250

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
}
else if (BSON_ITER_HOLDS_UTF8(&iter)) {
const char *value = bson_iter_utf8 (&iter, NULL);

if (!strcasecmp(key, "username")) {
mongoc_uri_set_username(uri, value);
} else if (!strcasecmp(key, "password")) {
mongoc_uri_set_password(uri, value);
} else if (!strcasecmp(key, "database")) {
mongoc_uri_set_database(uri, value);
} else if (!strcasecmp(key, "authsource")) {
mongoc_uri_set_auth_source(uri, value);
}
}
}
}

if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
ctx = php_stream_context_from_zval(*tmp, 0);
} else {
GET_DEFAULT_CONTEXT();
}
muri = mongoc_client_get_uri(client);
return uri;
} /* }}} */

if (driverOptions && mongoc_uri_get_ssl(muri)) {
void php_phongo_populate_default_ssl_ctx(php_stream_context *ctx, zval *driverOptions) /* {{{ */
{
zval **tmp;

#define SET_STRING_CTX(name) \
if (php_array_exists(driverOptions, name)) { \
if (driverOptions && php_array_exists(driverOptions, name)) { \
zval ztmp; \
zend_bool ctmp_free; \
int ctmp_len; \
Expand All @@ -1542,7 +1564,7 @@ mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptio
#define SET_BOOL_CTX(name, defaultvalue) \
{ \
zval ztmp; \
if (php_array_exists(driverOptions, name)) { \
if (driverOptions && php_array_exists(driverOptions, name)) { \
ZVAL_BOOL(&ztmp, php_array_fetchl_bool(driverOptions, ZEND_STRL(name))); \
php_stream_context_set_option(ctx, "ssl", name, &ztmp); \
} \
Expand All @@ -1567,12 +1589,46 @@ mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptio
SET_STRING_CTX("ciphers");
#undef SET_BOOL_CTX
#undef SET_STRING_CTX
} /* }}} */

mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, zval *driverOptions TSRMLS_DC) /* {{{ */
{
zval **tmp;
php_stream_context *ctx;
const char *mech;
mongoc_client_t *client;

ENTRY;


if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "debug", strlen("debug") + 1, (void**)&tmp) == SUCCESS) {
convert_to_string(*tmp);

zend_alter_ini_entry_ex((char *)PHONGO_DEBUG_INI, sizeof(PHONGO_DEBUG_INI), Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC);
}

if (driverOptions && zend_hash_find(Z_ARRVAL_P(driverOptions), "context", strlen("context") + 1, (void**)&tmp) == SUCCESS) {
ctx = php_stream_context_from_zval(*tmp, 0);
} else {
GET_DEFAULT_CONTEXT();
}

if (mongoc_uri_get_ssl(uri)) {
php_phongo_populate_default_ssl_ctx(ctx, driverOptions);
}

mech = mongoc_uri_get_auth_mechanism(muri);
MONGOC_DEBUG("Creating Manager, phongo-%s[%s] - mongoc-%s, libbson-%s", MONGODB_VERSION_S, MONGODB_STABILITY_S, MONGOC_VERSION_S, BSON_VERSION_S);
client = mongoc_client_new_from_uri(uri);

if (!client) {
RETURN(false);
}


mech = mongoc_uri_get_auth_mechanism(uri);

/* Check if we are doing X509 auth, in which case extract the username (subject) from the cert if no username is provided */
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(muri)) {
if (mech && !strcasecmp(mech, "MONGODB-X509") && !mongoc_uri_get_username(uri)) {
zval **pem;

if (SUCCESS == php_stream_context_get_option(ctx, "ssl", "local_cert", &pem)) {
Expand Down
3 changes: 2 additions & 1 deletion php_phongo.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
void php_phongo_write_concern_to_zval(zval *retval, const mongoc_write_concern_t *write_concern);
void php_phongo_cursor_to_zval(zval *retval, php_phongo_cursor_t *cursor);

mongoc_client_t *php_phongo_make_mongo_client(const char *uri, zval *driverOptions TSRMLS_DC);
mongoc_uri_t *php_phongo_make_uri(const char *uri_string, bson_t *options TSRMLS_DC);
mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, zval *driverOptions TSRMLS_DC);
void php_phongo_objectid_new_from_oid(zval *object, const bson_oid_t *oid TSRMLS_DC);
void php_phongo_cursor_id_new_from_id(zval *object, int64_t cursorid TSRMLS_DC);
void php_phongo_new_utcdatetime_from_epoch(zval *object, int64_t msec_since_epoch TSRMLS_DC);
Expand Down
24 changes: 18 additions & 6 deletions src/MongoDB/Manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,40 @@ PHP_METHOD(Manager, __construct)
{
php_phongo_manager_t *intern;
zend_error_handling error_handling;
char *uri;
int uri_len;
mongoc_uri_t *uri;
char *uri_string;
int uri_string_len;
zval *options = NULL;
bson_t bson_options = BSON_INITIALIZER;
zval *driverOptions = NULL;
(void)return_value; (void)return_value_ptr; (void)return_value_used;


zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
intern = (php_phongo_manager_t *)zend_object_store_get_object(getThis() TSRMLS_CC);

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!a!", &uri, &uri_len, &options, &driverOptions) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a!a!", &uri_string, &uri_string_len, &options, &driverOptions) == FAILURE) {
zend_restore_error_handling(&error_handling TSRMLS_CC);
return;
}
zend_restore_error_handling(&error_handling TSRMLS_CC);


intern->client = php_phongo_make_mongo_client(uri, driverOptions TSRMLS_CC);
if (!intern->client) {
if (options) {
zval_to_bson(options, PHONGO_BSON_NONE, &bson_options, NULL TSRMLS_CC);
}

uri = php_phongo_make_uri (uri_string, &bson_options TSRMLS_CC);
if (uri) {
intern->client = php_phongo_make_mongo_client(uri, driverOptions TSRMLS_CC);
mongoc_uri_destroy(uri);
} else {
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Failed to parse MongoDB URI");
return;
}
if (!intern->client) {
phongo_throw_exception(PHONGO_ERROR_RUNTIME TSRMLS_CC, "%s", "Failed to create Manager from URI");
}

}
/* }}} */
/* {{{ proto MongoDB\Driver\Cursor Manager::executeCommand(string $db, MongoDB\Driver\Command $command[, MongoDB\Driver\ReadPreference $readPreference = null])
Expand Down
51 changes: 51 additions & 0 deletions tests/connect/standalone-ssl-0006.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
--TEST--
Connect to MongoDB with using SSL and default options
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("STANDALONE_SSL"); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, array("ssl" => true, "serverselectiontimeoutms" => 100));


$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(array("my" => "value"));

throws(function() use ($manager, $bulk) {
$retval = $manager->executeBulkWrite(NS, $bulk);
}, "MongoDB\Driver\Exception\SSLConnectionException");



/* Disable all CA and hostname checks */
$opts = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
"allow_self_signed" => true,
),
);
$context = stream_context_create($opts);

$uriopts = array("ssl" => true, "serverselectiontimeoutms" => 100);
$ctxopts = array("context" => $context);
$manager = new MongoDB\Driver\Manager(STANDALONE_SSL, $uriopts, $ctxopts);


$bulk = new MongoDB\Driver\BulkWrite;
$bulk->insert(array("my" => "value"));

$retval = $manager->executeBulkWrite(NS, $bulk);
printf("Inserted %d documents\n", $retval->getInsertedCount());



?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
OK: Got MongoDB\Driver\Exception\SSLConnectionException
Inserted 1 documents
===DONE===

13 changes: 8 additions & 5 deletions tests/manager/manager-debug-001.phpt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--TEST--
MongoDB\Driver\Manager: Constructing invalid manager
MongoDB\Driver\Manager: Writing debug log files
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; CLEANUP(STANDALONE) ?>
--FILE--
Expand All @@ -19,14 +19,17 @@ unlink($file);
rmdir($name);

echo $content[0];
echo $content[1];
echo $content[2];
foreach($content as $line) {
if (strpos($line, "mongoc_bulk_operation_execute")) {
echo $line;
}
}

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
[%s] PHONGO: DEBUG > Creating Manager, phongo-0.%d.%d[%s] - mongoc-1.%s, libbson-1.%s
[%s] PHONGO: DEBUG > Connecting to 'mongodb://%s'
[%s] client: DEBUG > Using custom stream initiator.
[%s] mongoc: TRACE > ENTRY: mongoc_bulk_operation_execute():%d
[%s] mongoc: TRACE > EXIT: mongoc_bulk_operation_execute():%d
===DONE===
5 changes: 2 additions & 3 deletions tests/manager/manager-debug-002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ ini_set("mongodb.debug", "off");
<?php exit(0); ?>
--EXPECTF--
%a
[%s] PHONGO: TRACE > ENTRY: php_phongo_make_mongo_client():%d
[%s] PHONGO: DEBUG > Creating Manager, phongo-0.%d.%d[%s] - mongoc-1.%s, libbson-1.%s
[%s] PHONGO: DEBUG > Connecting to 'mongodb://%s'
[%s] client: DEBUG > Using custom stream initiator.
%a
[%s] PHONGO: DEBUG > Connecting to '%s:%d[mongodb://%s:%d]'
%a
===DONE===
2 changes: 0 additions & 2 deletions tests/manager/manager-debug-003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,5 @@ ini_set("mongodb.debug", "off");
%a
[%s] PHONGO: TRACE > ENTRY: php_phongo_make_mongo_client():%d
[%s] PHONGO: DEBUG > Creating Manager, phongo-0.%d.%d[%s] - mongoc-1.%s, libbson-1.%s
[%s] PHONGO: DEBUG > Connecting to 'mongodb://%s'
[%s] client: DEBUG > Using custom stream initiator.
%a
===DONE===
45 changes: 45 additions & 0 deletions tests/manager/manager-set-uri-options-001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--TEST--
MongoDB\Driver\Manager: Logging into MongoDB using credentials from $options
--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; NEEDS("STANDALONE_AUTH"); ?>
<?php CLEANUP(STANDALONE_AUTH) ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

$url = parse_url(STANDALONE_AUTH);
parse_str($url["query"], $args);


$dsn = sprintf("mongodb://%s:%d/", $url["host"], $url["port"]);
$options = array(
"username" => $url["user"],
"password" => $url["pass"],
) + $args;
$manager = new MongoDB\Driver\Manager($dsn, $options);


$bulk = new MongoDB\Driver\BulkWrite;

$bulk->insert(array("my" => "value"));
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();

printf("Inserted: %d\n", $inserted);


$options["username"] = "not-found-user";
$manager = new MongoDB\Driver\Manager($dsn, $options);
$bulk = new MongoDB\Driver\BulkWrite;

$bulk->insert(array("my" => "value"));
throws(function() use ($manager, $bulk) {
$inserted = $manager->executeBulkWrite(NS, $bulk)->getInsertedCount();
printf("Incorrectly inserted: %d\n", $inserted);
}, "MongoDB\Driver\Exception\AuthenticationException");
?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
Inserted: 1
OK: Got MongoDB\Driver\Exception\AuthenticationException
===DONE===
Loading