text: #include <mongoc/mongoc.h>
  #include <stdio.h>
  #include <stdlib.h>
  
  #include "client-side-encryption-helpers.h"
  
  /* This example demonstrates how to set up automatic decryption without
   * automatic encryption using the community version of MongoDB */
  int
  main (int argc, char **argv)
  {
  /* The collection used to store the encryption data keys. */
  #define KEYVAULT_DB "encryption"
  #define KEYVAULT_COLL "__libmongocTestKeyVault"
  /* The collection used to store the encrypted documents in this example. */
  #define ENCRYPTED_DB "test"
  #define ENCRYPTED_COLL "coll"
  
     int exit_status = EXIT_FAILURE;
     bool ret;
     uint8_t *local_masterkey = NULL;
     uint32_t local_masterkey_len;
     bson_t *kms_providers = NULL;
     bson_error_t error = {0};
     bson_t *index_keys = NULL;
     char *index_name = NULL;
     bson_t *create_index_cmd = NULL;
     bson_t *schema = NULL;
     mongoc_client_t *client = NULL;
     mongoc_collection_t *coll = NULL;
     mongoc_collection_t *keyvault_coll = NULL;
     bson_t *to_insert = NULL;
     bson_t *create_cmd = NULL;
     bson_t *create_cmd_opts = NULL;
     mongoc_write_concern_t *wc = NULL;
     mongoc_client_encryption_t *client_encryption = NULL;
     mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
     mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
     char *keyaltnames[] = {"mongoc_encryption_example_4"};
     bson_value_t datakey_id = {0};
     bson_value_t encrypted_field = {0};
     bson_value_t to_encrypt = {0};
     mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
     bson_value_t decrypted = {0};
     mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
     mongoc_client_t *unencrypted_client = NULL;
     mongoc_collection_t *unencrypted_coll = NULL;
  
     mongoc_init ();
  
     /* Configure the master key. This must be the same master key that was used
      * to create the encryption key. */
     local_masterkey =
        hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
     if (!local_masterkey || local_masterkey_len != 96) {
        fprintf (stderr,
                 "Specify LOCAL_MASTERKEY environment variable as a "
                 "secure random 96 byte hex value.\n");
        goto fail;
     }
  
     kms_providers = BCON_NEW ("local",
                               "{",
                               "key",
                               BCON_BIN (0, local_masterkey, local_masterkey_len),
                               "}");
  
     client =
        mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
     auto_encryption_opts = mongoc_auto_encryption_opts_new ();
     mongoc_auto_encryption_opts_set_keyvault_namespace (
        auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
     mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
                                                    kms_providers);
  
     /* Setting bypass_auto_encryption to true disables automatic encryption but
      * keeps the automatic decryption behavior. bypass_auto_encryption will also
      * disable spawning mongocryptd */
     mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
                                                             true);
  
     /* Once bypass_auto_encryption is set, community users can enable auto
      * encryption on the client. This will, in fact, only perform automatic
      * decryption. */
     ret = mongoc_client_enable_auto_encryption (
        client, auto_encryption_opts, &error);
     if (!ret) {
        goto fail;
     }
  
     /* Now that automatic decryption is on, we can test it by inserting a
      * document with an explicitly encrypted value into the collection. When we
      * look up the document later, it should be automatically decrypted for us.
      */
     coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
  
     /* Clear old data */
     mongoc_collection_drop (coll, NULL);
  
     /* Set up the key vault for this example. */
     keyvault_coll =
        mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
     mongoc_collection_drop (keyvault_coll, NULL);
  
     /* Create a unique index to ensure that two data keys cannot share the same
      * keyAltName. This is recommended practice for the key vault. */
     index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
     index_name = mongoc_collection_keys_to_index_string (index_keys);
     create_index_cmd = BCON_NEW ("createIndexes",
                                  KEYVAULT_COLL,
                                  "indexes",
                                  "[",
                                  "{",
                                  "key",
                                  BCON_DOCUMENT (index_keys),
                                  "name",
                                  index_name,
                                  "unique",
                                  BCON_BOOL (true),
                                  "partialFilterExpression",
                                  "{",
                                  "keyAltNames",
                                  "{",
                                  "$exists",
                                  BCON_BOOL (true),
                                  "}",
                                  "}",
                                  "}",
                                  "]");
     ret = mongoc_client_command_simple (client,
                                         KEYVAULT_DB,
                                         create_index_cmd,
                                         NULL /* read prefs */,
                                         NULL /* reply */,
                                         &error);
  
     if (!ret) {
        goto fail;
     }
  
     client_encryption_opts = mongoc_client_encryption_opts_new ();
     mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
                                                      kms_providers);
     mongoc_client_encryption_opts_set_keyvault_namespace (
        client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
  
     /* The key vault client is used for reading to/from the key vault. This can
      * be the same mongoc_client_t used by the application. */
     mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
                                                        client);
     client_encryption =
        mongoc_client_encryption_new (client_encryption_opts, &error);
     if (!client_encryption) {
        goto fail;
     }
  
     /* Create a new data key for the encryptedField.
      * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
      */
     datakey_opts = mongoc_client_encryption_datakey_opts_new ();
     mongoc_client_encryption_datakey_opts_set_keyaltnames (
        datakey_opts, keyaltnames, 1);
     ret = mongoc_client_encryption_create_datakey (
        client_encryption, "local", datakey_opts, &datakey_id, &error);
     if (!ret) {
        goto fail;
     }
  
     /* Explicitly encrypt a field. */
     encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
     mongoc_client_encryption_encrypt_opts_set_algorithm (
        encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
     mongoc_client_encryption_encrypt_opts_set_keyaltname (
        encrypt_opts, "mongoc_encryption_example_4");
     to_encrypt.value_type = BSON_TYPE_UTF8;
     to_encrypt.value.v_utf8.str = "123456789";
     to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
  
     ret = mongoc_client_encryption_encrypt (
        client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
     if (!ret) {
        goto fail;
     }
  
     to_insert = bson_new ();
     BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
     ret = mongoc_collection_insert_one (
        coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
     if (!ret) {
        goto fail;
     }
  
     /* When we retrieve the document, any encrypted fields will get automatically
      * decrypted by the driver. */
     printf ("decrypted document: ");
     if (!print_one_document (coll, &error)) {
        goto fail;
     }
     printf ("\n");
  
     unencrypted_client =
        mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
     unencrypted_coll = mongoc_client_get_collection (
        unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
  
     printf ("encrypted document: ");
     if (!print_one_document (unencrypted_coll, &error)) {
        goto fail;
     }
     printf ("\n");
  
     exit_status = EXIT_SUCCESS;
  fail:
     if (error.code) {
        fprintf (stderr, "error: %s\n", error.message);
     }
  
     bson_free (local_masterkey);
     bson_destroy (kms_providers);
     mongoc_collection_destroy (keyvault_coll);
     bson_destroy (index_keys);
     bson_free (index_name);
     bson_destroy (create_index_cmd);
     mongoc_collection_destroy (coll);
     mongoc_client_destroy (client);
     bson_destroy (to_insert);
     bson_destroy (schema);
     bson_destroy (create_cmd);
     bson_destroy (create_cmd_opts);
     mongoc_write_concern_destroy (wc);
     mongoc_client_encryption_destroy (client_encryption);
     mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
     mongoc_client_encryption_opts_destroy (client_encryption_opts);
     bson_value_destroy (&encrypted_field);
     mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
     bson_value_destroy (&decrypted);
     bson_value_destroy (&datakey_id);
     mongoc_collection_destroy (unencrypted_coll);
     mongoc_client_destroy (unencrypted_client);
     mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
  
     mongoc_cleanup ();
     return exit_status;
  }