/**
   \details Turn request parameters to SPropValue array. This
   convenient function should be used among MAPI ROPs that have
   parameters which can be turned to MAPI properties and are stored
   within backends.

   \param mem_ctx pointer to the memory context
   \param request generic pointer to the ROP request
   \param opnum MAPI opnum identifying ROP contents

   \note Developers must talloc_free returned SRow after they finish
   using it.

   \return Allocated SRow on success, otherwise NULL
 */
_PUBLIC_ struct SRow *libmapiserver_ROP_request_to_properties(TALLOC_CTX *mem_ctx, 
							      void *request, 
							      uint8_t opnum)
{
	struct SRow			*aRow;
	struct CreateFolder_req		*CreateFolder_req;

	aRow = talloc_zero(mem_ctx, struct SRow);
	aRow->lpProps = talloc_array(aRow, struct SPropValue, 2);
	aRow->cValues = 0;

	switch (opnum) {
	case op_MAPI_CreateFolder:
		CreateFolder_req = (struct CreateFolder_req *) request;
		aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
					       PR_FOLDER_TYPE, (void *)&(CreateFolder_req->ulFolderType));
		switch (CreateFolder_req->ulType) {
		case MAPI_FOLDER_ANSI:
			aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
						       PR_DISPLAY_NAME, (void *)(CreateFolder_req->FolderName.lpszA));
			aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
						       PR_COMMENT, (void *)(CreateFolder_req->FolderComment.lpszA));
			break;
		case MAPI_FOLDER_UNICODE:
			aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
						       PR_DISPLAY_NAME_UNICODE, (void *)(CreateFolder_req->FolderName.lpszW));
			aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
						       PR_COMMENT_UNICODE, (void *)(CreateFolder_req->FolderComment.lpszW));
			break;
		}
		
		break;
	default:
		OC_DEBUG(0, "opnum %d not implemented yet", opnum);
		talloc_free(aRow);
		return NULL;
	}
	
	return aRow;
}
Exemple #2
0
/**
   \details Build a SPropValue array from ocpf context

   This function builds a SPropValue array from the ocpf context and
   information stored.
   
   \param mem_ctx pointer to the memory context to use for memory
   allocation
   \param context_id identifier of the context to build a SPropValue
   array for

   \note This function is a server-side convenient function only. It
   doesn't handle named properties and its scope is much more limited
   than ocpf_set_SpropValue. Developers working on a client-side
   software/library must use ocpf_set_SPropValue instead.

   \return MAPI_E_SUCCESS on success, otherwise MAPI/OCPF error

   \sa ocpf_get_SPropValue
 */
_PUBLIC_ enum MAPISTATUS ocpf_server_set_SPropValue(TALLOC_CTX *mem_ctx, 
						    uint32_t context_id)
{
	struct ocpf_property	*pel;
	struct ocpf_context	*ctx;

	/* sanity checks */
	MAPI_RETVAL_IF(!ocpf, MAPI_E_NOT_INITIALIZED, NULL);

	/* Step 1. Search for the context */
	ctx = ocpf_context_search_by_context_id(ocpf->context, context_id);
	OCPF_RETVAL_IF(!ctx, NULL, OCPF_INVALID_CONTEXT, NULL);

	/* Step 2. Allocate SPropValue */
	ctx->cValues = 0;
	ctx->lpProps = talloc_array(ctx, struct SPropValue, 2);

	/* Step 3. Add Known properties */
	if (ctx->props && ctx->props->next) {
		for (pel = ctx->props; pel->next; pel = pel->next) {
			switch (pel->aulPropTag) {
			case PidTagMessageClass:
				ocpf_server_set_type(context_id, (const char *)pel->value);
				ctx->lpProps = add_SPropValue(ctx, ctx->lpProps, &ctx->cValues, 
							      pel->aulPropTag, pel->value);
				break;
			default:
				ctx->lpProps = add_SPropValue(ctx, ctx->lpProps, &ctx->cValues, 
							      pel->aulPropTag, pel->value);
			}
		}
	}
	/* Step 4. Add message class */
	if (ctx->type) {
		ctx->lpProps = add_SPropValue(ctx, ctx->lpProps, &ctx->cValues,
					      PidTagMessageClass, (const void *)ctx->type);
	}
	
	return MAPI_E_SUCCESS;	
}
Exemple #3
0
/**
 * Adds a new SPropValue at the end of values_array, allocating its memory in the mem_ctx.
 * *n_values holds number of items stored in the array, and will be increased by one.
 **/
