Пример #1
0
static enum mapistore_error get_nameid_type(struct namedprops_context *self,
					    uint16_t mapped_id,
					    uint16_t *prop_type)
{
	TALLOC_CTX *mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	MYSQL *conn = self->data;
	const char *sql = talloc_asprintf(mem_ctx,
		//FIXME mappedId or propId? mappedId is not unique
		"SELECT propType FROM "NAMEDPROPS_MYSQL_TABLE" WHERE mappedId=%d",
		mapped_id);
	if (mysql_query(conn, sql) != 0) {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);
	}
	MYSQL_RES *res = mysql_store_result(conn);
	if (mysql_num_rows(res) == 0) {
		// Not found
		mysql_free_result(res);
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_NOT_FOUND, mem_ctx);
	}
	MYSQL_ROW row = mysql_fetch_row(res);
	*prop_type = strtol(row[0], NULL, 10);
	mysql_free_result(res);
	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
Пример #2
0
/**
  \details Update Mapistore URI for existing FMID

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param fmid FMID to update
  \param mapistore_URI mapistore URI string to associate with fmid

  \return MAPISTORE_SUCCESS on success,
	  MAPISTORE_ERR_NOT_FOUND if FMID entry doesn't exists
	  MAPISTORE_ERR_NOT_INITIALIZED if ictx pointer is invalid (NULL)
	  MAPISTORE_ERR_INVALID_PARAMETER in case other parameters are not valid
	  MAPISTORE_ERR_DATABASE_OPS in case of MySQL error
 */
static enum mapistore_error mysql_record_update(struct indexing_context *ictx,
						const char *username,
						uint64_t fmid,
						const char *mapistore_URI)
{
	int		ret;
	char		*sql;
	TALLOC_CTX	*mem_ctx;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!mapistore_URI, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	mem_ctx = talloc_new(NULL);
	sql = talloc_asprintf(mem_ctx,
		"UPDATE %s "
		"SET url = '%s' "
		"WHERE username = '******' AND fmid = %"PRIu64,
		INDEXING_TABLE, _sql(mem_ctx, mapistore_URI), _sql(mem_ctx, username), fmid);

	ret = execute_query(MYSQL(ictx), sql);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	talloc_free(mem_ctx);

	/* did we updated anything? */
	/* TODO: Move mysql_affected_rows() in execute_query() */
	if (mysql_affected_rows(MYSQL(ictx)) == 0) {
		return MAPISTORE_ERR_NOT_FOUND;
	}

	return MAPISTORE_SUCCESS;
}
Пример #3
0
/**
  \details Search for existing FMID in indexing database

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param fmid FMID to search for
  \param is_soft_deleted pointer to output location to return soft deleted state

  \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
static enum mapistore_error mysql_search_existing_fmid(struct indexing_context *ictx,
						       const char *username,
						       uint64_t fmid, bool *is_soft_deleted)
{
	int		ret;
	uint64_t	soft_deleted;
	char		*sql;
	TALLOC_CTX	*mem_ctx;

	/* Sanity */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!is_soft_deleted, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	mem_ctx = talloc_new(NULL);
	sql = talloc_asprintf(mem_ctx,
		"SELECT soft_deleted FROM %s "
		"WHERE username = '******' AND fmid = %"PRIu64,
		INDEXING_TABLE, _sql(mem_ctx, username), fmid);
	ret = select_first_uint(MYSQL(ictx), sql, &soft_deleted);
	MAPI_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_EXIST, mem_ctx);

	*is_soft_deleted = (soft_deleted == 1);
	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
