Changes in / [2dd23da:fc650a8]


Ignore:
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • irc_im.c

    r2dd23da rfc650a8  
    573573        ic->data = c;
    574574
    575         topic = g_strdup_printf(
    576                 "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!",
    577                 c->title);
    578         irc_channel_set_topic(ic, topic, irc->root);
    579         g_free(topic);
     575        if (ic->topic == NULL) {
     576                /* New channel with no preset topic - make up a generic one */
     577                topic = g_strdup_printf(
     578                        "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!",
     579                        c->title);
     580                irc_channel_set_topic(ic, topic, irc->root);
     581        } else {
     582                /* Preset topic from the channel we picked */
     583                topic = g_strdup(ic->topic);
     584        }
     585
     586        g_free(c->topic);
     587        c->topic = topic;         /* Let groupchat borrow this pointer */
    580588
    581589        return TRUE;
  • protocols/account.c

    r2dd23da rfc650a8  
    8383                } else {
    8484                        strcpy(tag, "aim");
    85                 }
    86         } else if (strcmp(prpl->name, "jabber") == 0) {
    87                 if (strstr(a->user, "@gmail.com") ||
    88                     strstr(a->user, "@googlemail.com")) {
    89                         strcpy(tag, "gtalk");
    90                 } else if (strstr(a->user, "@chat.facebook.com")) {
    91                         strcpy(tag, "fb");
    9285                }
    9386        }
  • protocols/jabber/Makefile

    r2dd23da rfc650a8  
    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

    r2dd23da rfc650a8  
    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 ? 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 = strchr(bud->ext_jid, '/');
    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

    r2dd23da rfc650a8  
    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

    r2dd23da rfc650a8  
    5454};
    5555
     56static jabber_subproto_desc_t jabber_subproto_list[] = {
     57        { "jabber", JSUB_NONE, NULL, NULL },
     58        { "gtalk", JSUB_GTALK, &oauth2_service_google, "talk.google.com" },
     59        { "fb", JSUB_FACEBOOK, &oauth2_service_facebook, "chat.facebook.com" },
     60        { "hipchat", JSUB_HIPCHAT, NULL, "chat.hipchat.com" },
     61        { NULL },
     62};
     63
    5664static void jabber_init(account_t *acc)
    5765{
    5866        set_t *s;
    5967        char str[16];
     68        jabber_subproto_desc_t *subproto = acc->prpl->data;
    6069
    6170        s = set_add(&acc->set, "activity_timeout", "600", set_eval_int, acc);
    6271
    63         s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
    64 
    6572        s = set_add(&acc->set, "display_name", NULL, NULL, acc);
     73
     74        if (subproto->oauth2_service) {
     75                s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);
     76        }
    6677
    6778        g_snprintf(str, sizeof(str), "%d", jabber_port_list[0]);
     
    100111        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |
    101112                      ACC_FLAG_HANDLE_DOMAINS;
     113
     114        if (subproto->server) {
     115                set_setstr(&acc->set, "server", (char *) subproto->server);
     116        }
    102117}
    103118
     
    108123        struct im_connection *ic = imcb_new(acc);
    109124        struct jabber_data *jd = g_new0(struct jabber_data, 1);
     125        jabber_subproto_desc_t *subproto = acc->prpl->data;
    110126        char *s;
    111127
     
    117133        jd->ic = ic;
    118134        ic->proto_data = jd;
     135        jd->subproto = subproto->id;
    119136
    120137        jabber_set_me(ic, acc->user);
     
    141158        jd->buddies = g_hash_table_new(g_str_hash, g_str_equal);
    142159
    143         if (set_getbool(&acc->set, "oauth")) {
     160        if (subproto->oauth2_service && set_getbool(&acc->set, "oauth")) {
    144161                GSList *p_in = NULL;
    145162                const char *tok;
     
    147164                jd->fd = jd->r_inpa = jd->w_inpa = -1;
    148165
    149                 if (strstr(jd->server, ".facebook.com")) {
    150                         jd->oauth2_service = &oauth2_service_facebook;
    151                 } else {
    152                         jd->oauth2_service = &oauth2_service_google;
    153                 }
     166                jd->oauth2_service = subproto->oauth2_service;
    154167
    155168                oauth_params_parse(&p_in, ic->acc->pass);
     
    655668void jabber_initmodule()
    656669{
    657         struct prpl *ret = g_new0(struct prpl, 1);
    658 
    659         ret->name = "jabber";
    660         ret->mms = 0;                        /* no limit */
    661         ret->login = jabber_login;
    662         ret->init = jabber_init;
    663         ret->logout = jabber_logout;
    664         ret->buddy_msg = jabber_buddy_msg;
    665         ret->away_states = jabber_away_states;
    666         ret->set_away = jabber_set_away;
    667 //      ret->set_info = jabber_set_info;
    668         ret->get_info = jabber_get_info;
    669         ret->add_buddy = jabber_add_buddy;
    670         ret->remove_buddy = jabber_remove_buddy;
    671         ret->chat_msg = jabber_chat_msg_;
    672         ret->chat_topic = jabber_chat_topic_;
    673         ret->chat_invite = jabber_chat_invite_;
    674         ret->chat_leave = jabber_chat_leave_;
    675         ret->chat_join = jabber_chat_join_;
    676         ret->chat_with = jabber_chat_with_;
    677         ret->chat_add_settings = jabber_chat_add_settings;
    678         ret->chat_free_settings = jabber_chat_free_settings;
    679         ret->keepalive = jabber_keepalive;
    680         ret->send_typing = jabber_send_typing;
    681         ret->handle_cmp = g_strcasecmp;
    682         ret->handle_is_self = jabber_handle_is_self;
    683         ret->transfer_request = jabber_si_transfer_request;
    684         ret->buddy_action_list = jabber_buddy_action_list;
    685         ret->buddy_action = jabber_buddy_action;
    686 
    687         register_protocol(ret);
    688 }
     670        int i;
     671        struct prpl funcs;
     672
     673        memset(&funcs, 0, sizeof(funcs));
     674
     675        funcs.mms = 0;                        /* no limit */
     676        funcs.login = jabber_login;
     677        funcs.init = jabber_init;
     678        funcs.logout = jabber_logout;
     679        funcs.buddy_msg = jabber_buddy_msg;
     680        funcs.away_states = jabber_away_states;
     681        funcs.set_away = jabber_set_away;
     682        funcs.get_info = jabber_get_info;
     683        funcs.add_buddy = jabber_add_buddy;
     684        funcs.remove_buddy = jabber_remove_buddy;
     685        funcs.chat_msg = jabber_chat_msg_;
     686        funcs.chat_topic = jabber_chat_topic_;
     687        funcs.chat_invite = jabber_chat_invite_;
     688        funcs.chat_leave = jabber_chat_leave_;
     689        funcs.chat_join = jabber_chat_join_;
     690        funcs.chat_with = jabber_chat_with_;
     691        funcs.chat_add_settings = jabber_chat_add_settings;
     692        funcs.chat_free_settings = jabber_chat_free_settings;
     693        funcs.keepalive = jabber_keepalive;
     694        funcs.send_typing = jabber_send_typing;
     695        funcs.handle_cmp = g_strcasecmp;
     696        funcs.handle_is_self = jabber_handle_is_self;
     697        funcs.transfer_request = jabber_si_transfer_request;
     698        funcs.buddy_action_list = jabber_buddy_action_list;
     699        funcs.buddy_action = jabber_buddy_action;
     700
     701        for (i = 0; jabber_subproto_list[i].name; i++) {
     702                struct prpl *subproto = g_memdup(&funcs, sizeof(funcs));
     703                subproto->name = jabber_subproto_list[i].name;
     704                subproto->data = &jabber_subproto_list[i];
     705                register_protocol(subproto);
     706        }
     707}
  • protocols/jabber/jabber.h

    r2dd23da rfc650a8  
    7777} jabber_chat_flags_t;
    7878
     79typedef enum {
     80        JSUB_NONE = 0,
     81        JSUB_GTALK,
     82        JSUB_FACEBOOK,
     83        JSUB_HIPCHAT,
     84} jabber_subproto_t;
     85
     86typedef struct {
     87        const char *name;
     88        jabber_subproto_t id;
     89        const struct oauth2_service *oauth2_service;
     90        const char *server;
     91} jabber_subproto_desc_t;
     92
    7993struct jabber_data {
    8094        struct im_connection *ic;
     
    88102        struct xt_parser *xt;
    89103        jabber_flags_t flags;
     104        jabber_subproto_t subproto;
    90105
    91106        char *username;         /* USERNAME@server */
     
    235250#define XMLNS_IBB          "http://jabber.org/protocol/ibb"                      /* XEP-0047 */
    236251
     252/* Hipchat protocol extensions*/
     253#define XMLNS_HIPCHAT         "http://hipchat.com"
     254#define XMLNS_HIPCHAT_PROFILE "http://hipchat.com/protocol/profile"
     255#define XMLNS_HIPCHAT_MUC     "http://hipchat.com/protocol/muc#room"
     256
    237257/* jabber.c */
    238258void jabber_connect(struct im_connection *ic);
     
    244264int jabber_get_roster(struct im_connection *ic);
    245265int jabber_get_vcard(struct im_connection *ic, char *bare_jid);
     266int jabber_iq_disco_muc(struct im_connection *ic, char *muc_server);
    246267int jabber_add_to_roster(struct im_connection *ic, const char *handle, const char *name, const char *group);
    247268int jabber_remove_from_roster(struct im_connection *ic, char *handle);
     
    249270xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns);
    250271void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data);
     272int jabber_iq_disco_server(struct im_connection *ic);
    251273
    252274/* si.c */
     
    306328void jabber_error_free(struct jabber_error *err);
    307329gboolean jabber_set_me(struct im_connection *ic, const char *me);
     330char *jabber_get_bare_jid(char *jid);
    308331
    309332extern const struct jabber_away_state jabber_away_state_list[];
     
    341364void jabber_chat_invite(struct groupchat *c, char *who, char *message);
    342365
     366/* hipchat.c */
     367int jabber_get_hipchat_profile(struct im_connection *ic);
     368xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     369xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node);
     370xt_status jabber_parse_muc_list(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     371
    343372#endif
  • protocols/jabber/jabber_util.c

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

    r2dd23da rfc650a8  
    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->subproto == JSUB_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->subproto == JSUB_HIPCHAT) {
     424                        return hipchat_handle_success(ic, node);
     425                }
    399426        } else if (strcmp(node->name, "failure") == 0) {
    400427                imcb_error(ic, "Authentication failure");
  • root_commands.c

    r2dd23da rfc650a8  
    395395        if (len >= 1 && g_strncasecmp(cmd[1], "add", len) == 0) {
    396396                struct prpl *prpl;
     397                char *protocol_name = cmd[2];
    397398
    398399                MIN_ARGS(3);
     
    410411                }
    411412
    412                 prpl = find_protocol(cmd[2]);
     413                /* These used to be just hardcoded account tag guesses,
     414                 * now they are promoted to hardecoded subprotocol guesses */
     415                if (strcmp(protocol_name, "jabber") == 0) {
     416                        if (strstr(cmd[3], "@gmail.com") || strstr(cmd[3], "@googlemail.com")) {
     417                                protocol_name = "gtalk";
     418                        } else if (strstr(cmd[3], "@chat.facebook.com")) {
     419                                protocol_name = "fb";
     420                        }
     421                }
     422
     423                prpl = find_protocol(protocol_name);
    413424
    414425                if (prpl == NULL) {
Note: See TracChangeset for help on using the changeset viewer.