Beispiel #1
0
static mongoc_cursor_t *
query_collection (mongoc_collection_t *collection, uint32_t last_time)
{
   mongoc_cursor_t *cursor;
   bson_t query;
   bson_t gt;
   bson_t opts;

   BSON_ASSERT (collection);

   bson_init (&query);
   BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
   BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
   bson_append_document_end (&query, &gt);

   bson_init (&opts);
   BSON_APPEND_BOOL (&opts, "tailable", true);
   BSON_APPEND_BOOL (&opts, "awaitData", true);

   cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);

   bson_destroy (&query);
   bson_destroy (&opts);

   return cursor;
}
Beispiel #2
0
SEXP R_mongo_collection_find(SEXP ptr_col, SEXP ptr_query, SEXP ptr_opts) {
  mongoc_collection_t *col = r2col(ptr_col);
  bson_t *query = r2bson(ptr_query);
  bson_t *opts = r2bson(ptr_opts);
  mongoc_cursor_t *c = mongoc_collection_find_with_opts(col, query, opts, NULL);
  return cursor2r(c, ptr_col);
}
static future_t *
find (func_ctx_t *ctx, bson_t *cmd)
{
   BSON_APPEND_UTF8 (cmd, "find", "collection");
   ctx->cursor = mongoc_collection_find_with_opts (
      ctx->collection, tmp_bson ("{}"), ctx->opts, ctx->prefs);

   /* use ctx->data as the bson_t** out-param to mongoc_cursor_next () */
   return future_cursor_next (ctx->cursor, (const bson_t **) &ctx->data);
}
/* test that we add readConcern only inside $query, not outside it too */
static void
test_mongos_read_concern (void)
{
   mock_server_t *server;
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_read_prefs_t *prefs;
   mongoc_cursor_t *cursor;
   const bson_t *doc;
   future_t *future;
   request_t *request;

   server = mock_mongos_new (WIRE_VERSION_READ_CONCERN);
   mock_server_run (server);
   client = mongoc_client_new_from_uri (mock_server_get_uri (server));
   collection = mongoc_client_get_collection (client, "test", "test");
   prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
   cursor = mongoc_collection_find_with_opts (
      collection,
      tmp_bson ("{'a': 1}"),
      tmp_bson ("{'readConcern': {'level': 'foo'}}"),
      prefs);

   future = future_cursor_next (cursor, &doc);
   request = mock_server_receives_command (
      server,
      "test",
      MONGOC_QUERY_SLAVE_OK,
      "{"
      "  '$query': {"
      "    'find': 'test', 'filter': {}, 'readConcern': {'level': 'foo'}"
      "  },"
      "  '$readPreference': {"
      "    'mode': 'secondary'"
      "  },"
      "  'readConcern': {'$exists': false}"
      "}");

   mock_server_replies_to_find (
      request, MONGOC_QUERY_SLAVE_OK, 0, 1, "db.collection", "{}", true);

   /* mongoc_cursor_next returned true */
   BSON_ASSERT (future_get_bool (future));

   request_destroy (request);
   future_destroy (future);
   mongoc_cursor_destroy (cursor);
   mongoc_read_prefs_destroy (prefs);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mock_server_destroy (server);
}
Beispiel #5
0
int be_mongo_getuser(void *handle, const char *username, const char *password, char **phash, const char *clientid)
{
	struct mongo_backend *conf = (struct mongo_backend *)handle;
	mongoc_collection_t *collection;
	mongoc_cursor_t *cursor;
	bson_error_t error;
	const bson_t *doc;
	bson_iter_t iter;
	bson_t query;
	char *result = NULL;

	bson_init (&query);

	bson_append_utf8 (&query, conf->user_username_prop, -1, username, -1);

	collection = mongoc_client_get_collection (conf->client, conf->database, conf->user_coll);
	cursor = mongoc_collection_find_with_opts(collection, &query, NULL, NULL);

	if (!mongoc_cursor_error (cursor, &error) &&
		mongoc_cursor_next (cursor, &doc)) {

		bson_iter_init(&iter, doc);
		if (bson_iter_find(&iter, conf->user_password_prop)) {
			const char *password_src = bson_iter_utf8(&iter, NULL);
			size_t password_len = strlen(password_src) + 1;
			result = (char *) malloc(password_len);
			memcpy(result, password_src, password_len);
		} else {
			_log(LOG_NOTICE, "[mongo] (%s) missing for user (%s)", conf->user_password_prop, username);
		}
	}

	if (mongoc_cursor_error (cursor, &error)) {
		fprintf (stderr, "Cursor Failure: %s\n", error.message);
	}

	bson_destroy (&query);
	mongoc_cursor_destroy (cursor);
	mongoc_collection_destroy (collection);

	*phash = result;
	return BACKEND_DEFER;
}
Beispiel #6
0
static void
test_exhaust (void)
{
   mock_server_t *server;
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   request_t *request;
   future_t *future;
   const bson_t *doc;
   bson_error_t error;

   server = mock_server_with_autoismaster (WIRE_VERSION_FIND_CMD);
   mock_server_run (server);
   client = mongoc_client_new_from_uri (mock_server_get_uri (server));
   collection = mongoc_client_get_collection (client, "db", "collection");
   cursor = mongoc_collection_find_with_opts (collection,
                                              tmp_bson (NULL),
                                              NULL,
                                              tmp_bson ("{'exhaust': true}"));

   future = future_cursor_next (cursor, &doc);

   /* Find, getMore and killCursors commands spec: "The find command does not
    * support the exhaust flag from OP_QUERY. Drivers that support exhaust MUST
    * fallback to existing OP_QUERY wire protocol messages."
    */
   request = mock_server_receives_request (server);
   mock_server_replies_to_find (
      request, MONGOC_QUERY_SLAVE_OK | MONGOC_QUERY_EXHAUST,
      0, 0, "db.collection", "{}", false /* is_command */);

   ASSERT (future_get_bool (future));
   ASSERT_OR_PRINT (!mongoc_cursor_error (cursor, &error), error);

   request_destroy (request);
   future_destroy (future);
   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mock_server_destroy (server);
}
Beispiel #7
0
mongoc_gridfs_file_list_t *
_mongoc_gridfs_file_list_new_with_opts (mongoc_gridfs_t *gridfs,
                                        const bson_t *filter,
                                        const bson_t *opts)
{
   mongoc_gridfs_file_list_t *list;
   mongoc_cursor_t *cursor;

   cursor = mongoc_collection_find_with_opts (
      gridfs->files, filter, opts, NULL /* read prefs */);

   BSON_ASSERT (cursor);

   list = (mongoc_gridfs_file_list_t *) bson_malloc0 (sizeof *list);

   list->cursor = cursor;
   list->gridfs = gridfs;

   return list;
}
Beispiel #8
0
static void
_test_collection_op_query_or_find_command (
   test_collection_find_with_opts_t *test_data,
   check_request_fn_t                check_request_fn,
   const char                       *reply_json,
   int32_t                           max_wire_version)
{
   mock_server_t *server;
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   bson_error_t error;
   future_t *future;
   request_t *request;
   const bson_t *doc;

   server = mock_server_with_autoismaster (max_wire_version);
   mock_server_run (server);
   client = mongoc_client_new_from_uri (mock_server_get_uri (server));
   collection = mongoc_client_get_collection (client, "db", "collection");
   cursor = mongoc_collection_find_with_opts (collection,
                                              test_data->filter_bson,
                                              test_data->read_prefs,
                                              test_data->opts_bson);

   ASSERT_OR_PRINT (!mongoc_cursor_error (cursor, &error), error);
   future = future_cursor_next (cursor, &doc);
   request = check_request_fn (server, test_data);
   ASSERT (request);
   mock_server_replies_simple (request, reply_json);
   ASSERT (future_get_bool (future));

   request_destroy (request);
   future_destroy (future);
   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mock_server_destroy (server);
}
Beispiel #9
0
int be_mongo_superuser(void *conf, const char *username)
{
	struct mongo_backend *handle = (struct mongo_backend *) conf;
	mongoc_collection_t *collection;
	mongoc_cursor_t *cursor;
	bson_error_t error;
	const bson_t *doc;
	int result = 0;

	bson_t query;
	bson_iter_t iter;
	bson_init (&query);
	bson_append_utf8(&query, handle->user_username_prop, -1, username, -1);

	collection = mongoc_client_get_collection(handle->client, handle->database, handle->user_coll);

	cursor = mongoc_collection_find_with_opts(collection, &query, NULL, NULL);

	if (!mongoc_cursor_error (cursor, &error) &&
		mongoc_cursor_next (cursor, &doc)) {
		bson_iter_init(&iter, doc);
		if (bson_iter_find(&iter, handle->user_superuser_prop)) {
			result = bson_iter_as_bool(&iter) ? 1 : 0;
		}
	}

	if (mongoc_cursor_error (cursor, &error)) {
		fprintf(stderr, "Cursor Failure: %s\n", error.message);
	}

	bson_destroy (&query);
	mongoc_cursor_destroy (cursor);
	mongoc_collection_destroy (collection);

	return (result) ? BACKEND_ALLOW : BACKEND_DEFER;
}
Beispiel #10
0
int
main (int argc, char *argv[])
{
   mongoc_client_t *client = NULL;
   mongoc_database_t *database = NULL;
   mongoc_collection_t *collection = NULL;
   mongoc_cursor_t *cursor = NULL;
   bson_error_t error;
   const char *uristr = "mongodb://127.0.0.1/";
   const char *authuristr;
   bson_t roles;
   bson_t query;
   const bson_t *doc;

   if (argc != 2) {
      printf ("%s - [implicit|scram]\n", argv[0]);
      return 1;
   }

   if (strcmp (argv[1], "implicit") == 0) {
      authuristr = "mongodb://user,=:[email protected]/test?appname=scram-example";
   } else if (strcmp (argv[1], "scram") == 0) {
      authuristr = "mongodb://user,=:[email protected]/"
                   "test?appname=scram-example&authMechanism=SCRAM-SHA-1";
   } else {
      printf ("%s - [implicit|scram]\n", argv[0]);
      return 1;
   }

   mongoc_init ();

   client = mongoc_client_new (uristr);

   if (!client) {
      fprintf (stderr, "Failed to parse URI.\n");
      return EXIT_FAILURE;
   }

   mongoc_client_set_error_api (client, 2);

   database = mongoc_client_get_database (client, "test");

   bson_init (&roles);
   bson_init (&query);

   BCON_APPEND (&roles, "0", "{", "role", "root", "db", "admin", "}");

   mongoc_database_add_user (database, "user,=", "pass", &roles, NULL, &error);

   mongoc_database_destroy (database);

   mongoc_client_destroy (client);

   client = mongoc_client_new (authuristr);

   if (!client) {
      fprintf (stderr, "failed to parse SCRAM uri\n");
      goto CLEANUP;
   }

   mongoc_client_set_error_api (client, 2);

   collection = mongoc_client_get_collection (client, "test", "test");

   cursor = mongoc_collection_find_with_opts (collection, &query, NULL, NULL);

   mongoc_cursor_next (cursor, &doc);

   if (mongoc_cursor_error (cursor, &error)) {
      fprintf (stderr, "Auth error: %s\n", error.message);
      goto CLEANUP;
   }

CLEANUP:

   bson_destroy (&roles);
   bson_destroy (&query);

   if (collection) {
      mongoc_collection_destroy (collection);
   }

   if (client) {
      mongoc_client_destroy (client);
   }

   if (cursor) {
      mongoc_cursor_destroy (cursor);
   }

   mongoc_cleanup ();

   return EXIT_SUCCESS;
}
Beispiel #11
0
static void
test_getmore_cmd_await (void)
{
   bson_t *opts;
   mock_server_t *server;
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   future_t *future;
   request_t *request;
   const bson_t *doc;

   opts = tmp_bson ("{'tailable': true,"
                    " 'awaitData': true,"
                    " 'maxAwaitTimeMS': {'$numberLong': '9999'}}");

   /*
    * "find" command
    */
   server = mock_server_with_autoismaster (WIRE_VERSION_FIND_CMD);
   mock_server_run (server);
   client = mongoc_client_new_from_uri (mock_server_get_uri (server));
   collection = mongoc_client_get_collection (client, "db", "collection");
   cursor = mongoc_collection_find_with_opts (collection, tmp_bson (NULL),
                                              NULL, opts);

   future = future_cursor_next (cursor, &doc);
   request = mock_server_receives_command (
      server, "db", MONGOC_QUERY_SLAVE_OK,
      "{'find': 'collection', 'filter': {}}");

   ASSERT (request);
   mock_server_replies_simple (request, "{'ok': 1,"
                                        " 'cursor': {"
                                        "    'id': {'$numberLong': '123'},"
                                        "    'ns': 'db.collection',"
                                        "    'firstBatch': [{}]}}");

   ASSERT (future_get_bool (future));
   request_destroy (request);
   future_destroy (future);

   /*
    * "getMore" command
    */
   future = future_cursor_next (cursor, &doc);
   request = mock_server_receives_command (
      server, "db", MONGOC_QUERY_SLAVE_OK,
      "{'getMore': {'$numberLong': '123'},"
      " 'collection': 'collection',"
      " 'maxTimeMS': {'$numberLong': '9999'}}}");

   ASSERT (request);
   mock_server_replies_simple (request, "{'ok': 1,"
                                        " 'cursor': {"
                                        "    'id': {'$numberLong': '0'},"
                                        "    'ns': 'db.collection',"
                                        "    'nextBatch': [{}]}}");

   ASSERT (future_get_bool (future));

   request_destroy (request);
   future_destroy (future);
   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   mock_server_destroy (server);
}
bool map_reduce_basic (mongoc_database_t* database)
{
   bson_t reply;
   bson_t* command;
   bool res;
   bson_error_t error;
   mongoc_cursor_t* cursor;
   const bson_t* doc;

   bool map_reduce_done = false;
   bool query_done = false;

   const char* out_collection_name = "outCollection";
   mongoc_collection_t* out_collection;

   /* Empty find query */
   bson_t find_query = BSON_INITIALIZER;

   /* Construct the mapReduce command */

   /* Other arguments can also be specified here, like "query" or
      "limit" and so on */
   command = BCON_NEW ("mapReduce", BCON_UTF8 (COLLECTION_NAME),
                       "map", BCON_CODE (MAPPER),
                       "reduce", BCON_CODE (REDUCER),
                       "out", BCON_UTF8 (out_collection_name));
   res = mongoc_database_command_simple (database, command, NULL,
                                        &reply, &error);
   map_reduce_done = true;

   if (!res) {
      fprintf (stderr, "MapReduce failed: %s\n", error.message);
      goto cleanup;
   }

   /* Do something with the reply (it doesn't contain the mapReduce results) */
   print_res (&reply);

   /* Now we'll query outCollection to see what the results are */
   out_collection = mongoc_database_get_collection (database,
                                                    out_collection_name);
   cursor = mongoc_collection_find_with_opts (out_collection, &find_query,
                                              NULL, NULL);
   query_done = true;

   /* Do something with the results */
   while (mongoc_cursor_next (cursor, &doc)) {
      print_res (doc);
   }

   if (mongoc_cursor_error (cursor, &error)) {
      fprintf (stderr, "ERROR: %s\n", error.message);
      res = false;
      goto cleanup;
   }

cleanup:
   /* cleanup */
   if (query_done) {
      mongoc_cursor_destroy (cursor);
      mongoc_collection_destroy (out_collection);
   }

   if (map_reduce_done) {
      bson_destroy (&reply);
      bson_destroy (command);
   }

   return res;
}
int
main (int argc, char *argv[])
{
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   bson_error_t error;
   const bson_t *doc;
   const char *collection_name = "test";
   bson_t query;
   char *str;
   const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
   mongoc_uri_t *uri;

   mongoc_init ();

   if (argc > 1) {
      uri_string = argv[1];
   }

   if (argc > 2) {
      collection_name = argv[2];
   }

   uri = mongoc_uri_new_with_error (uri_string, &error);
   if (!uri) {
      fprintf (stderr,
               "failed to parse URI: %s\n"
               "error message:       %s\n",
               uri_string,
               error.message);
      return EXIT_FAILURE;
   }

   client = mongoc_client_new_from_uri (uri);
   if (!client) {
      return EXIT_FAILURE;
   }

   mongoc_client_set_error_api (client, 2);

   bson_init (&query);

#if 0
   bson_append_utf8 (&query, "hello", -1, "world", -1);
#endif

   collection = mongoc_client_get_collection (client, "test", collection_name);
   cursor = mongoc_collection_find_with_opts (
      collection,
      &query,
      NULL,  /* additional options */
      NULL); /* read prefs, NULL for default */

   while (mongoc_cursor_next (cursor, &doc)) {
      str = bson_as_canonical_extended_json (doc, NULL);
      fprintf (stdout, "%s\n", str);
      bson_free (str);
   }

   if (mongoc_cursor_error (cursor, &error)) {
      fprintf (stderr, "Cursor Failure: %s\n", error.message);
      return EXIT_FAILURE;
   }

   bson_destroy (&query);
   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);
   mongoc_uri_destroy (uri);
   mongoc_client_destroy (client);
   mongoc_cleanup ();

   return EXIT_SUCCESS;
}
static mongoc_cursor_t *
find (mongoc_collection_t *collection, mongoc_read_prefs_t *prefs)
{
   return mongoc_collection_find_with_opts (
      collection, tmp_bson ("{}"), NULL /* opts */, prefs);
}
Beispiel #15
0
int
main (int argc, char *argv[])
{
   int exit_code = EXIT_FAILURE;

   mongoc_client_t *client;
   mongoc_client_session_t *client_session = NULL;
   mongoc_collection_t *collection = NULL;
   const char *uristr = "mongodb://127.0.0.1/?appname=session-example";
   bson_error_t error;
   bson_t *selector = NULL;
   bson_t *update = NULL;
   bson_t *update_opts = NULL;
   bson_t *find_opts = NULL;
   mongoc_read_prefs_t *secondary = NULL;
   mongoc_cursor_t *cursor = NULL;
   const bson_t *doc;
   char *str;
   bool r;

   mongoc_init ();

   if (argc > 1) {
      uristr = argv[1];
   }

   client = mongoc_client_new (uristr);

   if (!client) {
      fprintf (stderr, "Failed to parse URI.\n");
      goto done;
   }

   mongoc_client_set_error_api (client, 2);

   /* pass NULL for options - by default the session is causally consistent */
   client_session = mongoc_client_start_session (client, NULL, &error);
   if (!client_session) {
      fprintf (stderr, "Failed to start session: %s\n", error.message);
      goto done;
   }

   collection = mongoc_client_get_collection (client, "test", "collection");
   selector = BCON_NEW ("_id", BCON_INT32 (1));
   update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
   update_opts = bson_new ();
   if (!mongoc_client_session_append (client_session, update_opts, &error)) {
      fprintf (stderr, "Could not add session to opts: %s\n", error.message);
      goto done;
   }

   r = mongoc_collection_update_one (
      collection, selector, update, update_opts, NULL /* reply */, &error);

   if (!r) {
      fprintf (stderr, "Update failed: %s\n", error.message);
      goto done;
   }

   bson_destroy (selector);
   selector = BCON_NEW ("_id", BCON_INT32 (1));
   secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);

   find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
   if (!mongoc_client_session_append (client_session, find_opts, &error)) {
      fprintf (stderr, "Could not add session to opts: %s\n", error.message);
      goto done;
   };

   /* read from secondary. since we're in a causally consistent session, the
    * data is guaranteed to reflect the update we did on the primary. the query
    * blocks waiting for the secondary to catch up, if necessary, or times out
    * and fails after 2000 ms.
    */
   cursor = mongoc_collection_find_with_opts (
      collection, selector, find_opts, secondary);

   bson_destroy (selector);
   mongoc_read_prefs_destroy (secondary);
   bson_destroy (find_opts);

   while (mongoc_cursor_next (cursor, &doc)) {
      str = bson_as_json (doc, NULL);
      fprintf (stdout, "%s\n", str);
      bson_free (str);
   }

   if (mongoc_cursor_error (cursor, &error)) {
      fprintf (stderr, "Cursor Failure: %s\n", error.message);
      goto done;
   }

   exit_code = EXIT_SUCCESS;