Пример #4
0
static enum mapistore_error tdb_record_update(struct indexing_context *ictx,
					      const char *username,
					      uint64_t fmid,
					      const char *mapistore_URI)
{
	int		ret;
	TDB_DATA	key;
	TDB_DATA	dbuf;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!mapistore_URI, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Add the record given its fid and mapistore_uri */
	key.dptr = (unsigned char *) talloc_asprintf(ictx, "0x%.16"PRIx64, fmid);
	key.dsize = strlen((const char *) key.dptr);

	dbuf.dptr = (unsigned char *) talloc_strdup(ictx, mapistore_URI);
	dbuf.dsize = strlen((const char *) dbuf.dptr);

	ret = tdb_store(TDB_WRAP(ictx)->tdb, key, dbuf, TDB_MODIFY);
	talloc_free(key.dptr);
	talloc_free(dbuf.dptr);

	if (ret == -1) {
		OC_DEBUG(3, "Unable to update 0x%.16"PRIx64" record: %s\n",
			  fmid, mapistore_URI);
		return MAPISTORE_ERR_NOT_FOUND;
	}

	return MAPISTORE_SUCCESS;
}
Пример #5
0
/**
   \details Open connection to indexing database for a given user

   \param mstore_ctx pointer to the mapistore context
   \param username name for which the indexing database has to be
   created

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
_PUBLIC_ enum mapistore_error mapistore_indexing_add(struct mapistore_context *mstore_ctx, 
						     const char *username,
						     struct indexing_context **ictxp)
{
	struct indexing_context_list	*ictx;
	const char			*indexing_url;
	enum MAPISTATUS			retval;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);

	/* Step 1. Search if the context already exists */
	*ictxp = mapistore_indexing_search(mstore_ctx, username);
	MAPISTORE_RETVAL_IF(*ictxp, MAPISTORE_SUCCESS, NULL);

	// indexing context has not been found, let's create it.
	retval = openchangedb_get_indexing_url(mstore_ctx->conn_info->oc_ctx, username, &indexing_url);
	if (retval != MAPI_E_SUCCESS) {
		indexing_url = default_indexing_url;
	}

	// indexing_url NULL means to use the default backend: tdb
	if (indexing_url == NULL) {
		ictx = talloc_zero(mstore_ctx, struct indexing_context_list);
		mapistore_indexing_tdb_init(mstore_ctx, username, &ictx->ctx);
	} else if (strncmp(indexing_url, "mysql://", strlen("mysql://")) == 0) {
/**
   \details Return the list of pending mapistore notifications
   available on the queue name specified in argument.

   \param mstore_ctx pointer to the mapistore context
   \param mqueue_name the name of the queue to open
   \param nl pointer on pointer to the list of mapistore notifications to return

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error.
 */
_PUBLIC_ enum MAPISTATUS mapistore_get_queued_notifications_named(struct mapistore_context *mstore_ctx,
								  const char *mqueue_name,
								  struct mapistore_notification_list **nl)
{
	int					ret;
	mqd_t					mqueue;
	struct mapistore_notification_list	*nlist = NULL;
	struct mapistore_notification_list	*el = NULL;
	unsigned int				prio;
	struct mq_attr				attr;
	DATA_BLOB				data;
	bool					found = false;

	printf("[%s:%d]: queue name = %s\n", __FUNCTION__, __LINE__, ((mqueue_name) ? mqueue_name : NULL));
	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!nl, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	mqueue = mq_open(mqueue_name, O_RDONLY|O_NONBLOCK|O_CREAT, 0777, NULL);
	if (mqueue == -1) {
		perror("mq_open");
		return MAPISTORE_ERR_NOT_INITIALIZED;
	}

	/* Retrieve queue attributes */
	ret = mq_getattr(mqueue, &attr);
	if (ret == -1) {
		perror("mq_getattr");
		/* set proper error message here and remove above */
		if (mq_close(mqueue) == -1) {
			perror("mq_close");
		}
		MAPISTORE_RETVAL_IF(ret == -1, MAPISTORE_ERR_NOT_FOUND, NULL);
	}

	data.data = talloc_size((TALLOC_CTX *)mstore_ctx, attr.mq_msgsize);
	while ((data.length = mq_receive(mqueue, (char *)data.data, attr.mq_msgsize, &prio)) != -1) {
		printf("* we received a notification on queue %s\n", mqueue_name);
		if (!nlist) {
			nlist = talloc_zero((TALLOC_CTX *)mstore_ctx, struct mapistore_notification_list);
		}
		el = mapistore_notification_process_mqueue_notif((TALLOC_CTX *)nlist, data);
		printf("* processing notification returned %p\n", el);
		if (el) {
			DLIST_ADD_END(nlist, el, struct mapistore_notification_list);
		}
		talloc_free(data.data);
		found = true;
		data.data = talloc_size((TALLOC_CTX *)mstore_ctx, attr.mq_msgsize);
	}
Пример #7
0
static enum mapistore_error tdb_record_get_uri(struct indexing_context *ictx,
					       const char *username,
					       TALLOC_CTX *mem_ctx,
					       uint64_t fmid,
					       char **urip,
					       bool *soft_deletedp)
{
	TDB_DATA			key, dbuf;
	int				ret;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!urip, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!soft_deletedp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Check if the fmid exists within the database */
	key.dptr = (unsigned char *) talloc_asprintf(ictx, "0x%.16"PRIx64, fmid);
	key.dsize = strlen((const char *) key.dptr);

	ret = tdb_exists(TDB_WRAP(ictx)->tdb, key);
	if (ret) {
		*soft_deletedp = false;
	}
	else {
		talloc_free(key.dptr);
		key.dptr = (unsigned char *) talloc_asprintf(ictx, "%s0x%.16"PRIx64,
							     MAPISTORE_SOFT_DELETED_TAG,
							     fmid);
		key.dsize = strlen((const char *)key.dptr);
		ret = tdb_exists(TDB_WRAP(ictx)->tdb, key);
		if (ret) {
			*soft_deletedp = true;
		}
		else {
			talloc_free(key.dptr);
			*urip = NULL;
			return MAPISTORE_ERR_NOT_FOUND;
		}
	}
	dbuf = tdb_fetch(TDB_WRAP(ictx)->tdb, key);
	*urip = talloc_strndup(mem_ctx, (const char *) dbuf.dptr, dbuf.dsize);
	free(dbuf.dptr);
	talloc_free(key.dptr);

	return MAPISTORE_SUCCESS;
}
/**
   \details return the mapped property ID matching the nameid
   structure passed in parameter.

   \param ldb_ctx pointer to the namedprops ldb context
   \param nameid the MAPINAMEID structure to lookup
   \param propID pointer to the property ID the function returns

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
 */
_PUBLIC_ enum mapistore_error mapistore_namedprops_create_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t mapped_id)
{
	int ret;
	TALLOC_CTX *mem_ctx;
	char *ldif_record;
	struct ldb_ldif *ldif;
	char *hex_id, *dec_id, *dec_mappedid, *guid;
	struct ldb_message *normalized_msg;
	const char *ldif_records[] = { NULL, NULL };

	mem_ctx = talloc_zero(NULL, TALLOC_CTX);

	dec_mappedid = talloc_asprintf(mem_ctx, "%u", mapped_id);
	guid = GUID_string(mem_ctx, &nameid.lpguid);
	switch (nameid.ulKind) {
	case MNID_ID:
		hex_id = talloc_asprintf(mem_ctx, "%.4x", nameid.kind.lid);
		dec_id = talloc_asprintf(mem_ctx, "%u", nameid.kind.lid);
		ldif_record = talloc_asprintf(mem_ctx, "dn: CN=0x%s,CN=%s,CN=default\nobjectClass: MNID_ID\ncn: 0x%s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropId: %s\n",
					      hex_id, guid, hex_id, guid, dec_mappedid, dec_id);
		break;
	case MNID_STRING:
		ldif_record = talloc_asprintf(mem_ctx, "dn: CN=%s,CN=%s,CN=default\nobjectClass: MNID_STRING\ncn: %s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropName: %s\n",
					      nameid.kind.lpwstr.Name, guid, nameid.kind.lpwstr.Name, guid, dec_mappedid, nameid.kind.lpwstr.Name);
		break;
	default:
		abort();
	}

	DEBUG(5, ("inserting record:\n%s\n", ldif_record));
	ldif_records[0] = ldif_record;
	ldif = ldb_ldif_read_string(ldb_ctx, ldif_records);
	ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg);
	MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
	ret = ldb_add(ldb_ctx, normalized_msg);
	talloc_free(normalized_msg);
	if (ret != LDB_SUCCESS) {
		MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
	}

	/* we invalidate the cache, if present */
	if (nameids_cache) {
		talloc_free(nameids_cache);
		nameids_cache = NULL;
	}

	return ret;
}
Пример #9
0
static enum mapistore_error transaction_commit(struct namedprops_context *self)
{
	MYSQL *conn = self->data;
	int res = mysql_query(conn, "COMMIT");
	MAPISTORE_RETVAL_IF(res, MAPISTORE_ERR_DATABASE_OPS, NULL);
	return MAPISTORE_SUCCESS;
}
/**
   \details return the next unmapped property ID

   \param ldb_ctx pointer to the namedprops ldb context

   \return 0 on error, the next mapped id otherwise
 */
