mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-29 15:36:13 +00:00 
			
		
		
		
	Add uuid wrapper API call ast_uuid_generate_str().
* Updated test_uuid.c to test the new API call. * Made system use the new API call to eliminate "10's of lines" where used. * Fixed untested ast_strdup() return in stasis_subscribe() by eliminating the need for it. struct stasis_subscription now contains the uniqueid[] string. * Fixed some issues in exchangecal_write_event(): Create uid with enough space for a UUID string to avoid a realloc. Fix off by one error if the calendar event provided a UUID string. There is no need to check for NULL before calling ast_free(). git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@384302 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -24,7 +24,7 @@ | |||||||
| #define _ASTERISK_UUID_H | #define _ASTERISK_UUID_H | ||||||
|  |  | ||||||
| /* Size of an RFC 4122 UUID string plus terminating null byte */ | /* Size of an RFC 4122 UUID string plus terminating null byte */ | ||||||
| #define AST_UUID_STR_LEN 37 | #define AST_UUID_STR_LEN (36 + 1) | ||||||
|  |  | ||||||
| struct ast_uuid; | struct ast_uuid; | ||||||
|  |  | ||||||
| @@ -50,10 +50,21 @@ struct ast_uuid *ast_uuid_generate(void); | |||||||
|  * \param uuid The UUID to convert to a string |  * \param uuid The UUID to convert to a string | ||||||
|  * \param[out] buf The buffer where the UUID string will be stored |  * \param[out] buf The buffer where the UUID string will be stored | ||||||
|  * \param size The size of the buffer. Must be at least AST_UUID_STR_LEN. |  * \param size The size of the buffer. Must be at least AST_UUID_STR_LEN. | ||||||
|  * \returns The UUID string (a pointer to buf) |  * \return The UUID string (a pointer to buf) | ||||||
|  */ |  */ | ||||||
| char *ast_uuid_to_str(const struct ast_uuid *uuid, char *buf, size_t size); | char *ast_uuid_to_str(const struct ast_uuid *uuid, char *buf, size_t size); | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |  * \brief Generate a UUID string. | ||||||
|  |  * \since 12.0.0 | ||||||
|  |  * | ||||||
|  |  * \param buf The buffer where the UUID string will be stored | ||||||
|  |  * \param size The size of the buffer. Must be at least AST_UUID_STR_LEN. | ||||||
|  |  * | ||||||
|  |  * \return The UUID string (a pointer to buf) | ||||||
|  |  */ | ||||||
|  | char *ast_uuid_generate_str(char *buf, size_t size); | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief Convert a string to a UUID |  * \brief Convert a string to a UUID | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -807,15 +807,7 @@ void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, con | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (ast_strlen_zero(id)) { | 	if (ast_strlen_zero(id)) { | ||||||
| 		struct ast_uuid *uuid = ast_uuid_generate(); | 		ast_uuid_generate_str(details->id, sizeof(details->id)); | ||||||
|  |  | ||||||
| 		if (!uuid) { |  | ||||||
| 			ao2_ref(details, -1); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		ast_uuid_to_str(uuid, details->id, AST_UUID_STR_LEN); |  | ||||||
| 		ast_free(uuid); |  | ||||||
| 	} else { | 	} else { | ||||||
| 		ast_copy_string(details->id, id, sizeof(details->id)); | 		ast_copy_string(details->id, id, sizeof(details->id)); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -106,7 +106,7 @@ const char *stasis_topic_name(const struct stasis_topic *topic) | |||||||
| /*! \internal */ | /*! \internal */ | ||||||
| struct stasis_subscription { | struct stasis_subscription { | ||||||
| 	/*! Unique ID for this subscription */ | 	/*! Unique ID for this subscription */ | ||||||
| 	char *uniqueid; | 	char uniqueid[AST_UUID_STR_LEN]; | ||||||
| 	/*! Topic subscribed to. */ | 	/*! Topic subscribed to. */ | ||||||
| 	struct stasis_topic *topic; | 	struct stasis_topic *topic; | ||||||
| 	/*! Mailbox for processing incoming messages. */ | 	/*! Mailbox for processing incoming messages. */ | ||||||
| @@ -121,8 +121,6 @@ static void subscription_dtor(void *obj) | |||||||
| { | { | ||||||
| 	struct stasis_subscription *sub = obj; | 	struct stasis_subscription *sub = obj; | ||||||
| 	ast_assert(!stasis_subscription_is_subscribed(sub)); | 	ast_assert(!stasis_subscription_is_subscribed(sub)); | ||||||
| 	ast_free(sub->uniqueid); |  | ||||||
| 	sub->uniqueid = NULL; |  | ||||||
| 	ao2_cleanup(sub->topic); | 	ao2_cleanup(sub->topic); | ||||||
| 	sub->topic = NULL; | 	sub->topic = NULL; | ||||||
| 	ast_taskprocessor_unreference(sub->mailbox); | 	ast_taskprocessor_unreference(sub->mailbox); | ||||||
| @@ -134,27 +132,19 @@ static void send_subscription_change_message(struct stasis_topic *topic, char *u | |||||||
| struct stasis_subscription *stasis_subscribe(struct stasis_topic *topic, stasis_subscription_cb callback, void *data) | struct stasis_subscription *stasis_subscribe(struct stasis_topic *topic, stasis_subscription_cb callback, void *data) | ||||||
| { | { | ||||||
| 	RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup); | 	RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup); | ||||||
| 	RAII_VAR(struct ast_uuid *, id, NULL, ast_free); |  | ||||||
| 	char uniqueid[AST_UUID_STR_LEN]; |  | ||||||
|  |  | ||||||
| 	sub = ao2_alloc(sizeof(*sub), subscription_dtor); | 	sub = ao2_alloc(sizeof(*sub), subscription_dtor); | ||||||
| 	if (!sub) { | 	if (!sub) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	id = ast_uuid_generate(); | 	ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid)); | ||||||
| 	if (!id) { |  | ||||||
| 		ast_log(LOG_ERROR, "UUID generation failed\n"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	ast_uuid_to_str(id, uniqueid, sizeof(uniqueid)); |  | ||||||
|  |  | ||||||
| 	sub->mailbox = ast_threadpool_serializer(uniqueid, pool); | 	sub->mailbox = ast_threadpool_serializer(sub->uniqueid, pool); | ||||||
| 	if (!sub->mailbox) { | 	if (!sub->mailbox) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sub->uniqueid = ast_strdup(uniqueid); |  | ||||||
| 	ao2_ref(topic, +1); | 	ao2_ref(topic, +1); | ||||||
| 	sub->topic = topic; | 	sub->topic = topic; | ||||||
| 	sub->callback = callback; | 	sub->callback = callback; | ||||||
| @@ -163,7 +153,7 @@ struct stasis_subscription *stasis_subscribe(struct stasis_topic *topic, stasis_ | |||||||
| 	if (topic_add_subscription(topic, sub) != 0) { | 	if (topic_add_subscription(topic, sub) != 0) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 	send_subscription_change_message(topic, uniqueid, "Subscribe"); | 	send_subscription_change_message(topic, sub->uniqueid, "Subscribe"); | ||||||
|  |  | ||||||
| 	ao2_ref(sub, +1); | 	ao2_ref(sub, +1); | ||||||
| 	return sub; | 	return sub; | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								main/uuid.c
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								main/uuid.c
									
									
									
									
									
								
							| @@ -38,13 +38,17 @@ struct ast_uuid { | |||||||
| 	uuid_t uu; | 	uuid_t uu; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct ast_uuid *ast_uuid_generate(void) | /*! | ||||||
|  |  * \internal | ||||||
|  |  * \brief Generate a UUID. | ||||||
|  |  * \since 12.0.0 | ||||||
|  |  * | ||||||
|  |  * \param uuid Fill this with a generated UUID. | ||||||
|  |  * | ||||||
|  |  * \return Nothing | ||||||
|  |  */ | ||||||
|  | static void generate_uuid(struct ast_uuid *uuid) | ||||||
| { | { | ||||||
| 	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid)); |  | ||||||
|  |  | ||||||
| 	if (!uuid) { |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	/* libuuid provides three methods of generating uuids, | 	/* libuuid provides three methods of generating uuids, | ||||||
| 	 * uuid_generate(), uuid_generate_random(), and uuid_generate_time(). | 	 * uuid_generate(), uuid_generate_random(), and uuid_generate_time(). | ||||||
| 	 * | 	 * | ||||||
| @@ -114,6 +118,16 @@ struct ast_uuid *ast_uuid_generate(void) | |||||||
| 	if (!has_dev_urandom) { | 	if (!has_dev_urandom) { | ||||||
| 		ast_mutex_unlock(&uuid_lock); | 		ast_mutex_unlock(&uuid_lock); | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct ast_uuid *ast_uuid_generate(void) | ||||||
|  | { | ||||||
|  | 	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid)); | ||||||
|  |  | ||||||
|  | 	if (!uuid) { | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	generate_uuid(uuid); | ||||||
| 	return uuid; | 	return uuid; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -124,10 +138,19 @@ char *ast_uuid_to_str(const struct ast_uuid *uuid, char *buf, size_t size) | |||||||
| 	return buf; | 	return buf; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | char *ast_uuid_generate_str(char *buf, size_t size) | ||||||
|  | { | ||||||
|  | 	struct ast_uuid uuid; | ||||||
|  |  | ||||||
|  | 	generate_uuid(&uuid); | ||||||
|  | 	return ast_uuid_to_str(&uuid, buf, size); | ||||||
|  | } | ||||||
|  |  | ||||||
| struct ast_uuid *ast_str_to_uuid(const char *str) | struct ast_uuid *ast_str_to_uuid(const char *str) | ||||||
| { | { | ||||||
| 	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid)); | 	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid)); | ||||||
| 	int res; | 	int res; | ||||||
|  |  | ||||||
| 	if (!uuid) { | 	if (!uuid) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| @@ -143,6 +166,7 @@ struct ast_uuid *ast_str_to_uuid(const char *str) | |||||||
| struct ast_uuid *ast_uuid_copy(const struct ast_uuid *src) | struct ast_uuid *ast_uuid_copy(const struct ast_uuid *src) | ||||||
| { | { | ||||||
| 	struct ast_uuid *dst = ast_malloc(sizeof(*dst)); | 	struct ast_uuid *dst = ast_malloc(sizeof(*dst)); | ||||||
|  |  | ||||||
| 	if (!dst) { | 	if (!dst) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| @@ -202,5 +226,4 @@ void ast_uuid_init(void) | |||||||
| 	uuid_generate_random(uu); | 	uuid_generate_random(uu); | ||||||
|  |  | ||||||
| 	ast_debug(1, "UUID system initiated\n"); | 	ast_debug(1, "UUID system initiated\n"); | ||||||
| 	return; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -243,17 +243,9 @@ static void *unref_exchangecal(void *obj) | |||||||
| static struct ast_str *generate_exchange_uuid(struct ast_str *uid) | static struct ast_str *generate_exchange_uuid(struct ast_str *uid) | ||||||
| { | { | ||||||
| 	char buffer[AST_UUID_STR_LEN]; | 	char buffer[AST_UUID_STR_LEN]; | ||||||
| 	struct ast_uuid *uuid = ast_uuid_generate(); |  | ||||||
|  |  | ||||||
| 	if (!uuid) { |  | ||||||
| 		ast_str_set(&uid, 0, "%s", ""); |  | ||||||
| 		return uid; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ast_str_set(&uid, 0, "%s", ast_uuid_to_str(uuid, buffer, AST_UUID_STR_LEN)); |  | ||||||
|  |  | ||||||
| 	ast_free(uuid); |  | ||||||
|  |  | ||||||
|  | 	ast_uuid_generate_str(buffer, sizeof(buffer)); | ||||||
|  | 	ast_str_set(&uid, 0, "%s", buffer); | ||||||
| 	return uid; | 	return uid; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -414,9 +406,17 @@ static struct ast_str *exchangecal_request(struct exchangecal_pvt *pvt, const ch | |||||||
|  |  | ||||||
| static int exchangecal_write_event(struct ast_calendar_event *event) | static int exchangecal_write_event(struct ast_calendar_event *event) | ||||||
| { | { | ||||||
| 	struct ast_str *body = NULL, *response = NULL, *subdir = NULL; | 	struct ast_str *body = NULL; | ||||||
| 	struct ast_str *uid = NULL, *summary = NULL, *description = NULL, *organizer = NULL, | 	struct ast_str *response = NULL; | ||||||
| 	               *location = NULL, *start = NULL, *end = NULL, *busystate = NULL; | 	struct ast_str *subdir = NULL; | ||||||
|  | 	struct ast_str *uid = NULL; | ||||||
|  | 	struct ast_str *summary = NULL; | ||||||
|  | 	struct ast_str *description = NULL; | ||||||
|  | 	struct ast_str *organizer = NULL; | ||||||
|  | 	struct ast_str *location = NULL; | ||||||
|  | 	struct ast_str *start = NULL; | ||||||
|  | 	struct ast_str *end = NULL; | ||||||
|  | 	struct ast_str *busystate = NULL; | ||||||
| 	int ret = -1; | 	int ret = -1; | ||||||
|  |  | ||||||
| 	if (!event) { | 	if (!event) { | ||||||
| @@ -434,7 +434,7 @@ static int exchangecal_write_event(struct ast_calendar_event *event) | |||||||
| 		goto write_cleanup; | 		goto write_cleanup; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!(uid = ast_str_create(32)) || | 	if (!(uid = ast_str_create(AST_UUID_STR_LEN)) || | ||||||
| 		!(summary = ast_str_create(32)) || | 		!(summary = ast_str_create(32)) || | ||||||
| 		!(description = ast_str_create(32)) || | 		!(description = ast_str_create(32)) || | ||||||
| 		!(organizer = ast_str_create(32)) || | 		!(organizer = ast_str_create(32)) || | ||||||
| @@ -449,7 +449,7 @@ static int exchangecal_write_event(struct ast_calendar_event *event) | |||||||
| 	if (ast_strlen_zero(event->uid)) { | 	if (ast_strlen_zero(event->uid)) { | ||||||
| 		uid = generate_exchange_uuid(uid); | 		uid = generate_exchange_uuid(uid); | ||||||
| 	} else { | 	} else { | ||||||
| 		ast_str_set(&uid, 36, "%s", event->uid); | 		ast_str_set(&uid, AST_UUID_STR_LEN, "%s", event->uid); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!is_valid_uuid(uid)) { | 	if (!is_valid_uuid(uid)) { | ||||||
| @@ -496,7 +496,14 @@ static int exchangecal_write_event(struct ast_calendar_event *event) | |||||||
| 		"      </a:prop>\n" | 		"      </a:prop>\n" | ||||||
| 		"    </a:set>\n" | 		"    </a:set>\n" | ||||||
| 		"</a:propertyupdate>\n", | 		"</a:propertyupdate>\n", | ||||||
| 		ast_str_buffer(uid), ast_str_buffer(summary), ast_str_buffer(description), ast_str_buffer(organizer), ast_str_buffer(location), ast_str_buffer(start), ast_str_buffer(end), ast_str_buffer(busystate)); | 		ast_str_buffer(uid), | ||||||
|  | 		ast_str_buffer(summary), | ||||||
|  | 		ast_str_buffer(description), | ||||||
|  | 		ast_str_buffer(organizer), | ||||||
|  | 		ast_str_buffer(location), | ||||||
|  | 		ast_str_buffer(start), | ||||||
|  | 		ast_str_buffer(end), | ||||||
|  | 		ast_str_buffer(busystate)); | ||||||
| 	ast_verb(0, "\n\n%s\n\n", ast_str_buffer(body)); | 	ast_verb(0, "\n\n%s\n\n", ast_str_buffer(body)); | ||||||
| 	ast_str_set(&subdir, 0, "/Calendar/%s.eml", ast_str_buffer(uid)); | 	ast_str_set(&subdir, 0, "/Calendar/%s.eml", ast_str_buffer(uid)); | ||||||
|  |  | ||||||
| @@ -505,39 +512,17 @@ static int exchangecal_write_event(struct ast_calendar_event *event) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| write_cleanup: | write_cleanup: | ||||||
| 	if (uid) { | 	ast_free(uid); | ||||||
| 		ast_free(uid); | 	ast_free(summary); | ||||||
| 	} | 	ast_free(description); | ||||||
| 	if (summary) { | 	ast_free(organizer); | ||||||
| 		ast_free(summary); | 	ast_free(location); | ||||||
| 	} | 	ast_free(start); | ||||||
| 	if (description) { | 	ast_free(end); | ||||||
| 		ast_free(description); | 	ast_free(busystate); | ||||||
| 	} | 	ast_free(body); | ||||||
| 	if (organizer) { | 	ast_free(response); | ||||||
| 		ast_free(organizer); | 	ast_free(subdir); | ||||||
| 	} |  | ||||||
| 	if (location) { |  | ||||||
| 		ast_free(location); |  | ||||||
| 	} |  | ||||||
| 	if (start) { |  | ||||||
| 		ast_free(start); |  | ||||||
| 	} |  | ||||||
| 	if (end) { |  | ||||||
| 		ast_free(end); |  | ||||||
| 	} |  | ||||||
| 	if (busystate) { |  | ||||||
| 		ast_free(busystate); |  | ||||||
| 	} |  | ||||||
| 	if (body) { |  | ||||||
| 		ast_free(body); |  | ||||||
| 	} |  | ||||||
| 	if (response) { |  | ||||||
| 		ast_free(response); |  | ||||||
| 	} |  | ||||||
| 	if (subdir) { |  | ||||||
| 		ast_free(subdir); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -305,19 +305,12 @@ static void *sorcery_config_open(const char *data) | |||||||
| { | { | ||||||
| 	char *tmp = ast_strdupa(data), *filename = strsep(&tmp, ","), *option; | 	char *tmp = ast_strdupa(data), *filename = strsep(&tmp, ","), *option; | ||||||
| 	struct sorcery_config *config; | 	struct sorcery_config *config; | ||||||
| 	struct ast_uuid *uuid; |  | ||||||
|  |  | ||||||
| 	if (ast_strlen_zero(filename) || !(config = ao2_alloc_options(sizeof(*config) + strlen(filename) + 1, sorcery_config_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK))) { | 	if (ast_strlen_zero(filename) || !(config = ao2_alloc_options(sizeof(*config) + strlen(filename) + 1, sorcery_config_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK))) { | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!(uuid = ast_uuid_generate())) { | 	ast_uuid_generate_str(config->uuid, sizeof(config->uuid)); | ||||||
| 		ao2_ref(config, -1); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ast_uuid_to_str(uuid, config->uuid, AST_UUID_STR_LEN); |  | ||||||
| 	ast_free(uuid); |  | ||||||
|  |  | ||||||
| 	ast_rwlock_init(&config->objects.lock); | 	ast_rwlock_init(&config->objects.lock); | ||||||
| 	config->buckets = DEFAULT_OBJECT_BUCKETS; | 	config->buckets = DEFAULT_OBJECT_BUCKETS; | ||||||
|   | |||||||
| @@ -50,7 +50,23 @@ AST_TEST_DEFINE(uuid) | |||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* First, make sure that we can generate a UUID */ | 	/* Use method of generating UUID directly as a string. */ | ||||||
|  | 	ast_uuid_generate_str(uuid_str, sizeof(uuid_str)); | ||||||
|  | 	if (strlen(uuid_str) != (AST_UUID_STR_LEN - 1)) { | ||||||
|  | 		ast_test_status_update(test, "Failed to directly generate UUID string\n"); | ||||||
|  | 		goto end; | ||||||
|  | 	} | ||||||
|  | 	ast_test_status_update(test, "Generate UUID direct to string, got %s\n", uuid_str); | ||||||
|  |  | ||||||
|  | 	/* Now convert the direct UUID string to a UUID */ | ||||||
|  | 	uuid1 = ast_str_to_uuid(uuid_str); | ||||||
|  | 	if (!uuid1) { | ||||||
|  | 		ast_test_status_update(test, "Unable to convert direct UUID string %s to UUID\n", uuid_str); | ||||||
|  | 		goto end; | ||||||
|  | 	} | ||||||
|  | 	ast_free(uuid1); | ||||||
|  |  | ||||||
|  | 	/* Make sure that we can generate a UUID */ | ||||||
| 	uuid1 = ast_uuid_generate(); | 	uuid1 = ast_uuid_generate(); | ||||||
| 	if (!uuid1) { | 	if (!uuid1) { | ||||||
| 		ast_test_status_update(test, "Unable to generate a UUID\n"); | 		ast_test_status_update(test, "Unable to generate a UUID\n"); | ||||||
| @@ -71,7 +87,7 @@ AST_TEST_DEFINE(uuid) | |||||||
| 		goto end; | 		goto end; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ast_test_status_update(test, "Converted uuid to string, got %s\n", uuid_str); | 	ast_test_status_update(test, "Second generated UUID converted to string, got %s\n", uuid_str); | ||||||
|  |  | ||||||
| 	/* Now convert the string back to a UUID */ | 	/* Now convert the string back to a UUID */ | ||||||
| 	uuid2 = ast_str_to_uuid(uuid_str); | 	uuid2 = ast_str_to_uuid(uuid_str); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user