gboolean
e_mapi_utils_add_spropvalue (TALLOC_CTX *mem_ctx,
			     struct SPropValue **values_array,
			     uint32_t *n_values,
			     uint32_t prop_tag,
			     gconstpointer prop_value)
{
	g_return_val_if_fail (mem_ctx != NULL, FALSE);
	g_return_val_if_fail (values_array != NULL, FALSE);
	g_return_val_if_fail (n_values != NULL, FALSE);

	*values_array = add_SPropValue (mem_ctx, *values_array, n_values, prop_tag, prop_value);

	return TRUE;
}
Exemple #4
0
/**
   \details EcDoRpc CreateFolder (0x1c) Rop. This operation creates 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 CreateFolder EcDoRpc_MAPI_REQ
   structure
   \param mapi_repl pointer to the CreateFolder 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

   \note We do not provide support for GhostInfo
 */
_PUBLIC_ enum MAPISTATUS EcDoRpc_RopCreateFolder(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		*parent = NULL;
	uint32_t			handle;
	uint64_t			parent_fid, fid, cn;
	struct SPropValue		cnValue;
	struct emsmdbp_object		*parent_object = NULL;
	struct emsmdbp_object		*object = NULL;
	struct CreateFolder_req		*request;
	struct CreateFolder_repl	*response;
	struct SRow			*aRow = NULL;
	void				*data;
	struct mapi_handles		*rec = NULL;

	OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] CreateFolder (0x1c)\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);

	/* Set up sensible values for the reply */
	mapi_repl->opnum = mapi_req->opnum;
	mapi_repl->error_code = MAPI_E_SUCCESS;
	mapi_repl->handle_idx = mapi_req->u.mapi_CreateFolder.handle_idx;

	if (!mapi_req->u.mapi_CreateFolder.ulFolderType ||
	    mapi_req->u.mapi_CreateFolder.ulFolderType > 0x2) {
		mapi_repl->error_code = MAPI_E_INVALID_PARAMETER;
		goto end;
	}

	/* Step 1. Retrieve parent handle in the hierarchy */
	handle = handles[mapi_req->handle_idx];
	retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
	OPENCHANGE_RETVAL_IF(retval, retval, NULL);

	/* With CreateFolder, the parent object really IS the parent object */
	mapi_handles_get_private_data(parent, &data);
	parent_object = (struct emsmdbp_object *)data;
	if (!parent_object) {
		OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] CreateFolder null object\n");
		mapi_repl->error_code = MAPI_E_NO_SUPPORT;
		goto end;
	}

	if (parent_object->type == EMSMDBP_OBJECT_MAILBOX) {
		mapi_repl->error_code = MAPI_E_NO_SUPPORT;
		goto end;
	}

	if (parent_object->type != EMSMDBP_OBJECT_FOLDER && parent_object->type != EMSMDBP_OBJECT_MAILBOX) {
		OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] CreateFolder wrong object type: 0x%x\n", parent_object->type);
		mapi_repl->error_code = MAPI_E_NO_SUPPORT;
		goto end;
	}

	request = &mapi_req->u.mapi_CreateFolder;
	response = &mapi_repl->u.mapi_CreateFolder;

	/* OC_DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder parent: 0x%.16"PRIx64"\n", parent_fid)); */
	/* OC_DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Creating %s\n", request->FolderName.lpszW)); */

	/* if (request->ulFolderType != FOLDER_GENERIC) { */
	/* 	OC_DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Unexpected folder type 0x%x\n", request->ulType)); */
	/* 	mapi_repl->error_code = MAPI_E_NO_SUPPORT; */
	/* 	goto end; */
	/* } */

	response->IsExistingFolder = false;

	ret = emsmdbp_object_get_fid_by_name(emsmdbp_ctx, parent_object, request->FolderName.lpszW, &fid);
	if (ret == MAPISTORE_SUCCESS) {
		if (oxosfld_is_special_folder(emsmdbp_ctx, fid) || request->ulFlags == OPEN_IF_EXISTS) {
			response->IsExistingFolder = true;
		} else {
			if (emsmdbp_is_mapistore(parent_object)) {
				OC_DEBUG(5, "Folder %s exists in MAPIStore", request->FolderName.lpszW);
			} else {
				OC_DEBUG(5, "Folder %s exists in OpenChangeDB", request->FolderName.lpszW);
			}
			mapi_repl->error_code = MAPI_E_COLLISION;
			goto end;
		}
	}

	mapi_handles_add(emsmdbp_ctx->handles_ctx, 0, &rec);
	if (response->IsExistingFolder) {
		retval = emsmdbp_object_open_folder_by_fid(rec, emsmdbp_ctx, parent_object, fid, &object);
		if (retval != MAPI_E_SUCCESS) {
			OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] Failure opening existing folder: %s\n", mapi_get_errstr(retval));
			mapi_handles_delete(emsmdbp_ctx->handles_ctx, rec->handle);
			mapi_repl->error_code = retval;
			goto end;
		}
	} else {
		/* Step 3. Turn CreateFolder parameters into MAPI property array */
		parent_fid = parent_object->object.folder->folderID;
		if (openchangedb_is_public_folder_id(emsmdbp_ctx->oc_ctx, parent_fid)) {
			retval = openchangedb_get_new_public_folderID(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &fid);
		} else {
			retval = mapistore_error_to_mapi(mapistore_indexing_get_new_folderID(emsmdbp_ctx->mstore_ctx, &fid));
		}
		if (retval != MAPI_E_SUCCESS) {
			OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] Could not obtain a new folder id\n");
			mapi_repl->error_code = MAPI_E_NO_SUPPORT;
			goto end;
		}

		retval = openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &cn);
		if (retval != MAPI_E_SUCCESS) {
			OC_DEBUG(4, "exchange_emsmdb: [OXCFOLD] Could not obtain a new folder cn\n");
			mapi_repl->error_code = MAPI_E_NO_SUPPORT;
			goto end;
		}

		aRow = libmapiserver_ROP_request_to_properties(mem_ctx, (void *)&mapi_req->u.mapi_CreateFolder, op_MAPI_CreateFolder);
		aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues), PR_PARENT_FID, (void *)(&parent_fid));
		cnValue.ulPropTag = PidTagChangeNumber;
		cnValue.value.d = cn;
		SRow_addprop(aRow, cnValue);

		retval = emsmdbp_object_create_folder(emsmdbp_ctx, parent_object, rec, fid,
						      aRow, true, &object);
		if (retval != MAPI_E_SUCCESS) {
			OC_DEBUG(5, "folder creation failed\n");
			mapi_handles_delete(emsmdbp_ctx->handles_ctx, rec->handle);
			mapi_repl->error_code = retval;
			goto end;
		}
	}

	handles[mapi_repl->handle_idx] = rec->handle;
	mapi_handles_set_private_data(rec, object);

	response->folder_id = fid;

	if (response->IsExistingFolder == true) {
		response->GhostUnion.GhostInfo.HasRules = false;
		response->GhostUnion.GhostInfo.IsGhosted = false;
	}

end:
	*size += libmapiserver_RopCreateFolder_size(mapi_repl);

	if (aRow) {
		talloc_free(aRow);
	}

	return MAPI_E_SUCCESS;
}