_PUBLIC_ uint16_t mapistore_namedprops_next_unused_id(struct ldb_context *ldb_ctx)
{
	uint16_t		highest_id = 0, current_id;
	TALLOC_CTX		*mem_ctx;
	struct ldb_result	*res = NULL;
	const char * const	attrs[] = { "mappedId", NULL };
	int			ret;
	unsigned int		i;

	mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");

	ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
			 LDB_SCOPE_SUBTREE, attrs, "(cn=*)");
	MAPISTORE_RETVAL_IF(ret != LDB_SUCCESS, 0, mem_ctx);

	for (i = 0; i < res->count; i++) {
		current_id = ldb_msg_find_attr_as_uint(res->msgs[i], "mappedId", 0);
		if (current_id > 0 && highest_id < current_id) {
			highest_id = current_id;
		}
	}

	talloc_free(mem_ctx);

	DEBUG(5, ("next_mapped_id: %d\n", (highest_id + 1)));

	return (highest_id + 1);
}
Пример #11
0
/**
   \details Open connection to indexing database for a given user

   \param mstore_ctx pointer to the mapistore context
   \param username name for which the indexing database has to be
   created
   \param connection_string mysql connection string
   \param ictxp returned value with the indexing context created

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
_PUBLIC_ enum mapistore_error mapistore_indexing_mysql_init(struct mapistore_context *mstore_ctx,
							    const char *username,
							    const char *connection_string,
							    struct indexing_context **ictxp)
{
	struct indexing_context	*ictx;
	bool			schema_created;
	char			*schema_file;
	MYSQL			*conn = NULL;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!connection_string, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!ictxp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	ictx = talloc_zero(mstore_ctx, struct indexing_context);
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NO_MEMORY, NULL);

	ictx->data = create_connection(connection_string, &conn);
	talloc_set_destructor(ictx, mapistore_indexing_mysql_destructor);
	MAPISTORE_RETVAL_IF(!ictx->data, MAPISTORE_ERR_NOT_INITIALIZED, ictx);
	if (!table_exists(conn, INDEXING_TABLE)) {
		DEBUG(3, ("Creating schema for indexing on mysql %s\n",
			  connection_string));

		schema_file = talloc_asprintf(ictx, "%s/%s", MAPISTORE_LDIF, INDEXING_SCHEMA_FILE);
		MAPISTORE_RETVAL_IF(!schema_file, MAPISTORE_ERR_NO_MEMORY, NULL);
		schema_created = create_schema(MYSQL(ictx), schema_file);
		talloc_free(schema_file);

		MAPISTORE_RETVAL_IF(!schema_created, MAPISTORE_ERR_NOT_INITIALIZED, ictx);
	}


	/* TODO: extract url from backend mapping, by the moment we use the username */
	ictx->url = talloc_strdup(ictx, username);
	MAPISTORE_RETVAL_IF(!ictx->url, MAPISTORE_ERR_NO_MEMORY, NULL);

	/* Fill function pointers */
	ictx->add_fmid = mysql_record_add;
	ictx->del_fmid = mysql_record_del;
	ictx->update_fmid = mysql_record_update;
	ictx->get_uri = mysql_record_get_uri;
	ictx->get_fmid = mysql_record_get_fmid;
	ictx->allocate_fmid = mysql_record_allocate_fmid;
	ictx->allocate_fmids = mysql_record_allocate_fmids;

	*ictxp = ictx;

	return MAPISTORE_SUCCESS;
}
Пример #12
0
static enum mapistore_error get_nameid(struct namedprops_context *self,
				       uint16_t mapped_id,
				       TALLOC_CTX *mem_ctx,
				       struct MAPINAMEID **nameidp)
{
	TALLOC_CTX *local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	MYSQL *conn = self->data;
	const char *sql = talloc_asprintf(local_mem_ctx,
		"SELECT type, oleguid, propName, propId FROM "NAMEDPROPS_MYSQL_TABLE" "
		"WHERE mappedId=%d", mapped_id);
	if (mysql_query(conn, sql) != 0) {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_DATABASE_OPS,
				    local_mem_ctx);
	}
	MYSQL_RES *res = mysql_store_result(conn);
	if (mysql_num_rows(res) == 0) {
		// Not found
		mysql_free_result(res);
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_NOT_FOUND,
				    local_mem_ctx);
	}
	MYSQL_ROW row = mysql_fetch_row(res);

	enum mapistore_error ret = MAPISTORE_SUCCESS;
	struct MAPINAMEID *nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
	const char *guid = row[1];
	GUID_from_string(guid, &nameid->lpguid);
	int type = strtol(row[0], NULL, 10);
	nameid->ulKind = type;
	if (type == MNID_ID) {
		nameid->kind.lid = strtol(row[3], NULL, 10);
	} else if (type == MNID_STRING) {
		const char *propName = row[2];
		nameid->kind.lpwstr.NameSize = strlen(propName) * 2 + 2;//FIXME WHY *2+2 and not just +1?
		nameid->kind.lpwstr.Name = talloc_strdup(nameid, propName);
	} else {
		nameid = NULL;
		ret = MAPISTORE_ERROR;
	}

	*nameidp = nameid;

	mysql_free_result(res);
	talloc_free(local_mem_ctx);

	return ret;
}
Пример #13
0
static enum mapistore_error get_mapped_id(struct namedprops_context *self,
					  struct MAPINAMEID nameid,
					  uint16_t *mapped_id)
{
	TALLOC_CTX *mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	int type = nameid.ulKind;
	char *guid = GUID_string(mem_ctx, &nameid.lpguid);
	MYSQL *conn = self->data;

	char *sql = NULL;
	if (type == MNID_ID) {
		uint32_t prop_id = nameid.kind.lid;
		sql = talloc_asprintf(mem_ctx,
			"SELECT mappedId FROM "NAMEDPROPS_MYSQL_TABLE" "
			"WHERE `type`=%d AND `oleguid`='%s' AND `propId`=%d",
			type, guid, prop_id);
	} else if (type == MNID_STRING) {
		const char *prop_name = nameid.kind.lpwstr.Name;
		sql = talloc_asprintf(mem_ctx,
			"SELECT mappedId FROM "NAMEDPROPS_MYSQL_TABLE" "
			"WHERE `type`=%d AND `oleguid`='%s' AND `propName`='%s'",
			type, guid, prop_name);
	} else {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERROR, mem_ctx);
	}

	if (mysql_query(conn, sql) != 0) {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);
	}

	MYSQL_RES *res = mysql_store_result(conn);
	if (mysql_num_rows(res) == 0) {
		// Not found
		mysql_free_result(res);
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_NOT_FOUND, mem_ctx);
	}
	MYSQL_ROW row = mysql_fetch_row(res);
	*mapped_id = strtol(row[0], NULL, 10);
	mysql_free_result(res);

	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