done:
   if (find_opts) {
      bson_destroy (find_opts);
   }
   if (update) {
      bson_destroy (update);
   }
   if (selector) {
      bson_destroy (selector);
   }
   if (update_opts) {
      bson_destroy (update_opts);
   }
   if (secondary) {
      mongoc_read_prefs_destroy (secondary);
   }
   /* destroy cursor, collection, session before the client they came from */
   if (cursor) {
      mongoc_cursor_destroy (cursor);
   }
   if (collection) {
      mongoc_collection_destroy (collection);
   }
   if (client_session) {
      mongoc_client_session_destroy (client_session);
   }
   if (client) {
      mongoc_client_destroy (client);
   }

   mongoc_cleanup ();

   return exit_code;
}
Beispiel #16
0
int be_mongo_aclcheck(void *conf, const char *clientid, const char *username, const char *topic, int acc)
{
	struct mongo_backend *handle = (struct mongo_backend *) conf;
	mongoc_collection_t *collection;
	mongoc_cursor_t *cursor;
	bson_error_t error;
	const bson_t *doc;
	bson_iter_t iter;
	int match = 0;
	const bson_oid_t *topic_lookup_oid = NULL;
	const char *topic_lookup_utf8 = NULL;
	int64_t topic_lookup_int64 = 0;

	bson_t query;

	bson_init(&query);
	bson_append_utf8(&query, handle->user_username_prop, -1, username, -1);

	collection = mongoc_client_get_collection(handle->client, handle->database, handle->user_coll);

	cursor = mongoc_collection_find_with_opts(collection, &query, NULL, NULL);

	if (!mongoc_cursor_error (cursor, &error) && mongoc_cursor_next (cursor, &doc)) {
		// First find any user[handle->user_topiclist_fk_prop]
		if (bson_iter_init_find(&iter, doc, handle->user_topiclist_fk_prop)) {
			bson_type_t loc_id_type = bson_iter_type(&iter);
			if (loc_id_type == BSON_TYPE_OID) {
				topic_lookup_oid = bson_iter_oid(&iter);
			} else if (loc_id_type == BSON_TYPE_INT32 || loc_id_type == BSON_TYPE_INT64) {
				topic_lookup_int64 = bson_iter_as_int64(&iter);
			} else if (loc_id_type == BSON_TYPE_UTF8) {
				topic_lookup_utf8 = bson_iter_utf8(&iter, NULL);
			}
		}

		// Look through the props from the beginning for user[handle->user_topics_prop]
		if (bson_iter_init_find(&iter, doc, handle->user_topics_prop)) {
			bson_type_t embedded_prop_type = bson_iter_type(&iter);
			if (embedded_prop_type == BSON_TYPE_ARRAY) {
				match = be_mongo_check_acl_topics_array(&iter, topic, clientid, username);
			} else if (embedded_prop_type == BSON_TYPE_DOCUMENT) {
				match = be_mongo_check_acl_topics_map(&iter, topic, acc, clientid, username);
			}
		}
	}

	if ((mongoc_cursor_error (cursor, &error)) && (match != 1)) {
		fprintf (stderr, "Cursor Failure: %s\n", error.message);
	}

	bson_destroy(&query);
	mongoc_cursor_destroy (cursor);
	mongoc_collection_destroy(collection);

	if (!match && (topic_lookup_oid != NULL || topic_lookup_int64 != 0 || topic_lookup_utf8 != NULL)) {
		bson_init(&query);
		if (topic_lookup_oid != NULL) {
			bson_append_oid(&query, handle->topiclist_key_prop, -1, topic_lookup_oid);
		} else if (topic_lookup_int64 != 0) {
			bson_append_int64(&query, handle->topiclist_key_prop, -1, topic_lookup_int64);
		} else if (topic_lookup_utf8 != NULL) {
			bson_append_utf8(&query, handle->topiclist_key_prop, -1, topic_lookup_utf8, -1);
		}
		collection = mongoc_client_get_collection(handle->client, handle->database, handle->topiclist_coll);
		cursor = mongoc_collection_find_with_opts(collection, &query, NULL, NULL);


		if (!mongoc_cursor_error (cursor, &error) && mongoc_cursor_next(cursor, &doc)) {

			bson_iter_init(&iter, doc);
			if (bson_iter_find(&iter, handle->topiclist_topics_prop)) {
				bson_type_t loc_prop_type = bson_iter_type(&iter);
				if (loc_prop_type == BSON_TYPE_ARRAY) {
					match = be_mongo_check_acl_topics_array(&iter, topic, clientid, username);
				} else if (loc_prop_type == BSON_TYPE_DOCUMENT) {
					match = be_mongo_check_acl_topics_map(&iter, topic, acc, clientid, username);
				}
			} else {
				_log(LOG_NOTICE, "[mongo] ACL check error - no topic list found for user (%s) in collection (%s)", username, handle->topiclist_coll);
			}
		}

		if ((mongoc_cursor_error (cursor, &error)) && (match != 1)) {
			fprintf (stderr, "Cursor Failure: %s\n", error.message);
		}

		bson_destroy(&query);
		mongoc_cursor_destroy(cursor);
		mongoc_collection_destroy(collection);
	}

	return (match) ? BACKEND_ALLOW : BACKEND_DEFER;
}
Beispiel #17
0
/**
 * _mongoc_gridfs_file_refresh_page:
 *
 *    Refresh a GridFS file's underlying page. This recalculates the current
 *    page number based on the file's stream position, then fetches that page
 *    from the database.
 *
 *    Note that this fetch is unconditional and the page is queried from the
 *    database even if the current page covers the same theoretical chunk.
 *
 *
 * Side Effects:
 *
 *    file->page is loaded with the appropriate buffer, fetched from the
 *    database. If the file position is at the end of the file and on a new
 *    chunk boundary, a new page is created. If the position is far past the
 *    end of the file, _mongoc_gridfs_file_extend is responsible for creating
 *    chunks to file the gap.
 *
 *    file->n is set based on file->pos. file->error is set on error.
 */
