예제 #1
0
파일: user.c 프로젝트: junaidk/uhub
void user_update_info(struct hub_user* u, struct adc_message* cmd)
{
	char prefix[2];
	char* argument;
	size_t n = 0;
	struct adc_message* cmd_new = adc_msg_copy(u->info);
	if (!cmd_new)
	{
		/* FIXME: OOM! */
		return;
	}

	/*
	 * FIXME: Optimization potential:
	 *
	 * remove parts of cmd that do not really change anything in cmd_new.
	 * this can save bandwidth if clients send multiple updates for information
	 * that does not really change anything.
	 */
	argument = adc_msg_get_argument(cmd, n++);
	while (argument)
	{
		if (strlen(argument) >= 2)
		{
			prefix[0] = argument[0];
			prefix[1] = argument[1];
			adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
		}
		
		hub_free(argument);
		argument = adc_msg_get_argument(cmd, n++);
	}
	user_set_info(u, cmd_new);
	adc_msg_free(cmd_new);
}
예제 #2
0
파일: hub.c 프로젝트: q3k/uhub
void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
	char* msg_esc   = adc_msg_get_argument(cmd, 0);
	char* message = adc_msg_unescape(msg_esc);
	char* log = hub_malloc(strlen(message) + strlen(user->id.nick) + 14);
	sprintf(log, "%s <%s> %s\n", get_timestamp(time(NULL)), user->id.nick, message);
	list_append(hub->chat_history, log);
	while (list_size(hub->chat_history) > (size_t) hub->config->max_chat_history)
	{
		char* msg = list_get_first(hub->chat_history);
		list_remove(hub->chat_history, msg);
		hub_free(msg);
	}
	hub_free(message);
	hub_free(msg_esc);
}
예제 #3
0
파일: hub.c 프로젝트: imobilis/uhub
int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
{
	char* password = adc_msg_get_argument(cmd, 0);
	int ret = 0;

	if (u->state == state_verify)
	{
		if (acl_password_verify(hub, u, password))
		{
			on_login_success(hub, u);
		}
		else
		{
			on_login_failure(hub, u, status_msg_auth_invalid_password);
			ret = -1;
		}
	}

	hub_free(password);
	return ret;
}
예제 #4
0
파일: hub.c 프로젝트: imobilis/uhub
int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
{
	char* message = adc_msg_get_argument(cmd, 0);
	char* message_decoded = NULL;
	int ret = 0;
	int relay = 1;
	int broadcast;
	int private_msg;
	int command;
	int offset;

	if (!message)
		return 0;

	message_decoded = adc_msg_unescape(message);
	if (!message_decoded)
	{
		hub_free(message);
		return 0;
	}

	if (!user_is_logged_in(u))
	{
		hub_free(message);
		return 0;
	}

	broadcast = (cmd->cache[0] == 'B');
	private_msg = (cmd->cache[0] == 'D' || cmd->cache[0] == 'E');
	command = (message[0] == '!' || message[0] == '+');

	if (broadcast && command)
	{
		/*
		 * A message such as "++message" is handled as "+message", by removing the first character.
		 * The first character is removed by memmoving the string one byte to the left.
		 */
		if (message[1] == message[0])
		{
			relay = 1;
			offset = adc_msg_get_arg_offset(cmd);
			memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
			cmd->length--;
		}
		else
		{
			relay = command_invoke(hub->commands, u, message_decoded);
		}
	}

	/* FIXME: Plugin should do this! */
	if (relay && (((hub->config->chat_is_privileged && !user_is_protected(u)) || (user_flag_get(u, flag_muted))) && broadcast))
	{
		relay = 0;
	}

	if (relay)
	{
		plugin_st status = st_default;
		if (broadcast)
		{
			status = plugin_handle_chat_message(hub, u, message_decoded, 0);
		}
		else if (private_msg)
		{
			struct hub_user* target = uman_get_user_by_sid(hub->users, cmd->target);
			if (target)
				status = plugin_handle_private_message(hub, u, target, message_decoded, 0);
			else
				relay = 0;
		}

		if (status == st_deny)
			relay = 0;
	}

	if (relay)
	{
		/* adc_msg_remove_named_argument(cmd, "PM"); */
		if (broadcast)
		{
			plugin_log_chat_message(hub, u, message_decoded, 0);
		}
		ret = route_message(hub, u, cmd);
	}
	hub_free(message);
	hub_free(message_decoded);
	return ret;
}
예제 #5
0
파일: hub.c 프로젝트: imobilis/uhub
int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
{
	int ret = 0;
	int index = 0;
	int ok = 1;
	char* arg = adc_msg_get_argument(cmd, index);

	if (hub->status == hub_status_disabled && u->state == state_protocol)
	{
		on_login_failure(hub, u, status_msg_hub_disabled);
		hub_free(arg);
		return -1;
	}

	while (arg)
	{
		if (strlen(arg) == 6)
		{
			fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
			if (strncmp(arg, ADC_SUP_FLAG_ADD, 2) == 0)
			{
				user_support_add(u, fourcc);
			}
			else if (strncmp(arg, ADC_SUP_FLAG_REMOVE, 2) == 0)
			{
				user_support_remove(u, fourcc);
			}
			else
			{
				ok = 0;
			}
		}
		else
		{
			ok = 0;
		}

		index++;
		hub_free(arg);
		arg = adc_msg_get_argument(cmd, index);
	}

	if (u->state == state_protocol)
	{
		if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
		if (!ok)
		{
			/* disconnect user. Do not send crap during initial handshake! */
			hub_disconnect_user(hub, u, quit_logon_error);
			return -1;
		}

		if (user_flag_get(u, feature_base))
		{
			/* User supports ADC/1.0 and a hash we know */
			if (user_flag_get(u, feature_tiger))
			{
				hub_send_handshake(hub, u);
				/* TODO: timeouts for mux users */
				if (u->connection)
					net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
			}
			else
			{
				// no common hash algorithm.
				hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
				hub_disconnect_user(hub, u, quit_protocol_error);
			}
		}
		else if (user_flag_get(u, feature_bas0))
		{
			if (hub->config->obsolete_clients)
			{
				hub_send_handshake(hub, u);
				/* TODO: timeouts for mux users */
				if (u->connection)
					net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
			}
			else
			{
				/* disconnect user for using an obsolete client. */
				char* tmp = adc_msg_escape(hub->config->msg_proto_obsolete_adc0);
				struct adc_message* message = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
				adc_msg_add_argument(message, tmp);
				hub_free(tmp);
				route_to_user(hub, u, message);
				adc_msg_free(message);
				hub_disconnect_user(hub, u, quit_protocol_error);
			}
		}
		else
		{
			/* Not speaking a compatible protocol - just disconnect. */
			hub_disconnect_user(hub, u, quit_logon_error);
		}
	}

	return ret;
}