Пример #14
0
static enum mapistore_error create_id(struct namedprops_context *self,
				      struct MAPINAMEID nameid,
				      uint16_t mapped_id)
{
	TALLOC_CTX *mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	const char **fields = (const char **) str_list_make_empty(mem_ctx);

	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "type=%d",
						      nameid.ulKind));
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "propType=%d",
						      PT_NULL));
	char *guid = GUID_string(mem_ctx, &nameid.lpguid);
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "oleguid='%s'",
						      guid));
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "mappedId=%u",
						      mapped_id));
	if (nameid.ulKind == MNID_ID) {
		fields = str_list_add(fields,
				      talloc_asprintf(mem_ctx, "propId=%u",
						      nameid.kind.lid));
	} else if (nameid.ulKind == MNID_STRING) {
		fields = str_list_add(fields,
				      talloc_asprintf(mem_ctx, "propName='%s'",
						      nameid.kind.lpwstr.Name));
	} else {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERROR, mem_ctx);
	}

	char *fields_sql = str_list_join(mem_ctx, fields, ',');
	char *sql = talloc_asprintf(mem_ctx,
		"INSERT INTO " NAMEDPROPS_MYSQL_TABLE " SET %s", fields_sql);
	DEBUG(5, ("Inserting record:\n%s\n", sql));
	MYSQL *conn = self->data;
	if (mysql_query(conn, sql) != 0) {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);
	}

	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
Пример #15
0
/**
  \details Adds FMID and related URL in indexing database

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param fmid FMID to record
  \param mapistore_URI mapistore URI string to associate with fmid

  \return MAPISTORE_SUCCESS on success,
	  MAPISTORE_ERR_EXIST if such entry already exists
	  MAPISTORE_ERR_NOT_INITIALIZED if ictx pointer is invalid (NULL)
	  MAPISTORE_ERR_INVALID_PARAMETER in case other parameters are not valid
	  MAPISTORE_ERR_DATABASE_OPS in case of MySQL error
 */