static bool
_mongoc_gridfs_file_refresh_page (mongoc_gridfs_file_t *file)
{
   bson_t query;
   bson_t child;
   bson_t opts;
   const bson_t *chunk;
   const char *key;
   bson_iter_t iter;
   int64_t existing_chunks;
   int64_t required_chunks;

   const uint8_t *data = NULL;
   uint32_t len;

   ENTRY;

   BSON_ASSERT (file);

   file->n = (int32_t) (file->pos / file->chunk_size);

   if (file->page) {
      _mongoc_gridfs_file_page_destroy (file->page);
      file->page = NULL;
   }

   /* if the file pointer is past the end of the current file (i.e. pointing to
    * a new chunk), we'll pass the page constructor a new empty page. */
   existing_chunks = divide_round_up (file->length, file->chunk_size);
   required_chunks = divide_round_up (file->pos + 1, file->chunk_size);
   if (required_chunks > existing_chunks) {
      data = (uint8_t *) "";
      len = 0;
   } else {
      /* if we have a cursor, but the cursor doesn't have the chunk we're going
       * to need, destroy it (we'll grab a new one immediately there after) */
      if (file->cursor && !_mongoc_gridfs_file_keep_cursor (file)) {
         mongoc_cursor_destroy (file->cursor);
         file->cursor = NULL;
      }

      if (!file->cursor) {
         bson_init (&query);
         BSON_APPEND_VALUE (&query, "files_id", &file->files_id);
         BSON_APPEND_DOCUMENT_BEGIN (&query, "n", &child);
         BSON_APPEND_INT32 (&child, "$gte", file->n);
         bson_append_document_end (&query, &child);

         bson_init (&opts);
         BSON_APPEND_DOCUMENT_BEGIN (&opts, "sort", &child);
         BSON_APPEND_INT32 (&child, "n", 1);
         bson_append_document_end (&opts, &child);

         BSON_APPEND_DOCUMENT_BEGIN (&opts, "projection", &child);
         BSON_APPEND_INT32 (&child, "n", 1);
         BSON_APPEND_INT32 (&child, "data", 1);
         BSON_APPEND_INT32 (&child, "_id", 0);
         bson_append_document_end (&opts, &child);

         /* find all chunks greater than or equal to our current file pos */
         file->cursor = mongoc_collection_find_with_opts (
            file->gridfs->chunks, &query, &opts, NULL);

         file->cursor_range[0] = file->n;
         file->cursor_range[1] = (uint32_t) (file->length / file->chunk_size);

         bson_destroy (&query);
         bson_destroy (&opts);

         BSON_ASSERT (file->cursor);
      }

      /* we might have had a cursor before, then seeked ahead past a chunk.
       * iterate until we're on the right chunk */
      while (file->cursor_range[0] <= file->n) {
         if (!mongoc_cursor_next (file->cursor, &chunk)) {
            /* copy cursor error; if there's none, we're missing a chunk */
            if (!mongoc_cursor_error (file->cursor, &file->error)) {
               missing_chunk (file);
            }

            RETURN (0);
         }

         file->cursor_range[0]++;
      }

      BSON_ASSERT (bson_iter_init (&iter, chunk));

      /* grab out what we need from the chunk */
      while (bson_iter_next (&iter)) {
         key = bson_iter_key (&iter);

         if (strcmp (key, "n") == 0) {
            if (file->n != bson_iter_int32 (&iter)) {
               missing_chunk (file);
               RETURN (0);
            }
         } else if (strcmp (key, "data") == 0) {
            bson_iter_binary (&iter, NULL, &len, &data);
         } else {
            /* Unexpected key. This should never happen */
            RETURN (0);
         }
      }

      if (file->n != file->pos / file->chunk_size) {
         return 0;
      }
   }

   if (!data) {
      bson_set_error (&file->error,
                      MONGOC_ERROR_GRIDFS,
                      MONGOC_ERROR_GRIDFS_CHUNK_MISSING,
                      "corrupt chunk number %" PRId32,
                      file->n);
      RETURN (0);
   }

   file->page = _mongoc_gridfs_file_page_new (data, len, file->chunk_size);

   /* seek in the page towards wherever we're supposed to be */
   RETURN (
      _mongoc_gridfs_file_page_seek (file->page, file->pos % file->chunk_size));
}