degesch: rework registration
Also fixed the annoying reconnect bug.
This commit is contained in:
parent
ebf9403872
commit
30191c76c8
110
degesch.c
110
degesch.c
@ -3057,8 +3057,11 @@ on_irc_disconnected (struct server *s)
|
||||
while ((channel = str_map_iter_next (&iter)))
|
||||
irc_left_channel (channel);
|
||||
|
||||
user_unref (s->irc_user);
|
||||
s->irc_user = NULL;
|
||||
if (s->irc_user)
|
||||
{
|
||||
user_unref (s->irc_user);
|
||||
s->irc_user = NULL;
|
||||
}
|
||||
|
||||
free (s->irc_user_mode);
|
||||
s->irc_user_mode = NULL;
|
||||
@ -3251,14 +3254,6 @@ irc_register (struct server *s)
|
||||
irc_send (s, "NICK %s", nickname);
|
||||
// IRC servers may ignore the last argument if it's empty
|
||||
irc_send (s, "USER %s 8 * :%s", username, *realname ? realname : " ");
|
||||
|
||||
// XXX: maybe we should wait for the first message from the server
|
||||
// FIXME: the user may exist already after we've reconnected. Either
|
||||
// make sure that there's no reference of this nick upon disconnection,
|
||||
// or search in "irc_users" first... or something.
|
||||
s->irc_user = irc_make_user (s, xstrdup (nickname));
|
||||
s->irc_user_mode = xstrdup ("");
|
||||
s->irc_user_host = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3507,6 +3502,8 @@ make_prompt (struct app_context *ctx, struct str *output)
|
||||
str_append_c (output, ' ');
|
||||
if (!irc_is_connected (s))
|
||||
str_append (output, "(disconnected)");
|
||||
else if (s->state != IRC_REGISTERED)
|
||||
str_append (output, "(unregistered)");
|
||||
else
|
||||
{
|
||||
str_append (output, s->irc_user->nickname);
|
||||
@ -3561,6 +3558,11 @@ irc_find_userhost (const char *prefix)
|
||||
static bool
|
||||
irc_is_this_us (struct server *s, const char *prefix)
|
||||
{
|
||||
// This shouldn't be called before successfully registering.
|
||||
// Better safe than sorry, though.
|
||||
if (!s->irc_user)
|
||||
return false;
|
||||
|
||||
char *nick = irc_cut_nickname (prefix);
|
||||
bool result = !irc_strcmp (nick, s->irc_user->nickname);
|
||||
free (nick);
|
||||
@ -3610,6 +3612,10 @@ irc_get_buffer_for_message (struct server *s,
|
||||
static bool
|
||||
irc_is_highlight (struct server *s, const char *message)
|
||||
{
|
||||
// This may be called by notices before even successfully registering
|
||||
if (!s->irc_user)
|
||||
return false;
|
||||
|
||||
// Well, this is rather crude but it should make most users happy.
|
||||
// Ideally we could do this at least in proper Unicode.
|
||||
char *copy = xstrdup (message);
|
||||
@ -4204,6 +4210,28 @@ irc_try_parse_welcome_for_userhost (struct server *s, const char *m)
|
||||
str_vector_free (&v);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_on_registered (struct server *s, const char *nickname)
|
||||
{
|
||||
s->irc_user = irc_get_or_make_user (s, nickname);
|
||||
s->irc_user_mode = xstrdup ("");
|
||||
s->irc_user_host = NULL;
|
||||
|
||||
s->state = IRC_REGISTERED;
|
||||
refresh_prompt (s->ctx);
|
||||
|
||||
// TODO: parse any response and store the result for us in app_context;
|
||||
// this enables proper message splitting on output;
|
||||
// we can also use WHOIS if it's not supported (optional by RFC 2812)
|
||||
irc_send (s, "USERHOST %s", s->irc_user->nickname);
|
||||
|
||||
const char *autojoin = get_config_string (s->ctx, "server.autojoin");
|
||||
if (autojoin)
|
||||
irc_send (s, "JOIN :%s", autojoin);
|
||||
|
||||
// TODO: rejoin all current channels (mark those we've left manually?)
|
||||
}
|
||||
|
||||
static void
|
||||
irc_process_numeric (struct server *s,
|
||||
const struct irc_message *msg, unsigned long numeric)
|
||||
@ -4211,6 +4239,8 @@ irc_process_numeric (struct server *s,
|
||||
// Numerics typically have human-readable information
|
||||
// TODO: try to output certain replies in more specific buffers
|
||||
|
||||
// TODO: fail the connection if there's no first parameter
|
||||
|
||||
// Get rid of the first parameter, if there's any at all,
|
||||
// as it contains our nickname and is of no practical use to the user
|
||||
struct str_vector copy;
|
||||
@ -4228,6 +4258,8 @@ irc_process_numeric (struct server *s,
|
||||
switch (numeric)
|
||||
{
|
||||
case IRC_RPL_WELCOME:
|
||||
irc_on_registered (s, msg->params.vector[0]);
|
||||
|
||||
// We still issue a USERHOST anyway as this is in general unreliable
|
||||
if (msg->params.len == 2)
|
||||
irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]);
|
||||
@ -4270,28 +4302,6 @@ irc_process_message (const struct irc_message *msg,
|
||||
input_show (&s->ctx->input);
|
||||
}
|
||||
|
||||
// XXX: or is the 001 numeric enough? For what?
|
||||
if (s->state == IRC_CONNECTED && (!strcasecmp (msg->command, "MODE")
|
||||
|| !strcasecmp (msg->command, "376") // RPL_ENDOFMOTD
|
||||
|| !strcasecmp (msg->command, "422"))) // ERR_NOMOTD
|
||||
{
|
||||
// XXX: should we really print this?
|
||||
buffer_send_status (s->ctx, s->buffer, "Successfully connected");
|
||||
s->state = IRC_REGISTERED;
|
||||
refresh_prompt (s->ctx);
|
||||
|
||||
// TODO: parse any response and store the result for us in app_context;
|
||||
// this enables proper message splitting on output;
|
||||
// we can also use WHOIS if it's not supported (optional by RFC 2812)
|
||||
irc_send (s, "USERHOST %s", s->irc_user->nickname);
|
||||
|
||||
const char *autojoin = get_config_string (s->ctx, "server.autojoin");
|
||||
if (autojoin)
|
||||
irc_send (s, "JOIN :%s", autojoin);
|
||||
|
||||
// TODO: rejoin all current channels (mark those we've left manually?)
|
||||
}
|
||||
|
||||
struct irc_handler key = { .name = msg->command };
|
||||
struct irc_handler *handler = bsearch (&key, g_irc_handlers,
|
||||
N_ELEMENTS (g_irc_handlers), sizeof key, irc_handler_cmp_by_name);
|
||||
@ -4402,7 +4412,7 @@ irc_autosplit_message (struct server *s, const char *message,
|
||||
{
|
||||
// :<nick>!<user>@<host> <fixed-part><message>
|
||||
int space_in_one_message = 0;
|
||||
if (s->irc_user_host)
|
||||
if (s->irc_user && s->irc_user_host)
|
||||
space_in_one_message = 510
|
||||
- 1 - (int) strlen (s->irc_user->nickname)
|
||||
- 1 - (int) strlen (s->irc_user_host)
|
||||
@ -4468,7 +4478,7 @@ log_outcoming_action (struct server *s,
|
||||
{
|
||||
(void) a;
|
||||
|
||||
if (buffer)
|
||||
if (buffer && soft_assert (s->irc_user))
|
||||
buffer_send (s->ctx, buffer, BUFFER_LINE_ACTION, 0,
|
||||
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
|
||||
.text = irc_to_utf8 (s->ctx, line));
|
||||
@ -4485,7 +4495,7 @@ static void
|
||||
log_outcoming_privmsg (struct server *s,
|
||||
struct send_autosplit_args *a, struct buffer *buffer, const char *line)
|
||||
{
|
||||
if (buffer)
|
||||
if (buffer && soft_assert (s->irc_user))
|
||||
buffer_send (s->ctx, buffer, BUFFER_LINE_PRIVMSG, 0,
|
||||
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
|
||||
.text = irc_to_utf8 (s->ctx, line));
|
||||
@ -4503,7 +4513,7 @@ static void
|
||||
log_outcoming_notice (struct server *s,
|
||||
struct send_autosplit_args *a, struct buffer *buffer, const char *line)
|
||||
{
|
||||
if (buffer)
|
||||
if (buffer && soft_assert (s->irc_user))
|
||||
buffer_send (s->ctx, buffer, BUFFER_LINE_NOTICE, 0,
|
||||
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
|
||||
.text = irc_to_utf8 (s->ctx, line));
|
||||
@ -4693,8 +4703,12 @@ try_decode_buffer (struct app_context *ctx, const char *word)
|
||||
}
|
||||
|
||||
static bool
|
||||
server_command_check (struct app_context *ctx, const char *action)
|
||||
server_command_check (struct app_context *ctx, const char *action,
|
||||
bool need_registration)
|
||||
{
|
||||
// "need_registration" is primarily for message sending commands,
|
||||
// as they may want to log buffer lines and use our current nickname
|
||||
|
||||
if (ctx->current_buffer->type == BUFFER_GLOBAL)
|
||||
buffer_send_error (ctx, ctx->current_buffer,
|
||||
"Can't do this from a global buffer (%s)", action);
|
||||
@ -4703,6 +4717,8 @@ server_command_check (struct app_context *ctx, const char *action)
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
if (!irc_is_connected (s))
|
||||
buffer_send_error (ctx, s->buffer, "Not connected");
|
||||
else if (s->state != IRC_REGISTERED && need_registration)
|
||||
buffer_send_error (ctx, s->buffer, "Not registered");
|
||||
else
|
||||
return true;
|
||||
}
|
||||
@ -4973,7 +4989,7 @@ handle_command_save (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_msg (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "send messages"))
|
||||
if (!server_command_check (ctx, "send messages", true))
|
||||
return true;
|
||||
if (!*arguments)
|
||||
return false;
|
||||
@ -4990,7 +5006,7 @@ handle_command_msg (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_query (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "send messages"))
|
||||
if (!server_command_check (ctx, "send messages", true))
|
||||
return true;
|
||||
if (!*arguments)
|
||||
return false;
|
||||
@ -5012,7 +5028,7 @@ handle_command_query (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_notice (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "send messages"))
|
||||
if (!server_command_check (ctx, "send messages", true))
|
||||
return true;
|
||||
if (!*arguments)
|
||||
return false;
|
||||
@ -5029,7 +5045,7 @@ handle_command_notice (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_ctcp (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "send messages"))
|
||||
if (!server_command_check (ctx, "send messages", true))
|
||||
return true;
|
||||
if (!*arguments)
|
||||
return false;
|
||||
@ -5056,7 +5072,7 @@ handle_command_ctcp (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_me (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "send messages"))
|
||||
if (!server_command_check (ctx, "send messages", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
@ -5087,7 +5103,7 @@ handle_command_quit (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_join (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "join"))
|
||||
if (!server_command_check (ctx, "join", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
@ -5116,7 +5132,7 @@ handle_command_join (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_part (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "part"))
|
||||
if (!server_command_check (ctx, "part", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
@ -5178,7 +5194,7 @@ handle_command_disconnect (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_list (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "list channels"))
|
||||
if (!server_command_check (ctx, "list channels", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
@ -5192,7 +5208,7 @@ handle_command_list (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_nick (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "change nickname"))
|
||||
if (!server_command_check (ctx, "change nickname", false))
|
||||
return true;
|
||||
if (!*arguments)
|
||||
return false;
|
||||
@ -5205,7 +5221,7 @@ handle_command_nick (struct app_context *ctx, char *arguments)
|
||||
static bool
|
||||
handle_command_quote (struct app_context *ctx, char *arguments)
|
||||
{
|
||||
if (!server_command_check (ctx, "quote"))
|
||||
if (!server_command_check (ctx, "quote", true))
|
||||
return true;
|
||||
|
||||
struct server *s = ctx->current_buffer->server;
|
||||
|
Loading…
Reference in New Issue
Block a user