static enum mapistore_error mysql_record_add(struct indexing_context *ictx,
					   const char *username,
					   uint64_t fmid,
					   const char *mapistore_URI)
{
	int		ret;
	bool		IsSoftDeleted = false;
	char		*sql;
	TALLOC_CTX	*mem_ctx;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!mapistore_URI, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Check if the fid/mid doesn't already exist within the database */
	ret = mysql_search_existing_fmid(ictx, username, fmid, &IsSoftDeleted);
	MAPISTORE_RETVAL_IF(ret == MAPISTORE_SUCCESS, MAPISTORE_ERR_EXIST, NULL);

	mem_ctx = talloc_new(NULL);
	sql = talloc_asprintf(mem_ctx,
		"INSERT INTO %s "
		"(username, fmid, url, soft_deleted) "
		"VALUES ('%s', %"PRIu64", '%s', '%d')",
		INDEXING_TABLE, _sql(mem_ctx, username), fmid,
		_sql(mem_ctx, mapistore_URI), 0);

	ret = execute_query(MYSQL(ictx), sql);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
/**
   \details return the mapped property ID matching the nameid
   structure passed in parameter.

   \param ldb_ctx pointer to the namedprops ldb context
   \param nameid the MAPINAMEID structure to lookup
   \param propID pointer to the property ID the function returns

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
 */
_PUBLIC_ enum mapistore_error mapistore_namedprops_get_mapped_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t *propID)
{
	TALLOC_CTX		*mem_ctx;
	struct ldb_result	*res = NULL;
	const char * const	attrs[] = { "*", NULL };
	int			ret;
	char			*filter = NULL;
	char			*guid;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERROR, NULL);
	MAPISTORE_RETVAL_IF(!propID, MAPISTORE_ERROR, NULL);

	*propID = 0;
	mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");
	guid = GUID_string(mem_ctx, (const struct GUID *)&nameid.lpguid);

	switch (nameid.ulKind) {
	case MNID_ID:
		filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_ID)(oleguid=%s)(cn=0x%.4x))",
					 guid, nameid.kind.lid);
		break;
	case MNID_STRING:
		filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_STRING)(oleguid=%s)(cn=%s))",
					 guid, nameid.kind.lpwstr.Name);
		break;
	}
	talloc_free(guid);

	ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
			 LDB_SCOPE_SUBTREE, attrs, "%s", filter);
	MAPISTORE_RETVAL_IF((ret != LDB_SUCCESS || !res->count), MAPISTORE_ERROR, mem_ctx);

	*propID = ldb_msg_find_attr_as_uint(res->msgs[0], "mappedId", 0);
	MAPISTORE_RETVAL_IF(!*propID, MAPISTORE_ERROR, mem_ctx);

	talloc_free(mem_ctx);

	return MAPISTORE_SUCCESS;
}
Пример #17
0
static enum mapistore_error tdb_record_add(struct indexing_context *ictx,
					   const char *username,
					   uint64_t fmid,
					   const char *mapistore_URI)
{
	int		ret;
	TDB_DATA	key;
	TDB_DATA	dbuf;
	bool		IsSoftDeleted = false;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!mapistore_URI, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Check if the fid/mid doesn't already exist within the database */
	ret = tdb_search_existing_fmid(ictx, username, fmid, &IsSoftDeleted);
	MAPISTORE_RETVAL_IF(ret, ret, NULL);

	/* Add the record given its fid and mapistore_uri */
	key.dptr = (unsigned char *) talloc_asprintf(ictx, "0x%.16"PRIx64, fmid);
	key.dsize = strlen((const char *) key.dptr);

	dbuf.dptr = (unsigned char *) talloc_strdup(ictx, mapistore_URI);
	dbuf.dsize = strlen((const char *) dbuf.dptr);

	ret = tdb_store(TDB_WRAP(ictx)->tdb, key, dbuf, TDB_INSERT);
	talloc_free(key.dptr);
	talloc_free(dbuf.dptr);

	if (ret == -1) {
		OC_DEBUG(3, "Unable to create 0x%.16"PRIx64" record: %s\n", fmid,
				 mapistore_URI);
		return MAPISTORE_ERR_DATABASE_OPS;
	}

	return MAPISTORE_SUCCESS;
}
Пример #18
0
/**
   \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 return the nameid structture matching the mapped property ID
   passed in parameter.

   \param ldb_ctx pointer to the namedprops ldb context
   \param propID the property ID to lookup
   \param nameid pointer to the MAPINAMEID structure the function returns

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
 */
_PUBLIC_ enum mapistore_error mapistore_namedprops_get_nameid(struct ldb_context *ldb_ctx, 
							      uint16_t propID,
							      struct MAPINAMEID **nameidp)
{
	TALLOC_CTX			*mem_ctx;
	struct ldb_result		*res = NULL;
	const char * const		attrs[] = { "*", NULL };
	int				ret;
	const char			*guid, *oClass, *cn;
        struct MAPINAMEID		*nameid;
	int				rc = MAPISTORE_SUCCESS;
	uint16_t			propidx;
					     
	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERROR, NULL);
	MAPISTORE_RETVAL_IF(!nameidp, MAPISTORE_ERROR, NULL);
	MAPISTORE_RETVAL_IF(propID < 0x8000, MAPISTORE_ERROR, NULL);

	if (!nameids_cache) {
		nameids_cache = talloc_array(NULL, struct MAPINAMEID *, 0x8000);
		memset(nameids_cache, 0, 0x8000 * sizeof (struct MAPINAMEID *));
	}
Пример #20
0
/**
   \details Retrieve MySQL backend parametric options from
   configuration file and store them into a data structure.

   \param lp_ctx Pointer to the loadparm context
   \param p pointer to the structure with individual
   parameters to return

   \return MAPISTORE_SUCCES on success, otherwise MAPISTORE error
 */
enum mapistore_error mapistore_namedprops_mysql_parameters(struct loadparm_context *lp_ctx,
							   struct namedprops_mysql_params *p)
{
	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!lp_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!p, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Retrieve parametric options */
	p->data = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_data");
	p->sock = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_sock");
	p->user = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_user");
	p->pass = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_pass");
	p->host = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_host");
	p->port = lpcfg_parm_int(lp_ctx, NULL, "namedproperties", "mysql_port", 3306);
	p->db = lpcfg_parm_string(lp_ctx, NULL, "namedproperties", "mysql_db");

	/* Enforce the logic */
	MAPISTORE_RETVAL_IF(!p->user, MAPISTORE_ERR_BACKEND_INIT, NULL);
	MAPISTORE_RETVAL_IF(!p->db, MAPISTORE_ERR_BACKEND_INIT, NULL);
	MAPISTORE_RETVAL_IF(!p->host && !p->sock, MAPISTORE_ERR_BACKEND_INIT, NULL);

