Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • irc_send.c

    r2d93f113 rc54bb11  
    172172        irc_t *irc = ic->irc;
    173173
    174         irc_write(irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name);
     174        if (irc->caps & CAP_EXTENDED_JOIN) {
     175                irc_write(irc, ":%s!%s@%s JOIN %s * :%s", iu->nick, iu->user, iu->host, ic->name, iu->fullname);
     176        } else {
     177                irc_write(irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name);
     178        }
    175179
    176180        if (iu == irc->user) {
     
    198202}
    199203
     204#define IRC_NAMES_LEN 385
     205
    200206void irc_send_names(irc_channel_t *ic)
    201207{
    202208        GSList *l;
    203         char namelist[385] = "";
     209        GString *namelist = g_string_sized_new(IRC_NAMES_LEN);
     210        gboolean uhnames = (ic->irc->caps & CAP_USERHOST_IN_NAMES);
    204211
    205212        /* RFCs say there is no error reply allowed on NAMES, so when the
     
    208215                irc_channel_user_t *icu = l->data;
    209216                irc_user_t *iu = icu->iu;
    210 
    211                 if (strlen(namelist) + strlen(iu->nick) > sizeof(namelist) - 4) {
    212                         irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist);
    213                         *namelist = 0;
    214                 }
    215 
    216                 if (icu->flags & IRC_CHANNEL_USER_OP) {
    217                         strcat(namelist, "@");
    218                 } else if (icu->flags & IRC_CHANNEL_USER_HALFOP) {
    219                         strcat(namelist, "%");
    220                 } else if (icu->flags & IRC_CHANNEL_USER_VOICE) {
    221                         strcat(namelist, "+");
    222                 }
    223 
    224                 strcat(namelist, iu->nick);
    225                 strcat(namelist, " ");
    226         }
    227 
    228         if (*namelist) {
    229                 irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist);
     217                size_t extra_len = strlen(iu->nick);
     218                char prefix;
     219
     220                if (uhnames) {
     221                        extra_len += strlen(iu->user) + strlen(iu->host) + 2;
     222                }
     223
     224                if (namelist->len + extra_len > IRC_NAMES_LEN - 4) {
     225                        irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist->str);
     226                        g_string_truncate(namelist, 0);
     227                }
     228
     229                if ((prefix = irc_channel_user_get_prefix(icu))) {
     230                        g_string_append_c(namelist, prefix);
     231                }
     232
     233                if (uhnames) {
     234                        g_string_append_printf(namelist, "%s!%s@%s ", iu->nick, iu->user, iu->host);
     235                } else {
     236                        g_string_append(namelist, iu->nick);
     237                        g_string_append_c(namelist, ' ');
     238                }
     239        }
     240
     241        if (namelist->len) {
     242                irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist->str);
    230243        }
    231244
    232245        irc_send_num(ic->irc, 366, "%s :End of /NAMES list", ic->name);
     246
     247        g_string_free(namelist, TRUE);
    233248}
    234249
     
    249264}
    250265
     266/* msg1 and msg2 are output parameters. If msg2 is non-null, msg1 is guaranteed to be non-null too.
     267   The idea is to defer the formatting of "$msg1 ($msg2)" to later calls to avoid a g_strdup_printf() here. */
     268static void get_status_message(bee_user_t *bu, char **msg1, char **msg2)
     269{
     270        *msg1 = NULL;
     271        *msg2 = NULL;
     272
     273        if (!(bu->flags & BEE_USER_ONLINE)) {
     274                *msg1 = "User is offline";
     275
     276        } else if ((bu->status && *bu->status) ||
     277                   (bu->status_msg && *bu->status_msg)) {
     278
     279                if (bu->status && bu->status_msg) {
     280                        *msg1 = bu->status;
     281                        *msg2 = bu->status_msg;
     282                } else {
     283                        *msg1 = bu->status ? : bu->status_msg;
     284                }
     285        }
     286
     287        if (*msg1 && !**msg1) {
     288                *msg1 = (bu->flags & BEE_USER_AWAY) ? "Away" : NULL;
     289        }
     290}
     291
    251292void irc_send_whois(irc_user_t *iu)
    252293{
     
    258299        if (iu->bu) {
    259300                bee_user_t *bu = iu->bu;
     301                char *msg1, *msg2;
     302                int num;
    260303
    261304                irc_send_num(irc, 312, "%s %s.%s :%s network", iu->nick, bu->ic->acc->user,
     
    263306                             bu->ic->acc->prpl->name);
    264307
    265                 if ((bu->status && *bu->status) ||
    266                     (bu->status_msg && *bu->status_msg)) {
    267                         int num = bu->flags & BEE_USER_AWAY ? 301 : 320;
    268 
    269                         if (bu->status && bu->status_msg) {
    270                                 irc_send_num(irc, num, "%s :%s (%s)", iu->nick, bu->status, bu->status_msg);
    271                         } else {
    272                                 irc_send_num(irc, num, "%s :%s", iu->nick, bu->status ? : bu->status_msg);
    273                         }
    274                 } else if (!(bu->flags & BEE_USER_ONLINE)) {
    275                         irc_send_num(irc, 301, "%s :%s", iu->nick, "User is offline");
     308                num = (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) ? 301 : 320;
     309
     310                get_status_message(bu, &msg1, &msg2);
     311
     312                if (msg1 && msg2) {
     313                        irc_send_num(irc, num, "%s :%s (%s)", iu->nick, msg1, msg2);
     314                } else if (msg1) {
     315                        irc_send_num(irc, num, "%s :%s", iu->nick, msg1);
    276316                }
    277317
     
    294334
    295335        while (l) {
    296                 irc_user_t *iu = l->data;
     336                irc_user_t *iu;
     337
     338                /* Null terminated string with three chars, respectively:
     339                 * { <H|G>, <@|%|+|\0>, \0 } */
     340                char status_prefix[3] = {0};
     341
    297342                if (is_channel) {
    298                         iu = ((irc_channel_user_t *) iu)->iu;
    299                 }
    300                 /* TODO(wilmer): Restore away/channel information here */
    301                 irc_send_num(irc, 352, "%s %s %s %s %s %c :0 %s",
     343                        irc_channel_user_t *icu = l->data;
     344                        status_prefix[1] = irc_channel_user_get_prefix(icu);
     345                        iu = icu->iu;
     346                } else {
     347                        iu = l->data;
     348                }
     349
     350                /* rfc1459 doesn't mention this: G means gone, H means here */
     351                status_prefix[0] = iu->flags & IRC_USER_AWAY ? 'G' : 'H';
     352
     353                irc_send_num(irc, 352, "%s %s %s %s %s %s :0 %s",
    302354                             is_channel ? channel : "*", iu->user, iu->host, irc->root->host,
    303                              iu->nick, iu->flags & IRC_USER_AWAY ? 'G' : 'H',
    304                              iu->fullname);
     355                             iu->nick, status_prefix, iu->fullname);
    305356                l = l->next;
    306357        }
     
    428479                  iu->nick, iu->user, iu->host, irc->user->nick, ic->name);
    429480}
     481
     482void irc_send_cap(irc_t *irc, char *subcommand, char *body)
     483{
     484        char *nick = irc->user->nick ? : "*";
     485
     486        irc_write(irc, ":%s CAP %s %s :%s", irc->root->host, nick, subcommand, body);
     487}
     488
     489void irc_send_away_notify(irc_user_t *iu)
     490{
     491        bee_user_t *bu = iu->bu;
     492
     493        if (!bu) {
     494                return;
     495        }
     496
     497        if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) {
     498                char *msg1, *msg2;
     499
     500                get_status_message(bu, &msg1, &msg2);
     501
     502                if (msg2) {
     503                        irc_write(iu->irc, ":%s!%s@%s AWAY :%s (%s)", iu->nick, iu->user, iu->host, msg1, msg2);
     504                } else {
     505                        irc_write(iu->irc, ":%s!%s@%s AWAY :%s", iu->nick, iu->user, iu->host, msg1);
     506                }
     507        } else {
     508                irc_write(iu->irc, ":%s!%s@%s AWAY", iu->nick, iu->user, iu->host);
     509        }
     510}
     511
Note: See TracChangeset for help on using the changeset viewer.