Changes in / [69982f8:1522faf]


Ignore:
Files:
1 added
14 edited

Legend:

Unmodified
Added
Removed
  • irc.h

    r69982f8 r1522faf  
    147147        IRC_CHANNEL_TEMP = 2,   /* Erase the channel when the user leaves,
    148148                                   and don't save it. */
     149
     150        /* Show a placeholder of the channel in listings, but don't save it */
     151        IRC_CHANNEL_KEEP_PLACEHOLDER = 4,
    149152
    150153        /* Hack: Set this flag right before jumping into IM when we expect
     
    299302void irc_channel_name_strip(char *name);
    300303int irc_channel_name_cmp(const char *a_, const char *b_);
     304char *irc_channel_name_gen(bee_t *bee, const char *name);
     305gboolean irc_channel_name_hint(irc_channel_t *ic, const char *name);
    301306void irc_channel_update_ops(irc_channel_t *ic, char *value);
    302307char *set_eval_irc_channel_ops(struct set *set, char *value);
  • irc_channel.c

    r69982f8 r1522faf  
    276276                if (ic->irc->status & USTATUS_SHUTDOWN) {
    277277                        /* Don't do anything fancy when we're shutting down anyway. */
    278                 } else if (ic->flags & IRC_CHANNEL_TEMP) {
     278                } else if (ic->flags & IRC_CHANNEL_TEMP && !(ic->flags & IRC_CHANNEL_KEEP_PLACEHOLDER)) {
    279279                        irc_channel_free_soon(ic);
    280280                } else {
     
    556556}
    557557
     558gboolean irc_channel_is_unused(bee_t *bee, char *name)
     559{
     560        char *type, *chat_type;
     561        irc_channel_t *oic;
     562
     563        if (!irc_channel_name_ok(name)) {
     564                return FALSE;
     565        }
     566
     567        if (!(oic = irc_channel_by_name(bee->ui_data, name))) {
     568                return TRUE;
     569        }
     570
     571        type = set_getstr(&oic->set, "type");
     572        chat_type = set_getstr(&oic->set, "chat_type");
     573
     574        if (type && chat_type && oic->data == FALSE &&
     575            strcmp(type, "chat") == 0 &&
     576            strcmp(chat_type, "groupchat") == 0) {
     577                /* There's a channel with this name already, but it looks
     578                   like it's not in use yet. Most likely the IRC client
     579                   rejoined the channel after a reconnect. Remove it so
     580                   we can reuse its name. */
     581                irc_channel_free(oic);
     582                return TRUE;
     583        }
     584
     585        return FALSE;
     586}
     587
     588char *irc_channel_name_gen(bee_t *bee, const char *hint)
     589{
     590        char *name, *final_name;
     591        gsize bytes_written;
     592
     593        name = g_convert_with_fallback(hint, -1, "ASCII//TRANSLIT", "UTF-8", "", NULL, &bytes_written, NULL);
     594        if (bytes_written > MAX_NICK_LENGTH) {
     595                name[MAX_NICK_LENGTH] = '\0';
     596        }
     597
     598        irc_channel_name_strip(name);
     599
     600        if (set_getbool(&bee->set, "lcnicks")) {
     601                nick_lc(bee->ui_data, name);
     602        }
     603
     604        while (!irc_channel_is_unused(bee, name)) {
     605                underscore_dedupe(name);
     606        }
     607
     608        final_name = g_strconcat("#", name, NULL);
     609
     610        g_free(name);
     611
     612        return final_name;
     613}
     614
     615gboolean irc_channel_name_hint(irc_channel_t *ic, const char *name)
     616{
     617        irc_t *irc = ic->irc;
     618        char *full_name;
     619
     620        /* Don't rename a channel if the user's in it already. */
     621        if (ic->flags & IRC_CHANNEL_JOINED) {
     622                return FALSE;
     623        }
     624
     625        if (!(full_name = irc_channel_name_gen(irc->b, name))) {
     626                return FALSE;
     627        }
     628
     629        g_free(ic->name);
     630        ic->name = full_name;
     631
     632        return TRUE;
     633}
     634
    558635static gint irc_channel_user_cmp(gconstpointer a_, gconstpointer b_)
    559636{
  • irc_im.c

    r69982f8 r1522faf  
    576576        ic->data = c;
    577577
    578         topic = g_strdup_printf(
    579                 "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!",
    580                 c->title);
    581         irc_channel_set_topic(ic, topic, irc->root);
    582         g_free(topic);
     578        if (ic->topic == NULL) {
     579                /* New channel with no preset topic - make up a generic one */
     580                topic = g_strdup_printf(
     581                        "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!",
     582                        c->title);
     583                irc_channel_set_topic(ic, topic, irc->root);
     584        } else {
     585                /* Preset topic from the channel we picked */
     586                topic = g_strdup(ic->topic);
     587        }
     588
     589        g_free(c->topic);
     590        c->topic = topic;         /* Let groupchat borrow this pointer */
    583591
    584592        return TRUE;
     
    600608        c->ui_data = NULL;
    601609        irc_channel_del_user(ic, ic->irc->user, IRC_CDU_KICK, "Chatroom closed by server");
     610
     611        return TRUE;
     612}
     613
     614static gboolean bee_irc_chat_placeholder_new(bee_t *bee, struct im_connection *ic, const char *handle,
     615                                             const char *name, const char *topic)
     616{
     617        irc_t *irc = bee->ui_data;
     618        irc_channel_t *ircc;
     619        char *full_name = irc_channel_name_gen(bee, name);
     620
     621        ircc = irc_channel_new(irc, full_name);
     622
     623        set_setstr(&ircc->set, "type", "chat");
     624        set_setstr(&ircc->set, "chat_type", "placeholder");
     625        set_setstr(&ircc->set, "account", ic->acc->tag);
     626        set_setstr(&ircc->set, "room", (char *) handle);
     627
     628        irc_channel_set_topic(ircc, topic, NULL);
     629
     630        g_free(full_name);
    602631
    603632        return TRUE;
     
    696725static gboolean bee_irc_chat_name_hint(bee_t *bee, struct groupchat *c, const char *name)
    697726{
    698         irc_t *irc = bee->ui_data;
    699         irc_channel_t *ic = c->ui_data, *oic;
    700         char *stripped, *full_name;
    701         gsize bytes_written;
    702 
    703         if (ic == NULL) {
    704                 return FALSE;
    705         }
    706 
    707         /* Don't rename a channel if the user's in it already. */
    708         if (ic->flags & IRC_CHANNEL_JOINED) {
    709                 return FALSE;
    710         }
    711 
    712         stripped = g_convert_with_fallback(name, -1, "ASCII//TRANSLIT", "UTF-8", "", NULL, &bytes_written, NULL);
    713         if (bytes_written > MAX_NICK_LENGTH) {
    714                 stripped[MAX_NICK_LENGTH] = '\0';
    715         }
    716 
    717         irc_channel_name_strip(stripped);
    718         if (set_getbool(&bee->set, "lcnicks")) {
    719                 nick_lc(irc, stripped);
    720         }
    721 
    722         if (stripped[0] == '\0') {
    723                 g_free(stripped);
    724                 return FALSE;
    725         }
    726 
    727         full_name = g_strdup_printf("#%s", stripped);
    728         g_free(stripped);
    729         if ((oic = irc_channel_by_name(irc, full_name))) {
    730                 char *type, *chat_type;
    731 
    732                 type = set_getstr(&oic->set, "type");
    733                 chat_type = set_getstr(&oic->set, "chat_type");
    734 
    735                 if (type && chat_type && oic->data == FALSE &&
    736                     strcmp(type, "chat") == 0 &&
    737                     strcmp(chat_type, "groupchat") == 0) {
    738                         /* There's a channel with this name already, but it looks
    739                            like it's not in use yet. Most likely the IRC client
    740                            rejoined the channel after a reconnect. Remove it so
    741                            we can reuse its name. */
    742                         irc_channel_free(oic);
    743                 } else {
    744                         g_free(full_name);
    745                         return FALSE;
    746                 }
    747         }
    748 
    749         g_free(ic->name);
    750         ic->name = full_name;
    751 
    752         return TRUE;
     727        return irc_channel_name_hint(c->ui_data, name);
    753728}
    754729
     
    878853static gboolean bee_irc_channel_chat_join(irc_channel_t *ic)
    879854{
    880         char *acc_s, *room;
     855        char *acc_s, *room, *chat_type;
    881856        account_t *acc;
    882857
    883         if (strcmp(set_getstr(&ic->set, "chat_type"), "room") != 0) {
     858        chat_type = set_getstr(&ic->set, "chat_type");
     859
     860        if (strcmp(chat_type, "room") != 0 && strcmp(chat_type, "placeholder") != 0) {
    884861                return TRUE;
    885862        }
     
    10371014        struct irc_channel *ic = set->data;
    10381015
     1016        ic->flags &= ~(IRC_CHANNEL_TEMP | IRC_CHANNEL_KEEP_PLACEHOLDER);
     1017
    10391018        if (strcmp(value, "groupchat") == 0) {
    10401019                ic->flags |= IRC_CHANNEL_TEMP;
    10411020        } else if (strcmp(value, "room") == 0) {
    1042                 ic->flags &= ~IRC_CHANNEL_TEMP;
     1021                // beep boop
     1022        } else if (strcmp(value, "placeholder") == 0) {
     1023                ic->flags |= IRC_CHANNEL_TEMP | IRC_CHANNEL_KEEP_PLACEHOLDER;
    10431024        } else {
    10441025                return NULL;
     
    11241105        bee_irc_chat_new,
    11251106        bee_irc_chat_free,
     1107        bee_irc_chat_placeholder_new,
    11261108        bee_irc_chat_log,
    11271109        bee_irc_chat_msg,
  • nick.c

    r69982f8 r1522faf  
    214214}
    215215
     216/* Used for nicks and channel names too! */
     217void underscore_dedupe(char nick[MAX_NICK_LENGTH + 1])
     218{
     219        if (strlen(nick) < (MAX_NICK_LENGTH - 1)) {
     220                nick[strlen(nick) + 1] = 0;
     221                nick[strlen(nick)] = '_';
     222        } else {
     223                /* We've got no more space for underscores,
     224                   so truncate it and replace the last three
     225                   chars with a random "_XX" suffix */
     226                int len = truncate_utf8(nick, MAX_NICK_LENGTH - 3);
     227                nick[len] = '_';
     228                g_snprintf(nick + len + 1, 3, "%2x", rand());
     229        }
     230}
     231
    216232void nick_dedupe(bee_user_t *bu, char nick[MAX_NICK_LENGTH + 1])
    217233{
     
    224240        while (!nick_ok(irc, nick) ||
    225241               ((iu = irc_user_by_name(irc, nick)) && iu->bu != bu)) {
    226                 if (strlen(nick) < (MAX_NICK_LENGTH - 1)) {
    227                         nick[strlen(nick) + 1] = 0;
    228                         nick[strlen(nick)] = '_';
    229                 } else {
    230                         /* We've got no more space for underscores,
    231                            so truncate it and replace the last three
    232                            chars with a random "_XX" suffix */
    233                         int len = truncate_utf8(nick, MAX_NICK_LENGTH - 3);
    234                         nick[len] = '_';
    235                         g_snprintf(nick + len + 1, 3, "%2x", rand());
    236                 }
     242
     243                underscore_dedupe(nick);
    237244
    238245                if (inf_protection-- == 0) {
  • nick.h

    r69982f8 r1522faf  
    2828char *nick_get(bee_user_t *bu);
    2929char *nick_gen(bee_user_t *bu);
     30void underscore_dedupe(char nick[MAX_NICK_LENGTH + 1]);
    3031void nick_dedupe(bee_user_t * bu, char nick[MAX_NICK_LENGTH + 1]);
    3132int nick_saved(bee_user_t *bu);
  • protocols/bee.h

    r69982f8 r1522faf  
    115115        gboolean (*chat_new)(bee_t *bee, struct groupchat *c);
    116116        gboolean (*chat_free)(bee_t *bee, struct groupchat *c);
     117        gboolean (*chat_placeholder_new)(bee_t *bee, struct im_connection *ic, const char *handle,
     118                                         const char *name, const char *topic);
    117119        /* System messages of any kind. */
    118120        gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text);
     
    165167 *   user, too. */
    166168G_MODULE_EXPORT struct groupchat *imcb_chat_new(struct im_connection *ic, const char *handle);
     169G_MODULE_EXPORT void imcb_chat_placeholder_new(struct im_connection *ic, const char *handle, const char *name,
     170                                               const char *topic);
    167171G_MODULE_EXPORT void imcb_chat_name_hint(struct groupchat *c, const char *name);
    168172G_MODULE_EXPORT void imcb_chat_free(struct groupchat *c);
  • protocols/bee_chat.c

    r69982f8 r1522faf  
    5454}
    5555
     56void imcb_chat_placeholder_new(struct im_connection *ic, const char *handle, const char *name, const char *topic)
     57{
     58        bee_t *bee = ic->bee;
     59
     60        if (bee->ui->chat_placeholder_new) {
     61                bee->ui->chat_placeholder_new(bee, ic, handle, name, topic);
     62        }
     63}
     64
    5665void imcb_chat_name_hint(struct groupchat *c, const char *name)
    5766{
  • protocols/jabber/Makefile

    r69982f8 r1522faf  
    1313
    1414# [SH] Program variables
    15 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o
     15objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o hipchat.o
    1616
    1717LFLAGS += -r
  • protocols/jabber/conference.c

    r69982f8 r1522faf  
    354354        struct xt_node *subject = xt_find_node(node->children, "subject");
    355355        struct xt_node *body = xt_find_node(node->children, "body");
    356         struct groupchat *chat = bud ? jabber_chat_by_jid(ic, bud->bare_jid) : NULL;
    357         struct jabber_chat *jc = chat ? chat->data : NULL;
    358         char *s;
     356        struct groupchat *chat = NULL;
     357        struct jabber_chat *jc = NULL;
     358        char *from = NULL;
     359        char *nick = NULL;
     360        char *final_from = NULL;
     361        char *bare_jid = NULL;
     362
     363        from = (bud) ? bud->full_jid : xt_find_attr(node, "from");
     364
     365        if (from) {
     366                nick = strchr(from, '/');
     367                if (nick) {
     368                        *nick = 0;
     369                }
     370                chat = jabber_chat_by_jid(ic, from);
     371                if (nick) {
     372                        *nick = '/';
     373                        nick++;
     374                }
     375        }
     376
     377        jc = (chat) ? chat->data : NULL;
     378
     379        if (!bud) {
     380                struct xt_node *c;
     381                char *s;
     382
     383                /* Try some clever stuff to find out the real JID here */
     384                c = xt_find_node_by_attr(node->children, "delay", "xmlns", XMLNS_DELAY);
     385
     386                if (c && ((s = xt_find_attr(c, "from")) ||
     387                          (s = xt_find_attr(c, "from_jid")))) {
     388                        /* This won't be useful if it's the MUC JID */
     389                        if (!(jc && jabber_compare_jid(s, jc->name))) {
     390                                /* Hopefully this one makes more sense! */
     391                                bud = jabber_buddy_by_jid(ic, s, GET_BUDDY_FIRST | GET_BUDDY_CREAT);
     392                        }
     393                }
     394
     395        }
    359396
    360397        if (subject && chat) {
    361                 s = (bud && bud->ext_jid) ? strchr(bud->ext_jid, '/') : NULL;
    362                 if (s) {
    363                         *s = 0;
    364                 }
    365                 imcb_chat_topic(chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ?
    366                                 subject->text : NULL, jabber_get_timestamp(node));
    367                 if (s) {
    368                         *s = '/';
    369                 }
    370         }
    371 
    372         if (bud == NULL || (jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me)) {
    373                 char *nick;
    374 
    375                 if (body == NULL || body->text_len == 0) {
    376                         /* Meh. Empty messages aren't very interesting, no matter
    377                            how much some servers love to send them. */
    378                         return;
    379                 }
    380 
    381                 s = xt_find_attr(node, "from");   /* pkt_message() already NULL-checked this one. */
    382                 nick = strchr(s, '/');
    383                 if (nick) {
    384                         /* If this message included a resource/nick we don't know,
    385                            we might still know the groupchat itself. */
    386                         *nick = 0;
    387                         chat = jabber_chat_by_jid(ic, s);
    388                         *nick = '/';
    389 
    390                         nick++;
     398                char *subject_text = subject->text_len > 0 ? subject->text : NULL;
     399                if (g_strcmp0(chat->topic, subject_text) != 0) {
     400                        bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL;
     401                        imcb_chat_topic(chat, bare_jid, subject_text,
     402                                        jabber_get_timestamp(node));
     403                        g_free(bare_jid);
     404                }
     405        }
     406
     407        if (body == NULL || body->text_len == 0) {
     408                /* Meh. Empty messages aren't very interesting, no matter
     409                   how much some servers love to send them. */
     410                return;
     411        }
     412
     413        if (chat == NULL) {
     414                if (nick == NULL) {
     415                        imcb_log(ic, "System message from unknown groupchat %s: %s", from, body->text);
    391416                } else {
    392                         /* message.c uses the EXACT_JID option, so bud should
    393                            always be NULL here for bare JIDs. */
    394                         chat = jabber_chat_by_jid(ic, s);
    395                 }
    396 
    397                 if (nick == NULL) {
    398                         /* This is fine, the groupchat itself isn't in jd->buddies. */
    399                         if (chat) {
    400                                 imcb_chat_log(chat, "From conference server: %s", body->text);
    401                         } else {
    402                                 imcb_log(ic, "System message from unknown groupchat %s: %s", s, body->text);
    403                         }
    404                 } else {
    405                         /* This can happen too, at least when receiving a backlog when
    406                            just joining a channel. */
    407                         if (chat) {
    408                                 imcb_chat_log(chat, "Message from unknown participant %s: %s", nick, body->text);
    409                         } else {
    410                                 imcb_log(ic, "Groupchat message from unknown JID %s: %s", s, body->text);
    411                         }
     417                        imcb_log(ic, "Groupchat message from unknown JID %s: %s", from, body->text);
    412418                }
    413419
    414420                return;
    415         } else if (chat == NULL) {
    416                 /* How could this happen?? We could do kill( self, 11 )
    417                    now or just wait for the OS to do it. :-) */
     421        } else if (chat != NULL && bud == NULL && nick == NULL) {
     422                imcb_chat_log(chat, "From conference server: %s", body->text);
    418423                return;
    419         }
    420         if (body && body->text_len > 0) {
    421                 s = (bud->ext_jid) ? strchr(bud->ext_jid, '/') : NULL;
    422                 if (s) {
    423                         *s = 0;
    424                 }
    425                 imcb_chat_msg(chat, bud->ext_jid, body->text, 0, jabber_get_timestamp(node));
    426                 if (s) {
    427                         *s = '/';
    428                 }
    429         }
    430 }
     424        } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me) {
     425                /* exclude self-messages since they would get filtered out
     426                 * but not the ones in the backlog */
     427                return;
     428        }
     429
     430        if (bud && jc && bud != jc->me) {
     431                bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid);
     432                final_from = bare_jid;
     433        } else {
     434                final_from = nick;
     435        }
     436
     437        imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node));
     438
     439        g_free(bare_jid);
     440}
  • protocols/jabber/iq.c

    r69982f8 r1522faf  
    2727static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2828static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    29 static int jabber_iq_disco_server(struct im_connection *ic);
    3029
    3130xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)
     
    388387                char *name = xt_find_attr(c, "name");
    389388                char *sub = xt_find_attr(c, "subscription");
     389                char *mention_name = xt_find_attr(c, "mention_name");
     390                char *nick = mention_name ? : name;
    390391
    391392                if (jid && sub) {
     
    396397                                if (name) {
    397398                                        imcb_rename_buddy(ic, jid, name);
     399                                }
     400
     401                                if (nick) {
     402                                        imcb_buddy_nick_hint(ic, jid, nick);
    398403                                }
    399404                        } else if (strcmp(sub, "remove") == 0) {
     
    855860                                                 struct xt_node *node, struct xt_node *orig);
    856861
    857 static int jabber_iq_disco_server(struct im_connection *ic)
     862int jabber_iq_disco_server(struct im_connection *ic)
    858863{
    859864        struct xt_node *node, *iq;
  • protocols/jabber/jabber.c

    r69982f8 r1522faf  
    5656static void jabber_init(account_t *acc)
    5757{
     58        char *default_server = NULL;
    5859        set_t *s;
    5960        char str[16];
    6061
     62        if (strcmp(acc->prpl->name, "hipchat") == 0) {
     63                default_server = "chat.hipchat.com";
     64        } else {
     65                s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
     66        }
     67
    6168        s = set_add(&acc->set, "activity_timeout", "600", set_eval_int, acc);
    62 
    63         s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
    6469
    6570        s = set_add(&acc->set, "display_name", NULL, NULL, acc);
     
    8186        s->flags |= ACC_SET_OFFLINE_ONLY | SET_HIDDEN_DEFAULT;
    8287
    83         s = set_add(&acc->set, "server", NULL, set_eval_account, acc);
     88        s = set_add(&acc->set, "server", default_server, set_eval_account, acc);
    8489        s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
    8590
     
    121126
    122127        jd->fd = jd->r_inpa = jd->w_inpa = -1;
     128
     129        if (strcmp(acc->prpl->name, "hipchat") == 0) {
     130                jd->flags |= JFLAG_HIPCHAT;
     131        }
    123132
    124133        if (jd->server == NULL) {
     
    656665{
    657666        struct prpl *ret = g_new0(struct prpl, 1);
     667        struct prpl *hipchat = NULL;
    658668
    659669        ret->name = "jabber";
     
    686696
    687697        register_protocol(ret);
    688 }
     698
     699        /* Another one for hipchat, which has completely different logins */
     700        hipchat = g_memdup(ret, sizeof(struct prpl));
     701        hipchat->name = "hipchat";
     702        register_protocol(hipchat);
     703}
  • protocols/jabber/jabber.h

    r69982f8 r1522faf  
    4848
    4949        JFLAG_GTALK =  0x100000,        /* Is Google Talk, as confirmed by iq discovery */
     50        JFLAG_HIPCHAT = 0x200000,       /* Is hipchat, because prpl->name says so */
    5051
    5152        JFLAG_SASL_FB = 0x10000,        /* Trying Facebook authentication. */
     
    235236#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    236237
     238/* Hipchat protocol extensions*/
     239#define XMLNS_HIPCHAT         "http://hipchat.com"
     240#define XMLNS_HIPCHAT_PROFILE "http://hipchat.com/protocol/profile"
     241#define XMLNS_HIPCHAT_MUC     "http://hipchat.com/protocol/muc#room"
     242
    237243/* jabber.c */
    238244void jabber_connect(struct im_connection *ic);
     
    244250int jabber_get_roster(struct im_connection *ic);
    245251int jabber_get_vcard(struct im_connection *ic, char *bare_jid);
     252int jabber_iq_disco_muc(struct im_connection *ic, char *muc_server);
    246253int jabber_add_to_roster(struct im_connection *ic, const char *handle, const char *name, const char *group);
    247254int jabber_remove_from_roster(struct im_connection *ic, char *handle);
     
    249256xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns);
    250257void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data);
     258int jabber_iq_disco_server(struct im_connection *ic);
    251259
    252260/* si.c */
     
    306314void jabber_error_free(struct jabber_error *err);
    307315gboolean jabber_set_me(struct im_connection *ic, const char *me);
     316char *jabber_get_bare_jid(char *jid);
    308317
    309318extern const struct jabber_away_state jabber_away_state_list[];
     
    341350void jabber_chat_invite(struct groupchat *c, char *who, char *message);
    342351
     352/* hipchat.c */
     353int jabber_get_hipchat_profile(struct im_connection *ic);
     354xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     355xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node);
     356xt_status jabber_parse_muc_list(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     357
    343358#endif
  • protocols/jabber/jabber_util.c

    r69982f8 r1522faf  
    820820        return TRUE;
    821821}
     822
     823/* Returns new reference! g_free() afterwards. */
     824char *jabber_get_bare_jid(char *jid)
     825{
     826        char *s = NULL;
     827
     828        if (jid == NULL) {
     829                return NULL;
     830        }
     831
     832        if ((s = strchr(jid, '/'))) {
     833                return g_strndup(jid, s - jid);
     834        } else {
     835                return g_strdup(jid);
     836        }
     837}
  • protocols/jabber/sasl.c

    r69982f8 r1522faf  
    5555        char *s;
    5656        int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0;
    57         int want_oauth = FALSE;
     57        int want_oauth = FALSE, want_hipchat = FALSE;
    5858        GString *mechs;
    5959
     
    7575
    7676        want_oauth = set_getbool(&ic->acc->set, "oauth");
     77        want_hipchat = (jd->flags & JFLAG_HIPCHAT);
    7778
    7879        mechs = g_string_new("");
     
    111112
    112113        reply = xt_new_node("auth", NULL, NULL);
    113         xt_add_attr(reply, "xmlns", XMLNS_SASL);
     114        if (!want_hipchat) {
     115                xt_add_attr(reply, "xmlns", XMLNS_SASL);
     116        } else {
     117                xt_add_attr(reply, "xmlns", XMLNS_HIPCHAT);
     118        }
    114119
    115120        if (sup_gtalk && want_oauth) {
     
    143148        } else if (sup_plain) {
    144149                int len;
    145 
    146                 xt_add_attr(reply, "mechanism", "PLAIN");
     150                GString *gs;
     151                char *username;
     152
     153                if (!want_hipchat) {
     154                        xt_add_attr(reply, "mechanism", "PLAIN");
     155                        username = jd->username;
     156                } else {
     157                        username = jd->me;
     158                }
     159
     160                /* set an arbitrary initial size to avoid reallocations */
     161                gs = g_string_sized_new(128);
    147162
    148163                /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */
    149                 len = strlen(jd->username) + strlen(ic->acc->pass) + 2;
    150                 s = g_malloc(len + 1);
    151                 s[0] = 0;
    152                 strcpy(s + 1, jd->username);
    153                 strcpy(s + 2 + strlen(jd->username), ic->acc->pass);
     164                g_string_append_c(gs, '\0');
     165                g_string_append(gs, username);
     166                g_string_append_c(gs, '\0');
     167                g_string_append(gs, ic->acc->pass);
     168                if (want_hipchat) {
     169                        /* Hipchat's variation adds \0resource at the end */
     170                        g_string_append_c(gs, '\0');
     171                        g_string_append(gs, set_getstr(&ic->acc->set, "resource"));
     172                }
     173
     174                len = gs->len;
     175                s = g_string_free(gs, FALSE);
     176
    154177                reply->text = base64_encode((unsigned char *) s, len);
    155178                reply->text_len = strlen(reply->text);
     
    397420                imcb_log(ic, "Authentication finished");
    398421                jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART;
     422
     423                if (jd->flags & JFLAG_HIPCHAT) {
     424                        return hipchat_handle_success(ic, node);
     425                }
    399426        } else if (strcmp(node->name, "failure") == 0) {
    400427                imcb_error(ic, "Authentication failure");
Note: See TracChangeset for help on using the changeset viewer.