	return MAPISTORE_SUCCESS;
}
Пример #21
0
static enum mapistore_error tdb_record_del(struct indexing_context *ictx,
					   const char *username,
					   uint64_t fmid,
					   uint8_t flags)
{
	int				ret;
	TDB_DATA			key;
	TDB_DATA			newkey;
	TDB_DATA			dbuf;
	bool				IsSoftDeleted = false;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Check if the fid/mid still exists within the database */
	ret = tdb_search_existing_fmid(ictx, username, fmid, &IsSoftDeleted);
	MAPISTORE_RETVAL_IF(!ret, ret, NULL);

	if (IsSoftDeleted == true) {
		key.dptr = (unsigned char *) talloc_asprintf(ictx, "%s0x%.16"PRIx64,
							     MAPISTORE_SOFT_DELETED_TAG, fmid);
	} else {
		key.dptr = (unsigned char *) talloc_asprintf(ictx, "0x%.16"PRIx64, fmid);
	}
	key.dsize = strlen((const char *) key.dptr);

	switch (flags) {
	case MAPISTORE_SOFT_DELETE:
		/* nothing to do if the record is already soft deleted */
		MAPISTORE_RETVAL_IF(IsSoftDeleted == true, MAPISTORE_SUCCESS, NULL);
		newkey.dptr = (unsigned char *) talloc_asprintf(ictx, "%s0x%.16"PRIx64,
								MAPISTORE_SOFT_DELETED_TAG,
								fmid);
		newkey.dsize = strlen ((const char *)newkey.dptr);
		/* Retrieve previous value */
		dbuf = tdb_fetch(TDB_WRAP(ictx)->tdb, key);
		/* Add new record */
		ret = tdb_store(TDB_WRAP(ictx)->tdb, newkey, dbuf, TDB_INSERT);
		free(dbuf.dptr);
		/* Delete previous record */
		ret = tdb_delete(TDB_WRAP(ictx)->tdb, key);
		talloc_free(key.dptr);
		talloc_free(newkey.dptr);
		break;
	case MAPISTORE_PERMANENT_DELETE:
		ret = tdb_delete(TDB_WRAP(ictx)->tdb, key);
		talloc_free(key.dptr);
		MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_OPS, NULL);
		break;
	default:
		return MAPISTORE_ERR_INVALID_PARAMETER;
	}

	return MAPISTORE_SUCCESS;
}
Пример #22
0
static enum mapistore_error tdb_search_existing_fmid(struct indexing_context *ictx,
						     const char *username,
						     uint64_t fmid, bool *IsSoftDeleted)
{
	int		ret;
	TDB_DATA	key;

	/* Sanity */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!IsSoftDeleted, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	key.dptr = (unsigned char *) talloc_asprintf(ictx, "0x%.16"PRIx64, fmid);
	key.dsize = strlen((const char *)key.dptr);
	*IsSoftDeleted = false;

	ret = tdb_exists(TDB_WRAP(ictx)->tdb, key);
	talloc_free(key.dptr);

	/* If it doesn't exist look for a SOFT_DELETED entry */
	if (!ret) {
		key.dptr = (unsigned char *) talloc_asprintf(ictx, "%s0x%.16"PRIx64,
							     MAPISTORE_SOFT_DELETED_TAG,
							     fmid);
		key.dsize = strlen((const char *)key.dptr);
		ret = tdb_exists(TDB_WRAP(ictx)->tdb, key);
		if (ret) {
			*IsSoftDeleted = true;
		}
	}

	MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_EXIST, NULL);

	return MAPISTORE_SUCCESS;
}
Пример #23
0
/**
  \details Get FMID by mapistore URI.

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param uri mapistore URI or pattern to search for
  \param partia if true, uri is pattern to search for
  \param fmidp pointer to valid location to store found FMID
  \param soft_deletedp Pointer to bool var to return Soft Deleted state

  \return MAPISTORE_SUCCESS on success
	  MAPISTORE_ERR_NOT_FOUND if uri does not exists in DB
	  MAPISTORE_ERR_NOT_INITIALIZED if ictx pointer is invalid (NULL)
	  MAPISTORE_ERR_INVALID_PARAMETER in case other parameters are not valid
	  MAPISTORE_ERR_DATABASE_OPS in case of MySQL error
 */
static enum mapistore_error mysql_record_get_fmid(struct indexing_context *ictx,
						  const char *username,
						  const char *uri,
						  bool partial,
						  uint64_t *fmidp,
						  bool *soft_deletedp)
{
	enum MYSQLRESULT	ret;
	char			*sql, *uri_like;
	MYSQL_RES		*res;
	MYSQL_ROW		row;
	TALLOC_CTX		*mem_ctx;

	// Sanity checks
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmidp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!soft_deletedp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	mem_ctx = talloc_named(NULL, 0, "mysql_record_get_fmid");

	sql = talloc_asprintf(mem_ctx,
		"SELECT fmid, soft_deleted FROM "INDEXING_TABLE" "
		"WHERE username = '******'", _sql(mem_ctx, username));
	if (partial) {
		uri_like = talloc_strdup(mem_ctx, uri);
		string_replace(uri_like, '*', '%');
		sql = talloc_asprintf_append(sql, " AND url LIKE '%s'",
					     _sql(mem_ctx, uri_like));
	} else {
		sql = talloc_asprintf_append(sql, " AND url = '%s'",
					     _sql(mem_ctx, uri));
	}

	ret = select_without_fetch(MYSQL(ictx), sql, &res);
	MAPISTORE_RETVAL_IF(ret == MYSQL_NOT_FOUND, MAPISTORE_ERR_NOT_FOUND, mem_ctx);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	row = mysql_fetch_row(res);

	*fmidp = strtoull(row[0], NULL, 0);
	*soft_deletedp = strtoull(row[1], NULL, 0) == 1;

	mysql_free_result(res);
	talloc_free(mem_ctx);

	return MAPISTORE_SUCCESS;
}
Пример #24
0
/**
   \details Return the next unused namedprops ID

   \param nprops pointer to the namedprops creontext
   \param highest_id pointer to the next ID to return

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
static enum mapistore_error next_unused_id(struct namedprops_context *nprops,
					   uint16_t *highest_id)
{
	TALLOC_CTX	*mem_ctx;
	MYSQL		*conn;
	MYSQL_RES	*res;
	MYSQL_ROW	row;
	char		*sql_query;
	int		ret;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!nprops, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!highest_id, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	conn = (MYSQL *) nprops->data;
	MAPISTORE_RETVAL_IF(!conn, MAPISTORE_ERR_DATABASE_OPS, NULL);

	mem_ctx = talloc_named(NULL, 0, "next_unused_id");
	MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_NO_MEMORY, NULL);

	sql_query = talloc_asprintf(mem_ctx, "SELECT max(mappedId) FROM %s", NAMEDPROPS_MYSQL_TABLE);
	MAPISTORE_RETVAL_IF(!sql_query, MAPISTORE_ERR_NO_MEMORY, mem_ctx);

	ret = mysql_query(conn, sql_query);
	talloc_free(sql_query);
	MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	res = mysql_store_result(conn);
	MAPISTORE_RETVAL_IF(!res, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	row = mysql_fetch_row(res);
	if (!row) {
		mysql_free_result(res);
		mapistore_set_errno(MAPISTORE_ERR_DATABASE_OPS);
		talloc_free(mem_ctx);
		return MAPISTORE_ERR_DATABASE_OPS;
	}

	*highest_id = strtol(row[0], NULL, 10);

	mysql_free_result(res);
	talloc_free(mem_ctx);

	*highest_id = *highest_id + 1;
	return MAPISTORE_SUCCESS;
}
Пример #25
0
/**
  \details Delete FMID mapping from database.
	   Note that function will succeed when there is no such FMID

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param fmid FMID to delete
  \param flags MAPISTORE_SOFT_DELETE - soft delete the entry,
	       MAPISTORE_PERMANENT_DELETE - permanently delete

  \return MAPISTORE_SUCCESS on success
	  MAPISTORE_ERR_NOT_INITIALIZED if ictx pointer is invalid (NULL)
	  MAPISTORE_ERR_INVALID_PARAMETER in case other parameters are not valid
	  MAPISTORE_ERR_DATABASE_OPS in case of MySQL error
 */
