/** \details Initialize mapistore named properties MySQL backend \param mem_ctx pointer to the memory context \param lp_ctx pointer to the loadparm context \param nprops_ctx pointer on pointer to the namedprops context to return \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error */ enum mapistore_error mapistore_namedprops_mysql_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct namedprops_context **nprops_ctx) { enum mapistore_error retval; struct namedprops_context *nprops = NULL; struct namedprops_mysql_params parms; MYSQL *conn = NULL; /* Sanity checks */ MAPISTORE_RETVAL_IF(!lp_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL); MAPISTORE_RETVAL_IF(!nprops_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL); /* Retrieve smb.conf arguments */ retval = mapistore_namedprops_mysql_parameters(lp_ctx, &parms); if (retval != MAPISTORE_SUCCESS) { DEBUG(0, ("[%s:%d] ERROR: parsing MySQL named properties " "parametric option failed with %s\n", __FUNCTION__, __LINE__, mapistore_errstr(retval))); MAPISTORE_RETVAL_ERR(retval, NULL); } /* Establish MySQL connection */ if (parms.sock) { // FIXME DEBUG(0, ("Not implemented connect through unix socket to mysql")); } else { char *connection_string = connection_string_from_parameters(mem_ctx, &parms); MAPISTORE_RETVAL_IF(!connection_string, MAPISTORE_ERR_NOT_INITIALIZED, NULL); create_connection(connection_string, &conn); } MAPISTORE_RETVAL_IF(!conn, MAPISTORE_ERR_NOT_INITIALIZED, NULL); /* Initialize the database */ if (!is_schema_created(conn) || is_database_empty(conn)) { retval = initialize_database(conn, parms.data); MAPISTORE_RETVAL_IF(retval != MAPISTORE_SUCCESS, retval, NULL); } /* Create context */ nprops = talloc_zero(mem_ctx, struct namedprops_context); MAPISTORE_RETVAL_IF(!nprops, MAPISTORE_ERR_NO_MEMORY, NULL); nprops->backend_type = NAMEDPROPS_BACKEND_MYSQL; nprops->create_id = create_id; nprops->get_mapped_id = get_mapped_id; nprops->get_nameid = get_nameid; nprops->get_nameid_type = get_nameid_type; nprops->next_unused_id = next_unused_id; nprops->transaction_commit = transaction_commit; nprops->transaction_start = transaction_start; nprops->data = conn; talloc_set_destructor(nprops, mapistore_namedprops_mysql_destructor); *nprops_ctx = nprops; return MAPISTORE_SUCCESS; }
/** \details EcDoRpc ModifyPermissions (0x40) Rop. This operation gets the GUID of a public folder's per-user information. \param mem_ctx pointer to the memory context \param emsmdbp_ctx pointer to the emsmdb provider context \param mapi_req pointer to the GetPerUserLongTermIds EcDoRpc_MAPI_REQ \param mapi_repl pointer to the GetPerUserLongTermIds EcDoRpc_MAPI_REPL \param handles pointer to the MAPI handles array \param size pointer to the mapi_response size to update \return MAPI_E_SUCCESS on success, otherwise MAPI error */ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopModifyPermissions(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx, struct EcDoRpc_MAPI_REQ *mapi_req, struct EcDoRpc_MAPI_REPL *mapi_repl, uint32_t *handles, uint16_t *size) { enum MAPISTATUS retval; enum mapistore_error mretval; struct mapi_handles *folder; struct emsmdbp_object *folder_object; void *data = NULL; uint32_t handle; struct ModifyPermissions_req *request; OC_DEBUG(4, "exchange_emsmdb: [OXCSTOR] ModifyPermissions (0x40)\n"); /* Sanity checks */ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL); mapi_repl->opnum = mapi_req->opnum; mapi_repl->handle_idx = mapi_req->handle_idx; mapi_repl->error_code = MAPI_E_SUCCESS; /* Ensure handle references a folder object */ handle = handles[mapi_req->handle_idx]; retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &folder); if (retval) { mapi_repl->error_code = MAPI_E_INVALID_OBJECT; OC_DEBUG(5, " handle (%x) not found: %x\n", handle, mapi_req->handle_idx); goto end; } retval = mapi_handles_get_private_data(folder, &data); if (retval || !data) { mapi_repl->error_code = MAPI_E_INVALID_OBJECT; OC_DEBUG(5, " handle data not found, idx = %x\n", mapi_req->handle_idx); goto end; } folder_object = (struct emsmdbp_object *) data; if (folder_object->type != EMSMDBP_OBJECT_FOLDER) { mapi_repl->error_code = MAPI_E_INVALID_OBJECT; OC_DEBUG(5, " unhandled object type: %d\n", folder_object->type); goto end; } request = &mapi_req->u.mapi_ModifyPermissions; if (emsmdbp_is_mapistore(folder_object)) { mretval = mapistore_folder_modify_permissions(emsmdbp_ctx->mstore_ctx, emsmdbp_get_contextID(folder_object), folder_object->backend_object, request->rowList.ModifyFlags, request->rowList.ModifyCount, request->rowList.PermissionsData); if (mretval != MAPISTORE_SUCCESS) { OC_DEBUG(5, "mapistore_folder_modify_permissions: %s\n", mapistore_errstr(mretval)); mapi_repl->error_code = mapistore_error_to_mapi(mretval); } } else { mapi_repl->error_code = MAPI_E_NOT_FOUND; } end: *size += libmapiserver_RopModifyPermissions_size(mapi_repl); return MAPI_E_SUCCESS; }
/** \details EcDoRpc DeleteFolder (0x1d) Rop. This operation deletes a folder on the remote server. \param mem_ctx pointer to the memory context \param emsmdbp_ctx pointer to the emsmdb provider context \param mapi_req pointer to the DeleteFolder EcDoRpc_MAPI_REQ structure \param mapi_repl pointer to the DeleteFolder EcDoRpc_MAPI_REPL structure \param handles pointer to the MAPI handles array \param size pointer to the mapi_response size to update \return MAPI_E_SUCCESS on success, otherwise MAPI error */ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopDeleteFolder(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx, struct EcDoRpc_MAPI_REQ *mapi_req, struct EcDoRpc_MAPI_REPL *mapi_repl, uint32_t *handles, uint16_t *size) { enum MAPISTATUS retval; enum mapistore_error ret; struct mapi_handles *rec = NULL; uint32_t handle; void *handle_priv_data; struct emsmdbp_object *handle_object = NULL; OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] DeleteFolder (0x1d)\n"); /* Sanity checks */ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL); /* Initialize default empty DeleteFolder reply */ mapi_repl->opnum = mapi_req->opnum; mapi_repl->error_code = MAPI_E_SUCCESS; mapi_repl->handle_idx = mapi_req->handle_idx; /* TODO: factor this out to be convenience API */ /* Convert the handle index into a handle, and then get the folder id */ handle = handles[mapi_req->handle_idx]; retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec); OPENCHANGE_RETVAL_IF(retval, retval, NULL); mapi_handles_get_private_data(rec, &handle_priv_data); handle_object = (struct emsmdbp_object *)handle_priv_data; if (!handle_object) { OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] DeleteFolder null object\n"); mapi_repl->error_code = MAPI_E_NO_SUPPORT; return MAPI_E_SUCCESS; } if (handle_object->type != EMSMDBP_OBJECT_FOLDER) { OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] DeleteFolder wrong object type: 0x%x\n", handle_object->type); mapi_repl->error_code = MAPI_E_NO_SUPPORT; return MAPI_E_SUCCESS; } retval = MAPI_E_SUCCESS; ret = emsmdbp_folder_delete(emsmdbp_ctx, handle_object, mapi_req->u.mapi_DeleteFolder.FolderId, mapi_req->u.mapi_DeleteFolder.DeleteFolderFlags); if (ret == MAPISTORE_ERR_EXIST) { mapi_repl->u.mapi_DeleteFolder.PartialCompletion = true; } else if (ret != MAPISTORE_SUCCESS) { OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] DeleteFolder failed to delete fid 0x%.16"PRIx64" (%s)", mapi_req->u.mapi_DeleteFolder.FolderId, mapistore_errstr(ret)); if (ret == MAPISTORE_ERR_DENIED) { retval = MAPI_E_NO_ACCESS; } else { retval = MAPI_E_NOT_FOUND; } } mapi_repl->error_code = retval; *size += libmapiserver_RopDeleteFolder_size(mapi_repl); return MAPI_E_SUCCESS; }
/** \details EcDoRpc RegisterNotification (0x29) Rop. This operation subscribes for specified notifications on the server and returns a handle of the subscription to the client. \param mem_ctx pointer to the memory context \param emsmdbp_ctx pointer to the emsmdb provider context \param mapi_req pointer to the RegisterNotification EcDoRpc_MAPI_REQ structure \param mapi_repl pointer to the RegisterNotification EcDoRpc_MAPI_REPL structure \param handles pointer to the MAPI handles array \param size pointer to the mapi_response size to update \return MAPI_E_SUCCESS on success, otherwise MAPI error */ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopRegisterNotification(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx, struct EcDoRpc_MAPI_REQ *mapi_req, struct EcDoRpc_MAPI_REPL *mapi_repl, uint32_t *handles, uint16_t *size) { enum MAPISTATUS retval; enum mapistore_error mretval; struct emsmdbp_object *parent_object; struct emsmdbp_object *subscription_object; struct mapi_handles *parent_rec = NULL; struct mapi_handles *subscription_rec = NULL; uint32_t handle; void *data; uint16_t flags; uint64_t fid = 0; uint64_t mid = 0; OC_DEBUG(4, "exchange_emsmdb: [OXCNOTIF] RegisterNotification (0x29)\n"); /* Sanity checks */ OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL); OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL); OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL); mapi_repl->opnum = mapi_req->opnum; mapi_repl->handle_idx = mapi_req->u.mapi_RegisterNotification.handle_idx; mapi_repl->error_code = MAPI_E_SUCCESS; handle = handles[mapi_req->handle_idx]; retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent_rec); if (retval) { mapi_repl->error_code = MAPI_E_INVALID_OBJECT; OC_DEBUG(5, " handle (%x) not found: %x\n", handle, mapi_req->handle_idx); goto end; } retval = mapi_handles_get_private_data(parent_rec, &data); if (retval) { mapi_repl->error_code = retval; OC_DEBUG(5, " handle data not found, idx = %x\n", mapi_req->handle_idx); goto end; } parent_object = (struct emsmdbp_object *) data; retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &subscription_rec); if (retval) { mapi_repl->error_code = retval; goto end; } /* Notification subscriptions */ flags = mapi_req->u.mapi_RegisterNotification.NotificationFlags; if (mapi_req->u.mapi_RegisterNotification.WantWholeStore) { flags |= sub_WholeStore; } else { fid = mapi_req->u.mapi_RegisterNotification.FolderId.ID; mid = mapi_req->u.mapi_RegisterNotification.MessageId.ID; } mretval = mapistore_notification_subscription_add(emsmdbp_ctx->mstore_ctx, emsmdbp_ctx->session_uuid, subscription_rec->handle, flags, fid, mid, 0, NULL); if (mretval != MAPISTORE_SUCCESS) { /* MS-OXCROPS section 2.2.14.1 does not describe a * failure response buffer for RegisterNotification * Rop */ OC_DEBUG(0, "Failed to add subscription: %s", mapistore_errstr(mretval)); } handles[mapi_repl->handle_idx] = subscription_rec->handle; /* Create emsmdbp subscription object */ subscription_object = emsmdbp_object_subscription_init(subscription_rec, emsmdbp_ctx, parent_object); if (!subscription_object) { OC_DEBUG(0, "Unable to create subscription object"); } mapi_handles_set_private_data(subscription_rec, subscription_object); subscription_object->object.subscription->handle = subscription_rec->handle; end: *size += libmapiserver_RopRegisterNotification_size(); return MAPI_E_SUCCESS; }
int main(int argc, const char *argv[]) { TALLOC_CTX *mem_ctx; int retval; struct mapistore_context *mstore_ctx; struct loadparm_context *lp_ctx; struct backend_context *context; struct backend_context_list *context_list; poptContext pc; int opt, i; const char *opt_debug = NULL; uint32_t context_id = 0; void *root_folder; enum { OPT_DEBUG=1000 }; struct poptOption long_options[] = { POPT_AUTOHELP { "debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set the debug level", NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL } }; mem_ctx = talloc_named(NULL, 0, "mapistore_EL_test"); lp_ctx = loadparm_init_global(true); setup_logging(NULL, DEBUG_STDOUT); pc = poptGetContext("mapistore_test", argc, argv, long_options, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_DEBUG: opt_debug = poptGetOptArg(pc); break; } } poptFreeContext(pc); if (opt_debug) lpcfg_set_cmdline(lp_ctx, "log level", opt_debug); printf("Mapping path : "); retval = mapistore_set_mapping_path("/tmp"); if (retval != MAPISTORE_SUCCESS) { printf("ERROR: %s\n", mapistore_errstr(retval)); exit (1); } printf("OK\n"); printf("Initialise mapistore\n"); mstore_ctx = mapistore_init(mem_ctx, lp_ctx, NULL); if (!mstore_ctx) { printf("ERROR: %s\n", mapistore_errstr(retval)); exit (1); } printf("Adding a context (INBOX)\n"); retval = mapistore_add_context(mstore_ctx, "Administrator", "EasyLinux://INBOX", -1, &context_id, &root_folder); if (retval != MAPISTORE_SUCCESS) { printf("ERROR: %s\n", mapistore_errstr(retval)); exit (1); } //DEBUG(0,(" Root folder: %s",(char *)root_folder) ); /* DEBUG(0,("Delete context : ")); retval = mapistore_del_context(mstore_ctx, context_id); DEBUG(0,("OK\n")); */ DEBUG(0,("Release : ")); retval = mapistore_release(mstore_ctx); if (retval != MAPISTORE_SUCCESS) { DEBUG(0, ("%s\n", mapistore_errstr(retval))); exit (1); } DEBUG(0,("OK\n")); return 0; }
int main(int argc, const char *argv[]) { TALLOC_CTX *mem_ctx; enum mapistore_error retval; poptContext pc; int opt; struct loadparm_context *lp_ctx; struct ocnotify_private ocnotify; struct mapistore_notification_context *ctx; const char *opt_server = NULL; const char *opt_newmail = NULL; bool opt_list_server = false; bool ret; int verbosity = 0; char *debuglevel = NULL; const char *sep = NULL; uint32_t i = 0; uint32_t count = 0; const char **hosts = NULL; enum { OPT_USERNAME=1000, OPT_BACKEND, OPT_DSTFOLDER, OPT_SEPARATOR, OPT_SERVER, OPT_SERVER_LIST, OPT_FLUSH, OPT_NEWMAIL, OPT_VERBOSE }; struct poptOption long_options[] = { POPT_AUTOHELP { "username", 'U', POPT_ARG_STRING, NULL, OPT_USERNAME, "set the username", NULL }, { "backend", 'b', POPT_ARG_STRING, NULL, OPT_BACKEND, "set the mapistore backend", NULL }, { "dstfolder", 0, POPT_ARG_STRING, NULL, OPT_DSTFOLDER, "set the destination folder", NULL }, { "sep", 0, POPT_ARG_STRING, NULL, OPT_SEPARATOR, "set the folder separator", NULL }, { "server", 'H', POPT_ARG_STRING, NULL, OPT_SERVER, "set the resolver address", NULL }, { "list", 0, POPT_ARG_NONE, NULL, OPT_SERVER_LIST, "list notification service instances", NULL }, { "flush", 0, POPT_ARG_NONE, NULL, OPT_FLUSH, "flush notification cache for the user", NULL }, { "newmail", 'n', POPT_ARG_STRING, NULL, OPT_NEWMAIL, "send newmail notification and specify .eml", NULL }, { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, "Add one or more -v to increase verbosity", NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL } }; mem_ctx = talloc_new(NULL); if (!mem_ctx) return 1; lp_ctx = loadparm_init_global(true); if (!lp_ctx) return 1; oc_log_init_stdout(); memset(&ocnotify, 0, sizeof (struct ocnotify_private)); pc = poptGetContext("ocnotify", argc, argv, long_options, 0); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_USERNAME: ocnotify.username = poptGetOptArg(pc); break; case OPT_BACKEND: ocnotify.backend = poptGetOptArg(pc); break; case OPT_DSTFOLDER: ocnotify.dstfolder = poptGetOptArg(pc); break; case OPT_SEPARATOR: sep = poptGetOptArg(pc); ocnotify.sep = sep[0]; break; case OPT_SERVER: opt_server = poptGetOptArg(pc); break; case OPT_SERVER_LIST: opt_list_server = true; break; case OPT_FLUSH: ocnotify.flush = true; break; case OPT_NEWMAIL: opt_newmail = poptGetOptArg(pc); break; case OPT_VERBOSE: verbosity += 1; break; } } if (!ocnotify.username) { fprintf(stderr, "[ERR] username not specified\n"); exit (1); } debuglevel = talloc_asprintf(mem_ctx, "%u", verbosity); ret = lpcfg_set_cmdline(lp_ctx, "log level", debuglevel); if (ret == false) { oc_log(OC_LOG_FATAL, "unable to set log level"); exit (1); } talloc_free(debuglevel); if (opt_server) { ret = lpcfg_set_cmdline(lp_ctx, "mapistore:notification_cache", opt_server); if (ret == false) { oc_log(OC_LOG_FATAL, "unable to set mapistore:notification_cache"); exit (1); } } retval = mapistore_notification_init(mem_ctx, lp_ctx, &ctx); if (retval != MAPISTORE_SUCCESS) { oc_log(OC_LOG_FATAL, "[ERR] unable to initialize mapistore notification"); exit(1); } ocnotify.mstore_ctx.notification_ctx = ctx; /* Check if the user is registered */ retval = mapistore_notification_resolver_exist(&ocnotify.mstore_ctx, ocnotify.username); if (retval) { oc_log(OC_LOG_ERROR, "[ERR] resolver session: '%s'", mapistore_errstr(retval)); exit(1); } /* Retrieve server instances */ retval = mapistore_notification_resolver_get(mem_ctx, &ocnotify.mstore_ctx, ocnotify.username, &count, &hosts); if (retval) { oc_log(OC_LOG_ERROR, "[ERR] resolver record: '%s'", mapistore_errstr(retval)); exit (1); } if (opt_list_server) { oc_log(0, "%d servers found for '%s'\n", count, ocnotify.username); for (i = 0; i < count; i++) { oc_log(0, "\t* %s\n", hosts[i]); } } /* Send mail notification */ if (opt_newmail) { ocnotify_newmail(mem_ctx, ocnotify, count, hosts, opt_newmail); } /* Flush invalid data */ if (ocnotify.flush) { for (i = 0; i < count; i++) { retval = mapistore_notification_resolver_delete(&ocnotify.mstore_ctx, ocnotify.username, hosts[i]); } } talloc_free(ctx); poptFreeContext(pc); talloc_free(mem_ctx); return 0; }