示例#1
0
文件: proto-irc.c 项目: arinity/gchat
static void
process_named_msg (session * sess, char *type, char *word[], char *word_eol[])
{
    server *serv = sess->server;
    char ip[128], nick[NICKLEN];
    char *text, *ex;
    int len = strlen (type);

    /* fill in the "ip" and "nick" buffers */
    ex = strchr (word[1], '!');
    if (!ex)                    /* no '!', must be a server message */
    {
        safe_strcpy (ip, word[1], sizeof (ip));
        safe_strcpy (nick, word[1], sizeof (nick));
    }
    else
    {
        safe_strcpy (ip, ex + 1, sizeof (ip));
        ex[0] = 0;
        safe_strcpy (nick, word[1], sizeof (nick));
        ex[0] = '!';
    }

    if (len == 4)
    {
        guint32 t;

        t = WORDL ((guint8) type[0], (guint8) type[1], (guint8) type[2],
                   (guint8) type[3]);
        /* this should compile to a bunch of: CMP.L, JE ... nice & fast */
        switch (t)
        {
        case WORDL ('J', 'O', 'I', 'N'):
        {
            char *chan = word[3];

            if (*chan == ':')
                chan++;
            if (!serv->p_cmp (nick, serv->nick))
                inbound_ujoin (serv, chan, nick, ip);
            else
                inbound_join (serv, chan, nick, ip);
        }
        return;

        case WORDL ('K', 'I', 'C', 'K'):
        {
            char *kicked = word[4];
            char *reason = word_eol[5];
            if (*kicked)
            {
                if (*reason == ':')
                    reason++;
                if (!strcmp (kicked, serv->nick))
                    inbound_ukick (serv, word[3], nick, reason);
                else
                    inbound_kick (serv, word[3], kicked, nick,
                                  reason);
            }
        }
        return;

        case WORDL ('K', 'I', 'L', 'L'):
            EMIT_SIGNAL (XP_TE_KILL, sess, nick, word_eol[5], NULL, NULL,
                         0);
            return;

        case WORDL ('M', 'O', 'D', 'E'):
            handle_mode (serv, word, word_eol, nick, FALSE);        /* modes.c */
            return;

        case WORDL ('N', 'I', 'C', 'K'):
            inbound_newnick (serv, nick, (word_eol[3][0] == ':')
                             ? word_eol[3] + 1 : word_eol[3], FALSE);
            return;

        case WORDL ('P', 'A', 'R', 'T'):
        {
            char *chan = word[3];
            char *reason = word_eol[4];

            if (*chan == ':')
                chan++;
            if (*reason == ':')
                reason++;
            if (!strcmp (nick, serv->nick))
                inbound_upart (serv, chan, ip, reason);
            else
                inbound_part (serv, chan, nick, ip, reason);
        }
        return;

        case WORDL ('P', 'O', 'N', 'G'):
            inbound_ping_reply (serv->server_session,
                                (word[4][0] ==
                                 ':') ? word[4] + 1 : word[4], word[3]);
            return;

        case WORDL ('Q', 'U', 'I', 'T'):
            inbound_quit (serv, nick, ip,
                          (word_eol[3][0] ==
                           ':') ? word_eol[3] + 1 : word_eol[3]);
            return;
        }

        goto garbage;
    }

    else if (len >= 5)
    {
        guint32 t;

        t = WORDL ((guint8) type[0], (guint8) type[1], (guint8) type[2],
                   (guint8) type[3]);
        /* this should compile to a bunch of: CMP.L, JE ... nice & fast */
        switch (t)
        {
        case WORDL ('I', 'N', 'V', 'I'):
            if (ignore_check (word[1], IG_INVI))
                return;

            if (word[4][0] == ':')
                EMIT_SIGNAL (XP_TE_INVITED, sess, word[4] + 1, nick,
                             serv->servername, NULL, 0);
            else
                EMIT_SIGNAL (XP_TE_INVITED, sess, word[4], nick,
                             serv->servername, NULL, 0);

            return;

        case WORDL ('N', 'O', 'T', 'I'):
        {
            int id = FALSE;     /* identified */

            text = word_eol[4];
            if (*text == ':')
                text++;

            if (serv->have_idmsg)
            {
                if (*text == '+')
                {
                    id = TRUE;
                    text++;
                }
                else if (*text == '-')
                    text++;
            }

            if (!ignore_check (word[1], IG_NOTI))
                inbound_notice (serv, word[3], nick, text, ip, id);
        }
        return;

        case WORDL ('P', 'R', 'I', 'V'):
        {
            char *to = word[3];
            int len;
            int id = FALSE;     /* identified */
            if (*to)
            {
                text = word_eol[4];
                if (*text == ':')
                    text++;
                if (serv->have_idmsg)
                {
                    if (*text == '+')
                    {
                        id = TRUE;
                        text++;
                    }
                    else if (*text == '-')
                        text++;
                }
                len = strlen (text);
                if (text[0] == 1 && text[len - 1] == 1)       /* ctcp */
                {
                    text[len - 1] = 0;
                    text++;
                    if (strncasecmp (text, "ACTION", 6) != 0)
                        flood_check (nick, ip, serv, sess, 0);
                    if (strncasecmp (text, "DCC ", 4) == 0)
                        /* redo this with handle_quotes TRUE */
                        process_data_init (word[1], word_eol[1],
                                           word, word_eol, TRUE,
                                           FALSE);
                    ctcp_handle (sess, to, nick, ip, text, word,
                                 word_eol, id);
                }
                else
                {
                    if (is_channel (serv, to))
                    {
                        if (ignore_check (word[1], IG_CHAN))
                            return;
                        inbound_chanmsg (serv, NULL, to, nick,
                                         text, FALSE, id);
                    }
                    else
                    {
                        if (ignore_check (word[1], IG_PRIV))
                            return;
                        inbound_privmsg (serv, nick, ip, text,
                                         id);
                    }
                }
            }
        }
        return;

        case WORDL ('T', 'O', 'P', 'I'):
            inbound_topicnew (serv, nick, word[3],
                              (word_eol[4][0] ==
                               ':') ? word_eol[4] + 1 : word_eol[4]);
            return;

        case WORDL ('W', 'A', 'L', 'L'):
            text = word_eol[3];
            if (*text == ':')
                text++;
            EMIT_SIGNAL (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0);
            return;
        }
    }

garbage:
    /* unknown message */
    PrintTextf (sess, "GARBAGE: %s\n", word_eol[1]);
}
示例#2
0
static void
process_named_msg (session *sess, char *type, char *word[], char *word_eol[])
{
    server *serv = sess->server;
    char ip[128], nick[NICKLEN];
    char *text, *ex;
    int len = strlen (type);

    /* fill in the "ip" and "nick" buffers */
    ex = strchr (word[1], '!');
    if (!ex)							  /* no '!', must be a server message */
    {
        safe_strcpy (ip, word[1], sizeof (ip));
        safe_strcpy (nick, word[1], sizeof (nick));
    } else
    {
        safe_strcpy (ip, ex + 1, sizeof (ip));
        ex[0] = 0;
        safe_strcpy (nick, word[1], sizeof (nick));
        ex[0] = '!';
    }

    if (len == 4)
    {
        guint32 t;

        t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]);
        /* this should compile to a bunch of: CMP.L, JE ... nice & fast */
        switch (t)
        {
        case WORDL('J','O','I','N'):
        {
            char *chan = word[3];

            if (*chan == ':')
                chan++;
            if (!serv->p_cmp (nick, serv->nick))
                inbound_ujoin (serv, chan, nick, ip);
            else
                inbound_join (serv, chan, nick, ip);
        }
        return;

        case WORDL('K','I','C','K'):
        {
            char *kicked = word[4];
            char *reason = word_eol[5];
            if (*kicked)
            {
                if (*reason == ':')
                    reason++;
                if (!strcmp (kicked, serv->nick))
                    inbound_ukick (serv, word[3], nick, reason);
                else
                    inbound_kick (serv, word[3], kicked, nick, reason);
            }
        }
        return;

        case WORDL('K','I','L','L'):
            EMIT_SIGNAL (XP_TE_KILL, sess, nick, word_eol[5], NULL, NULL, 0);
            return;

        case WORDL('M','O','D','E'):
            handle_mode (serv, word, word_eol, nick, FALSE);	/* modes.c */
            return;

        case WORDL('N','I','C','K'):
            inbound_newnick (serv, nick, (word_eol[3][0] == ':')
                             ? word_eol[3] + 1 : word_eol[3], FALSE);
            return;

        case WORDL('P','A','R','T'):
        {
            char *chan = word[3];
            char *reason = word_eol[4];

            if (*chan == ':')
                chan++;
            if (*reason == ':')
                reason++;
            if (!strcmp (nick, serv->nick))
                inbound_upart (serv, chan, ip, reason);
            else
                inbound_part (serv, chan, nick, ip, reason);
        }
        return;

        case WORDL('P','O','N','G'):
            inbound_ping_reply (serv->server_session,
                                (word[4][0] == ':') ? word[4] + 1 : word[4], word[3]);
            return;

        case WORDL('Q','U','I','T'):
            inbound_quit (serv, nick, ip,
                          (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3]);
            return;
        }

        goto garbage;
    }

    else if (len >= 5)
    {
        guint32 t;

        t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]);
        /* this should compile to a bunch of: CMP.L, JE ... nice & fast */
        switch (t)
        {
        case WORDL('I','N','V','I'):
            if (ignore_check (word[1], IG_INVI))
                return;

            if (word[4][0] == ':')
                EMIT_SIGNAL (XP_TE_INVITED, sess, word[4] + 1, nick,
                             serv->servername, NULL, 0);
            else
                EMIT_SIGNAL (XP_TE_INVITED, sess, word[4], nick,
                             serv->servername, NULL, 0);

            return;

        case WORDL('N','O','T','I'):
        {
            int id = FALSE;	/* identified */

            text = word_eol[4];
            if (*text == ':')
                text++;

            if (serv->have_idmsg)
            {
                if (*text == '+')
                {
                    id = TRUE;
                    text++;
                } else if (*text == '-')
                    text++;
            }

            if (!ignore_check (word[1], IG_NOTI))
                inbound_notice (serv, word[3], nick, text, ip, id);
        }
        return;

        case WORDL('P','R','I','V'):
        {
            char *to = word[3];
            int len;
            int id = FALSE;	/* identified */
            if (*to)
            {
                text = word_eol[4];
                if (*text == ':')
                    text++;
                if (serv->have_idmsg)
                {
                    if (*text == '+')
                    {
                        id = TRUE;
                        text++;
                    } else if (*text == '-')
                        text++;
                }
                len = strlen (text);
                if (text[0] == 1 && text[len - 1] == 1)	/* ctcp */
                {
                    text[len - 1] = 0;
                    text++;
                    if (g_ascii_strncasecmp (text, "ACTION", 6) != 0)
                        flood_check (nick, ip, serv, sess, 0);
                    if (g_ascii_strncasecmp (text, "DCC ", 4) == 0)
                        /* redo this with handle_quotes TRUE */
                        process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE);
                    ctcp_handle (sess, to, nick, ip, text, word, word_eol, id);
                } else
                {
                    if (is_channel (serv, to))
                    {
                        if (ignore_check (word[1], IG_CHAN))
                            return;
                        inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id);
                    } else
                    {
                        if (ignore_check (word[1], IG_PRIV))
                            return;
                        inbound_privmsg (serv, nick, ip, text, id);
                    }
                }
            }
        }
        return;

        case WORDL('T','O','P','I'):
            inbound_topicnew (serv, nick, word[3],
                              (word_eol[4][0] == ':') ? word_eol[4] + 1 : word_eol[4]);
            return;

        case WORDL('W','A','L','L'):
            text = word_eol[3];
            if (*text == ':')
                text++;
            EMIT_SIGNAL (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0);
            return;
        }
    }

    else if (len == 3)
    {
        guint32 t;
        guint32 want_cap;		/* format the CAP REQ string based on previous capabilities being requested or not */
        guint32 want_sasl;		/* CAP END shouldn't be sent when SASL is requested, it needs further responses */
        char *pass;				/* buffer for SASL password */
        char buffer[256];		/* buffer for requesting capabilities and emitting the signal */

        t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]);
        switch (t)
        {
        case WORDL('C','A','P','\0'):
            if (strncasecmp (word[4], "ACK", 3) == 0)
            {
                EMIT_SIGNAL (XP_TE_CAPACK, sess->server->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0);

                if (strstr (word_eol[5], "identify-msg") != 0)
                {
                    serv->have_idmsg = TRUE;
                }

                if (strstr (word_eol[5], "multi-prefix") != 0)
                {
                    serv->have_namesx = TRUE;
                }

                if (strstr (word_eol[5], "sasl") != 0)
                {
                    serv->have_sasl = TRUE;
                    EMIT_SIGNAL (XP_TE_SASLAUTH, serv->server_session, sess->server->sasluser, NULL, NULL, NULL, 0);
                    tcp_send_len (serv, "AUTHENTICATE PLAIN\r\n", 20);

                    pass = encode_sasl_pass (sess->server->sasluser, sess->server->saslpassword);
                    tcp_sendf (sess->server, "AUTHENTICATE %s\r\n", pass);
                    free (pass);
                }
            }
            else if (strncasecmp (word[4], "LS", 2) == 0)
            {
                EMIT_SIGNAL (XP_TE_CAPLIST, serv->server_session, word[1], word[5][0]==':' ? ++word_eol[5] : word_eol[5], NULL, NULL, 0);
                want_cap = 0;
                want_sasl = 0;

                if (strstr (word_eol[5], "identify-msg") != 0)
                {
                    strcpy (buffer, "CAP REQ :identify-msg");
                    want_cap = 1;
                }
                if (strstr (word_eol[5], "multi-prefix") != 0)
                {
                    want_cap ? strcat (buffer, " multi-prefix") : strcpy (buffer, "CAP REQ :multi-prefix");
                    want_cap = 1;
                }
                /* if the SASL password is set, request SASL auth */
                if (strstr (word_eol[5], "sasl") != 0 && strlen (sess->server->saslpassword) != 0)
                {
                    want_cap ? strcat (buffer, " sasl") : strcpy (buffer, "CAP REQ :sasl");
                    want_sasl = 1;
                }

                if (want_cap)
                {
                    /* buffer + 9 = emit buffer without "CAP REQ :" */
                    EMIT_SIGNAL (XP_TE_CAPREQ, sess->server->server_session, buffer + 9, NULL, NULL, NULL, 0);
                    tcp_sendf (serv, "%s\r\n", buffer);
                }
                if (!want_sasl)
                {
                    /* if we use SASL, CAP END is dealt via raw numerics */
                    tcp_send_len (serv, "CAP END\r\n", 9);
                }
            }
            else if (strncasecmp (word[4], "NAK", 3) == 0)
            {
                tcp_send_len (serv, "CAP END\r\n", 9);
            }

            return;
        }
    }

garbage:
    /* unknown message */
    PrintTextf (sess, "GARBAGE: %s\n", word_eol[1]);
}