static enum mapistore_error mysql_record_del(struct indexing_context *ictx,
					     const char *username,
					     uint64_t fmid,
					     uint8_t flags)
{
	int		ret;
	bool		IsSoftDeleted = false;
	char		*sql;
	TALLOC_CTX	*mem_ctx;


	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	/* Check if the fid/mid still exists within the database */
	ret = mysql_search_existing_fmid(ictx, username, fmid, &IsSoftDeleted);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_SUCCESS, NULL);

	mem_ctx = talloc_new(NULL);

	switch (flags) {
	case MAPISTORE_SOFT_DELETE:
		/* nothing to do if the record is already soft deleted */
		MAPISTORE_RETVAL_IF(IsSoftDeleted == true, MAPISTORE_SUCCESS, NULL);
		sql = talloc_asprintf(mem_ctx,
			"UPDATE %s "
			"SET soft_deleted=1 "
			"WHERE username = '******' AND fmid = %"PRIu64,
			INDEXING_TABLE, _sql(mem_ctx, username), fmid);
		break;
	case MAPISTORE_PERMANENT_DELETE:
		sql = talloc_asprintf(mem_ctx,
			"DELETE FROM %s "
			"WHERE username = '******' AND fmid = %"PRIu64,
			INDEXING_TABLE, _sql(mem_ctx, username), fmid);
		break;
	default:
		talloc_free(mem_ctx);
		return MAPISTORE_ERR_INVALID_PARAMETER;
	}

	execute_query(MYSQL(ictx), sql);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
Пример #26
0
/**
  \details Get mapistore URI by FMID.

  \param ictx valid pointer to indexing context
  \param username samAccountName for current user
  \param mem_ctx TALLOC_CTX to allocate mapistore URI
  \param fmid FMID to search for
  \param soft_deletedp Pointer to bool var to return Soft Deleted state

  \return MAPISTORE_SUCCESS on success
	  MAPISTORE_ERR_NOT_INITIALIZED if ictx pointer is invalid (NULL)
	  MAPISTORE_ERR_INVALID_PARAMETER in case other parameters are not valid
	  MAPISTORE_ERR_DATABASE_OPS in case of MySQL error
 */
static enum mapistore_error mysql_record_get_uri(struct indexing_context *ictx,
						 const char *username,
						 TALLOC_CTX *mem_ctx,
						 uint64_t fmid,
						 char **urip,
						 bool *soft_deletedp)
{
	int		ret;
	char		*sql;
	MYSQL_RES	*res;
	MYSQL_ROW	row;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!urip, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!soft_deletedp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);


	sql = talloc_asprintf(mem_ctx,
		"SELECT url, soft_deleted FROM %s "
		"WHERE username = '******' AND fmid = %"PRIu64,
		INDEXING_TABLE, _sql(mem_ctx, username), fmid);

	ret = select_without_fetch(MYSQL(ictx), sql, &res);
	MAPISTORE_RETVAL_IF(ret == MYSQL_NOT_FOUND, MAPISTORE_ERR_NOT_FOUND, sql);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, sql);

	row = mysql_fetch_row(res);

	*urip = talloc_strdup(mem_ctx, row[0]);
	*soft_deletedp = strtoull(row[1], NULL, 0) == 1;

	talloc_free(sql);
	return MAPISTORE_SUCCESS;
}
/**
   \details Initialize the named properties database or return pointer
   to the existing one if already initialized/opened.

   \param mem_ctx pointer to the memory context
   \param ldb_ctx pointer on pointer to the ldb context the function
   returns

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
enum mapistore_error mapistore_namedprops_init(TALLOC_CTX *mem_ctx, struct ldb_context **_ldb_ctx)
{
	int			ret;
	struct stat		sb;
	struct ldb_context	*ldb_ctx = NULL;
	struct ldb_ldif		*ldif;
	char			*filename;
	FILE			*f;
	struct tevent_context	*ev;
	char			*database;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
	MAPISTORE_RETVAL_IF(!_ldb_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);

	ev = tevent_context_init(mem_ctx);
	MAPISTORE_RETVAL_IF(!ev, MAPISTORE_ERR_NO_MEMORY, NULL);

	database = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAMED);
	DEBUG(0, ("database = %s\n", database));

	/* Step 1. Stat the database and populate it if it doesn't exist */
	if (stat(database, &sb) == -1) {
		ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0);
		talloc_free(database);
		MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL);

		filename = talloc_asprintf(mem_ctx, "%s/mapistore_namedprops.ldif", 
					   mapistore_namedprops_get_ldif_path());
		f = fopen(filename, "r");
		talloc_free(filename);
		MAPISTORE_RETVAL_IF(!f, MAPISTORE_ERROR, NULL);
		
		ldb_transaction_start(ldb_ctx);

		while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) {
			struct ldb_message *normalized_msg;
			ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg);
			MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
			ret = ldb_add(ldb_ctx, normalized_msg);
			talloc_free(normalized_msg);
			if (ret != LDB_SUCCESS) {
				fclose(f);
				MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
			}
			ldb_ldif_read_free(ldb_ctx, ldif);
		}

		ldb_transaction_commit(ldb_ctx);
		fclose(f);

	} else {
		ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0);
		talloc_free(database);
		MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL);
	}

	*_ldb_ctx = ldb_ctx;

	return MAPISTORE_SUCCESS;
}
Пример #28
0
/**
  \details Initialize the database and provision it

  \param conn pointer to the MySQL context
  \param schema_path pointer to the path holding schema files

  \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 */
static enum mapistore_error initialize_database(MYSQL *conn, const char *schema_path)
{
	TALLOC_CTX		*mem_ctx;
	enum mapistore_error	retval = MAPISTORE_SUCCESS;
	struct ldb_context	*ldb_ctx;
	struct ldb_ldif		*ldif;
	struct ldb_message	*msg;
	int			ret;
	char			*filename;
	FILE			*f;
	bool			inserted;
	bool			schema_created;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!conn, MAPISTORE_ERR_DATABASE_INIT, NULL);

	mem_ctx = talloc_named(NULL, 0, "initialize_database");
	MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_NO_MEMORY, NULL);

	filename = talloc_asprintf(mem_ctx, "%s/" NAMEDPROPS_MYSQL_SCHEMA,
				   schema_path ? schema_path : mapistore_namedprops_get_ldif_path());
	MAPISTORE_RETVAL_IF(!filename, MAPISTORE_ERR_NO_MEMORY, mem_ctx);
	schema_created = create_schema(conn, filename);
	if (!schema_created) {
		DEBUG(1, ("Failed named properties schema creation, "
			  "last mysql error was: `%s`\n", mysql_error(conn)));
		MAPISTORE_RETVAL_ERR(MAPISTORE_ERR_DATABASE_INIT, mem_ctx);
	}

	ldb_ctx = ldb_init(mem_ctx, NULL);
	MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_BACKEND_INIT, mem_ctx);

	filename = talloc_asprintf(mem_ctx, "%s/mapistore_namedprops.ldif",
				   schema_path ? schema_path : mapistore_namedprops_get_ldif_path());
	MAPISTORE_RETVAL_IF(!filename, MAPISTORE_ERR_NO_MEMORY, mem_ctx);

	f = fopen(filename, "r");
	talloc_free(filename);
	MAPISTORE_RETVAL_IF(!f, MAPISTORE_ERR_BACKEND_INIT, mem_ctx);
	
	while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) {
		ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &msg);
		if (ret) {
			retval = MAPISTORE_ERR_DATABASE_INIT;
			mapistore_set_errno(MAPISTORE_ERR_DATABASE_INIT);
			goto end;
		}

		inserted = insert_ldif_msg(conn, msg);
		ldb_ldif_read_free(ldb_ctx, ldif);
		if (!inserted) {
			retval = MAPISTORE_ERR_DATABASE_OPS;
			mapistore_set_errno(MAPISTORE_ERR_DATABASE_OPS);
			goto end;
		}
	}

end:
	talloc_free(mem_ctx);
	fclose(f);

	return retval;
}
Пример #29
0
static enum mapistore_error mysql_record_allocate_fmids(struct indexing_context *ictx,
						      const char *username,
						      int count,
						      uint64_t *fmidp)
{
	int		ret;
	uint64_t	next_fmid;
	char		*sql;
	TALLOC_CTX	*mem_ctx;

	/* SANITY checks */
	MAPISTORE_RETVAL_IF(!ictx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(!fmidp, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(count < 0, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
	MAPISTORE_RETVAL_IF(count == 0, MAPISTORE_SUCCESS, NULL);

	/* Retrieve and increment the counter */
	ret = execute_query(MYSQL(ictx), "START TRANSACTION");
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, NULL);

	mem_ctx = talloc_new(NULL);
	sql = talloc_asprintf(mem_ctx,
		"SELECT next_fmid FROM %s "
		"WHERE username = '******'",
		INDEXING_ALLOC_TABLE, _sql(mem_ctx, username));
	ret = select_first_uint(MYSQL(ictx), sql, &next_fmid);
	switch (ret) {
	case MYSQL_SUCCESS:
		if (next_fmid <= MAX_PUBLIC_FOLDER_ID) {
			next_fmid = MAX_PUBLIC_FOLDER_ID + 1;
		}
		// Update next fmid
		sql = talloc_asprintf(mem_ctx,
			"UPDATE %s SET next_fmid = %"PRIu64
			" WHERE username='******'",
			INDEXING_ALLOC_TABLE,
			next_fmid + count,
			_sql(mem_ctx, username));
		break;
	case MYSQL_NOT_FOUND:
		// First allocation, insert in the database
		next_fmid = MAX_PUBLIC_FOLDER_ID + 1;
		sql = talloc_asprintf(mem_ctx,
			"INSERT INTO %s (username, next_fmid) "
			"VALUES('%s', %"PRIu64")",
			INDEXING_ALLOC_TABLE,
			_sql(mem_ctx, username),
			next_fmid + count);
		break;

	default:
		// Unknown error
		talloc_free(mem_ctx);
		return MAPISTORE_ERR_DATABASE_OPS;
	}
	ret = execute_query(MYSQL(ictx), sql);
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	ret = execute_query(MYSQL(ictx), "COMMIT");
	MAPISTORE_RETVAL_IF(ret != MYSQL_SUCCESS, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);

	*fmidp = next_fmid;

	return MAPISTORE_SUCCESS;
}