Changeset 3fbce97 for protocols


Ignore:
Timestamp:
2016-09-24T20:14:34Z (8 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Children:
ba52ac5
Parents:
63cad66 (diff), 82cb190 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into parson

Location:
protocols
Files:
1 added
72 edited

Legend:

Unmodified
Added
Removed
  • protocols/account.c

    r63cad66 r3fbce97  
    8484                    strstr(a->user, "@googlemail.com")) {
    8585                        strcpy(tag, "gtalk");
    86                 } else if (strstr(a->user, "@chat.facebook.com")) {
    87                         strcpy(tag, "fb");
    8886                }
    8987        }
  • protocols/bee.h

    r63cad66 r3fbce97  
    6262        BEE_USER_LOCAL = 256,   /* Locally-added contacts (not in real contact list) */
    6363        BEE_USER_SPECIAL = 512, /* Denotes a user as being special */
     64        BEE_USER_NOOTR = 4096,  /* Per-user version of OPT_NOOTR */
    6465} bee_user_flags_t;
    6566
     
    104105        gboolean (*user_status)(bee_t *bee, struct bee_user *bu, struct bee_user *old);
    105106        /* On every incoming message. sent_at = 0 means unknown. */
    106         gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at);
     107        gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    107108        /* Flags currently defined (OPT_TYPING/THINKING) in nogaim.h. */
    108109        gboolean (*user_typing)(bee_t *bee, bee_user_t *bu, guint32 flags);
     
    117118        /* System messages of any kind. */
    118119        gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text);
    119         gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at);
     120        gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, guint32 flags, time_t sent_at);
    120121        gboolean (*chat_add_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
    121         gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu);
     122        gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *reason);
    122123        gboolean (*chat_topic)(bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu);
    123124        gboolean (*chat_name_hint)(bee_t *bee, struct groupchat *c, const char *name);
     
    128129        void (*ft_close)(struct im_connection *ic, struct file_transfer *ft);
    129130        void (*ft_finished)(struct im_connection *ic, struct file_transfer *ft);
     131
     132        void (*log)(bee_t *bee, const char *tag, const char *msg);
    130133} bee_ui_funcs_t;
    131134
  • protocols/bee_chat.c

    r63cad66 r3fbce97  
    9595}
    9696
    97 void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at)
     97void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at)
    9898{
    9999        struct im_connection *ic = c->ic;
    100100        bee_t *bee = ic->bee;
    101101        bee_user_t *bu;
    102         gboolean temp;
     102        gboolean temp = FALSE;
    103103        char *s;
    104104
    105         /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */
    106         if (handle_is_self(ic, who)) {
     105        if (handle_is_self(ic, who) && !(flags & OPT_SELFMESSAGE)) {
    107106                return;
    108107        }
     
    122121
    123122        if (bee->ui->chat_msg) {
    124                 bee->ui->chat_msg(bee, c, bu, msg, sent_at);
     123                bee->ui->chat_msg(bee, c, bu, msg, flags, sent_at);
    125124        }
    126125
     
    230229
    231230        if (bee->ui->chat_remove_user && bu) {
    232                 bee->ui->chat_remove_user(bee, c, bu);
     231                bee->ui->chat_remove_user(bee, c, bu, reason);
    233232        }
    234233}
  • protocols/bee_user.c

    r63cad66 r3fbce97  
    247247}
    248248
    249 void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, uint32_t flags, time_t sent_at)
     249void imcb_buddy_msg(struct im_connection *ic, const char *handle, const char *msg, guint32 flags, time_t sent_at)
    250250{
    251251        bee_t *bee = ic->bee;
     
    265265
    266266        if (bee->ui->user_msg && bu) {
    267                 bee->ui->user_msg(bee, bu, msg, sent_at);
     267                bee->ui->user_msg(bee, bu, msg, flags, sent_at);
    268268        } else {
    269269                imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg);
     
    297297}
    298298
    299 void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags)
     299void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags)
    300300{
    301301        bee_user_t *bu;
  • protocols/ft.h

    r63cad66 r3fbce97  
    5858 *                                    | accept
    5959 *                                    V
    60  *                     /------ /-------------\                    /------------------------\
    61  *         out_of_data |       | TRANSFERING | -----------------> | TRANSFERING | CANCELED |
    62  *                     \-----> \-------------/  [canceled,]free   \------------------------/
     60 *                     /------ /-------------\                    /--------------------------\
     61 *         out_of_data |       | TRANSFERRING | -----------------> | TRANSFERRING | CANCELED |
     62 *                     \-----> \-------------/  [canceled,]free   \--------------------------/
    6363 *                                    |
    6464 *                                    | finished,free
    6565 *                                    V
    66  *                       /------------------------\
    67  *                       | TRANSFERING | FINISHED |
    68  *                       \------------------------/
     66 *                       /-------------------------\
     67 *                       | TRANSFERRING | FINISHED |
     68 *                       \-------------------------/
    6969 */
    7070typedef struct file_transfer {
     
    115115
    116116        /*
    117          * If set, called after succesful connection setup.
     117         * If set, called after successful connection setup.
    118118         */
    119119        void (*accept)(struct file_transfer *file);
  • protocols/jabber/conference.c

    r63cad66 r3fbce97  
    2626
    2727static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
     28static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2829
    2930struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password)
     
    121122        }
    122123        if (bud) {
    123                 jabber_chat_free(jabber_chat_by_jid(ic, bud->bare_jid));
     124                struct groupchat *c = jabber_chat_by_jid(ic, bud->bare_jid);
     125                if (c) {
     126                        jabber_chat_free(c);
     127                }
    124128        }
    125129
    126130        return XT_HANDLED;
     131}
     132
     133static xt_status jabber_chat_self_message(struct im_connection *ic, struct xt_node *node, struct xt_node *orig)
     134{
     135        /* This is a self message sent by this bitlbee - just drop it */
     136        return XT_ABORT;
    127137}
    128138
     
    171181        node = jabber_make_packet("message", "groupchat", jc->name, node);
    172182
    173         if (!jabber_write_packet(ic, node)) {
    174                 xt_free_node(node);
    175                 return 0;
    176         }
    177         xt_free_node(node);
    178 
    179         return 1;
     183        jabber_cache_add(ic, node, jabber_chat_self_message);
     184
     185        return !jabber_write_packet(ic, node);
    180186}
    181187
     
    299305                                        }
    300306                                }
    301 
    302                                 /* Some program-specific restrictions. */
    303                                 imcb_clean_handle(ic, bud->ext_jid);
    304307                        }
    305308                        bud->flags |= JBFLAG_IS_ANONYMOUS;
     
    331334        } else if (type) { /* type can only be NULL or "unavailable" in this function */
    332335                if ((bud->flags & JBFLAG_IS_CHATROOM) && bud->ext_jid) {
     336                        char *reason = NULL;
     337                        char *status = NULL;
     338                        char *status_text = NULL;
     339                       
     340                        if ((c = xt_find_node_by_attr(node->children, "x", "xmlns", XMLNS_MUC_USER))) {
     341                                struct xt_node *c2 = c->children;
     342
     343                                while ((c2 = xt_find_node(c2, "status"))) {
     344                                        char *code = xt_find_attr(c2, "code");
     345                                        if (g_strcmp0(code, "301") == 0) {
     346                                                status = "Banned";
     347                                                break;
     348                                        } else if (g_strcmp0(code, "303") == 0) {
     349                                                /* This could be handled in a cleverer way,
     350                                                 * but let's just show a literal part/join for now */
     351                                                status = "Changing nicks";
     352                                                break;
     353                                        } else if (g_strcmp0(code, "307") == 0) {
     354                                                status = "Kicked";
     355                                                break;
     356                                        }
     357                                        c2 = c2->next;
     358                                }
     359
     360                                /* Sometimes the status message is in presence/x/item/reason */
     361                                if ((c2 = xt_find_path(c, "item/reason")) && c2->text && c2->text_len) {
     362                                        status_text = c2->text;
     363                                }
     364                        }
     365
     366                        /* Sometimes the status message is right inside <presence> */
     367                        if ((c = xt_find_node(node->children, "status")) && c->text && c->text_len) {
     368                                status_text = c->text;
     369                        }
     370
     371                        if (status_text && status) {
     372                                reason = g_strdup_printf("%s: %s", status, status_text);
     373                        } else {
     374                                reason = g_strdup(status_text ? : status);
     375                        }
     376
    333377                        s = strchr(bud->ext_jid, '/');
    334378                        if (s) {
    335379                                *s = 0;
    336380                        }
    337                         imcb_chat_remove_buddy(chat, bud->ext_jid, NULL);
     381                        imcb_chat_remove_buddy(chat, bud->ext_jid, reason);
    338382                        if (bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS) {
    339                                 imcb_remove_buddy(ic, bud->ext_jid, NULL);
     383                                imcb_remove_buddy(ic, bud->ext_jid, reason);
    340384                        }
    341385                        if (s) {
    342386                                *s = '/';
    343387                        }
     388
     389                        g_free(reason);
    344390                }
    345391
     
    360406        char *final_from = NULL;
    361407        char *bare_jid = NULL;
     408        guint32 flags = 0;
    362409
    363410        from = (bud) ? bud->full_jid : xt_find_attr(node, "from");
     
    396443
    397444        if (subject && chat) {
    398                 char *subject_text = subject->text_len > 0 ? subject->text : NULL;
     445                char *subject_text = subject->text_len > 0 ? subject->text : "";
    399446                if (g_strcmp0(chat->topic, subject_text) != 0) {
    400447                        bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL;
     
    402449                                        jabber_get_timestamp(node));
    403450                        g_free(bare_jid);
     451                        bare_jid = NULL;
    404452                }
    405453        }
     
    422470                imcb_chat_log(chat, "From conference server: %s", body->text);
    423471                return;
    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 */
     472        } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me &&
     473                   (jabber_cache_handle_packet(ic, node) == XT_ABORT)) {
     474                /* Self message marked by this bitlbee, don't show it */
    427475                return;
    428476        }
    429477
    430         if (bud && jc && bud != jc->me) {
     478        if (bud) {
    431479                bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid);
    432480                final_from = bare_jid;
     481                flags = (bud == jc->me) ? OPT_SELFMESSAGE : 0;
    433482        } else {
    434483                final_from = nick;
    435484        }
    436485
    437         imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node));
     486        imcb_chat_msg(chat, final_from, body->text, flags, jabber_get_timestamp(node));
    438487
    439488        g_free(bare_jid);
  • protocols/jabber/hipchat.c

    r63cad66 r3fbce97  
    4242                *sep = '/';
    4343        }
     44
     45        jd->muc_host = g_strdup(xt_find_attr(node, "muc_host"));
    4446
    4547        /* Hipchat's auth doesn't expect a restart here */
     
    9294
    9395}
     96
     97/* Returns a newly allocated string that tries to match the "slug" part of the JID using an
     98 * approximation of the method used by the server. This might fail in some rare conditions
     99 * (old JIDs generated a different way, locale settings unicode, etc) */
     100char *hipchat_make_channel_slug(const char *name)
     101{
     102        char *lower;
     103        char *new = g_malloc(strlen(name) + 1);
     104        int i = 0;
     105
     106        do {
     107                if (*name == ' ') {
     108                        new[i++] = '_';
     109                } else if (*name && !strchr("\"&'/:<>@", *name)) {
     110                        new[i++] = *name;
     111                }
     112        } while (*(name++));
     113
     114        new[i] = '\0';
     115
     116        lower = g_utf8_strdown(new, -1);
     117        g_free(new);
     118
     119        return lower;
     120}
     121
     122char *hipchat_guess_channel_name(struct im_connection *ic, const char *name)
     123{
     124        struct jabber_data *jd = ic->proto_data;
     125        char *slug, *retval, *underscore;
     126       
     127        if (!(underscore = strchr(jd->username, '_')) || !jd->muc_host) {
     128                return NULL;
     129        }
     130
     131        slug = hipchat_make_channel_slug(name);
     132
     133        /* Get the organization ID from the username, before the underscore */
     134        *underscore = '\0';
     135
     136        retval = g_strdup_printf("%s_%s@%s", jd->username, slug, jd->muc_host);
     137
     138        *underscore = '_';
     139
     140        g_free(slug);
     141
     142        return retval;
     143}
  • protocols/jabber/io.c

    r63cad66 r3fbce97  
    147147}
    148148
    149 static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond)
    150 {
    151         struct im_connection *ic = data;
    152         struct jabber_data *jd = ic->proto_data;
    153         char buf[512];
    154         int st;
    155 
    156         if (jd->fd == -1) {
    157                 return FALSE;
    158         }
    159 
    160         if (jd->ssl) {
    161                 st = ssl_read(jd->ssl, buf, sizeof(buf));
    162         } else {
    163                 st = read(jd->fd, buf, sizeof(buf));
    164         }
    165 
    166         if (st > 0) {
    167                 /* Parse. */
    168                 if (xt_feed(jd->xt, buf, st) < 0) {
     149static gboolean jabber_feed_input(struct im_connection *ic, char *buf, int size)
     150{
     151        struct jabber_data *jd = ic->proto_data;
     152
     153        /* Allow not passing a size for debugging purposes.
     154         * This never happens when reading from the socket */
     155        if (size == -1) {
     156                size = strlen(buf);
     157        }
     158
     159        /* Parse. */
     160        if (xt_feed(jd->xt, buf, size) < 0) {
     161                imcb_error(ic, "XML stream error");
     162                imc_logout(ic, TRUE);
     163                return FALSE;
     164        }
     165
     166        /* Execute all handlers. */
     167        if (!xt_handle(jd->xt, NULL, 1)) {
     168                /* Don't do anything, the handlers should have
     169                   aborted the connection already. */
     170                return FALSE;
     171        }
     172
     173        if (jd->flags & JFLAG_STREAM_RESTART) {
     174                jd->flags &= ~JFLAG_STREAM_RESTART;
     175                jabber_start_stream(ic);
     176        }
     177
     178        /* Garbage collection. */
     179        xt_cleanup(jd->xt, NULL, 1);
     180
     181        /* This is a bit hackish, unfortunately. Although xmltree
     182           has nifty event handler stuff, it only calls handlers
     183           when nodes are complete. Since the server should only
     184           send an opening <stream:stream> tag, we have to check
     185           this by hand. :-( */
     186        if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) {
     187                if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) {
     188                        jd->flags |= JFLAG_STREAM_STARTED;
     189
     190                        /* If there's no version attribute, assume
     191                           this is an old server that can't do SASL
     192                           authentication. */
     193                        if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) {
     194                                /* If there's no version= tag, we suppose
     195                                   this server does NOT implement: XMPP 1.0,
     196                                   SASL and TLS. */
     197                                if (set_getbool(&ic->acc->set, "tls")) {
     198                                        imcb_error(ic, "TLS is turned on for this "
     199                                                   "account, but is not supported by this server");
     200                                        imc_logout(ic, FALSE);
     201                                        return FALSE;
     202                                } else {
     203                                        if (!jabber_init_iq_auth(ic)) {
     204                                                return FALSE;
     205                                        }
     206                                }
     207                        }
     208                } else {
    169209                        imcb_error(ic, "XML stream error");
    170210                        imc_logout(ic, TRUE);
    171211                        return FALSE;
    172212                }
    173 
    174                 /* Execute all handlers. */
    175                 if (!xt_handle(jd->xt, NULL, 1)) {
    176                         /* Don't do anything, the handlers should have
    177                            aborted the connection already. */
     213        }
     214
     215        return TRUE;
     216}
     217
     218
     219static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond)
     220{
     221        struct im_connection *ic = data;
     222        struct jabber_data *jd = ic->proto_data;
     223        char buf[512];
     224        int st;
     225
     226        if (jd->fd == -1) {
     227                return FALSE;
     228        }
     229
     230        if (jd->ssl) {
     231                st = ssl_read(jd->ssl, buf, sizeof(buf));
     232        } else {
     233                st = read(jd->fd, buf, sizeof(buf));
     234        }
     235
     236        if (st > 0) {
     237                if (!jabber_feed_input(ic, buf, st)) {
    178238                        return FALSE;
    179                 }
    180 
    181                 if (jd->flags & JFLAG_STREAM_RESTART) {
    182                         jd->flags &= ~JFLAG_STREAM_RESTART;
    183                         jabber_start_stream(ic);
    184                 }
    185 
    186                 /* Garbage collection. */
    187                 xt_cleanup(jd->xt, NULL, 1);
    188 
    189                 /* This is a bit hackish, unfortunately. Although xmltree
    190                    has nifty event handler stuff, it only calls handlers
    191                    when nodes are complete. Since the server should only
    192                    send an opening <stream:stream> tag, we have to check
    193                    this by hand. :-( */
    194                 if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) {
    195                         if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) {
    196                                 jd->flags |= JFLAG_STREAM_STARTED;
    197 
    198                                 /* If there's no version attribute, assume
    199                                    this is an old server that can't do SASL
    200                                    authentication. */
    201                                 if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) {
    202                                         /* If there's no version= tag, we suppose
    203                                            this server does NOT implement: XMPP 1.0,
    204                                            SASL and TLS. */
    205                                         if (set_getbool(&ic->acc->set, "tls")) {
    206                                                 imcb_error(ic, "TLS is turned on for this "
    207                                                            "account, but is not supported by this server");
    208                                                 imc_logout(ic, FALSE);
    209                                                 return FALSE;
    210                                         } else {
    211                                                 return jabber_init_iq_auth(ic);
    212                                         }
    213                                 }
    214                         } else {
    215                                 imcb_error(ic, "XML stream error");
    216                                 imc_logout(ic, TRUE);
    217                                 return FALSE;
    218                         }
    219239                }
    220240        } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) {
  • protocols/jabber/iq.c

    r63cad66 r3fbce97  
    2828static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    2929static xt_status jabber_gmail_handle_new(struct im_connection *ic, struct xt_node *node);
     30static xt_status jabber_iq_carbons_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    3031
    3132xt_status jabber_pkt_iq(struct xt_node *node, gpointer data)
     
    5253                      (c = xt_find_node(node->children, "time"))) ||
    5354                    !(s = xt_find_attr(c, "xmlns"))) {
    54                         /* Sigh. Who decided to suddenly invent new elements
    55                            instead of just sticking with <query/>? */
    56                         return XT_HANDLED;
     55
     56                        reply = jabber_make_error_packet(node, "service-unavailable", "cancel", NULL);
     57                        st = jabber_write_packet(ic, reply);
     58                        xt_free_node(reply);
     59                        return st;
    5760                }
    5861
     
    118121                                                   XMLNS_BYTESTREAMS,
    119122                                                   XMLNS_FILETRANSFER,
     123                                                   XMLNS_CARBONS,
    120124                                                   NULL };
    121125                        const char **f;
     
    134138                } else {
    135139                        xt_free_node(reply);
    136                         reply = jabber_make_error_packet(node, "feature-not-implemented", "cancel", NULL);
     140                        reply = jabber_make_error_packet(node, "service-unavailable", "cancel", NULL);
    137141                        pack = 0;
    138142                }
     
    385389        struct xt_node *response;
    386390        struct jabber_data *jd = ic->proto_data;
    387 
    388         response = jabber_make_packet("iq", "result", g_strdup_printf("%s@%s", jd->username, jd->server), NULL);
     391       
     392        response = jabber_make_packet("iq", "result", jd->me, NULL);
    389393
    390394        jabber_cache_add(ic, response, NULL);
     
    10041008{
    10051009        struct jabber_data *jd = ic->proto_data;
    1006         struct xt_node *id;
    1007 
    1008         if ((id = xt_find_path(node, "query/identity"))) {
     1010        struct xt_node *query, *id;
     1011
     1012        if (!(query = xt_find_node(node->children, "query"))) {
     1013                return XT_HANDLED;
     1014        }
     1015
     1016        if (xt_find_node_by_attr(query->children, "feature", "var", XMLNS_CARBONS) &&
     1017            set_getbool(&ic->acc->set, "carbons")) {
     1018
     1019                struct xt_node *enable, *iq;
     1020
     1021                enable = xt_new_node("enable", NULL, NULL);
     1022                xt_add_attr(enable, "xmlns", XMLNS_CARBONS);
     1023                iq = jabber_make_packet("iq", "set", NULL, enable);
     1024
     1025                jabber_cache_add(ic, iq, jabber_iq_carbons_response);
     1026                jabber_write_packet(ic, iq);
     1027        }
     1028
     1029        if ((id = xt_find_node(query->children, "identity"))) {
    10091030                char *cat, *type, *name;
    10101031
     
    10231044        return XT_HANDLED;
    10241045}
     1046
     1047static xt_status jabber_iq_carbons_response(struct im_connection *ic,
     1048                                            struct xt_node *node, struct xt_node *orig)
     1049{
     1050        struct jabber_error *err;
     1051
     1052        if ((err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR))) {
     1053                imcb_error(ic, "Error enabling carbons: %s%s%s",
     1054                           err->code, err->text ? ": " : "", err->text ? err->text : "");
     1055                jabber_error_free(err);
     1056        } else {
     1057                imcb_log(ic, "Carbons enabled");
     1058        }
     1059
     1060        return XT_HANDLED;
     1061}
  • protocols/jabber/jabber.c

    r63cad66 r3fbce97  
    114114        s->flags |= ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
    115115
     116        s = set_add(&acc->set, "carbons", "true", set_eval_bool, acc);
     117        s->flags |= ACC_SET_OFFLINE_ONLY;
     118
    116119        acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE |
    117120                      ACC_FLAG_HANDLE_DOMAINS;
     
    148151        }
    149152
     153        if (strstr(jd->server, ".facebook.com")) {
     154                imcb_error(ic, "Facebook's XMPP service is gone. Try this instead: https://wiki.bitlbee.org/HowtoFacebookMQTT");
     155                imc_logout(ic, FALSE);
     156                return;
     157        }
     158
    150159        if ((s = strchr(jd->server, '/'))) {
    151160                *s = 0;
     
    167176                jd->fd = jd->r_inpa = jd->w_inpa = -1;
    168177
    169                 if (strstr(jd->server, ".facebook.com")) {
    170                         jd->oauth2_service = &oauth2_service_facebook;
    171                 } else {
    172                         jd->oauth2_service = &oauth2_service_google;
    173                 }
     178                /* There are no other options atm, so assume google for everything
     179                   Facebook and MSN XMPP used to be here. RIP. */
     180                jd->oauth2_service = &oauth2_service_google;
    174181
    175182                oauth_params_parse(&p_in, ic->acc->pass);
     
    197204        } else {
    198205                jabber_connect(ic);
     206        }
     207}
     208
     209static void jabber_xmlconsole_enable(struct im_connection *ic)
     210{
     211        struct jabber_data *jd = ic->proto_data;
     212        const char *handle = JABBER_XMLCONSOLE_HANDLE;
     213        bee_user_t *bu;
     214       
     215        jd->flags |= JFLAG_XMLCONSOLE;
     216
     217        if (!(bu = bee_user_by_handle(ic->bee, ic, handle))) {
     218                bu = bee_user_new(ic->bee, ic, handle, 0);
     219                bu->flags |= BEE_USER_NOOTR;
    199220        }
    200221}
     
    266287
    267288        if (set_getbool(&acc->set, "xmlconsole")) {
    268                 jd->flags |= JFLAG_XMLCONSOLE;
    269                 /* Shouldn't really do this at this stage already, maybe. But
    270                    I think this shouldn't break anything. */
    271                 imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);
     289                jabber_xmlconsole_enable(ic);
    272290        }
    273291
     
    334352        }
    335353        if (jd->fd >= 0) {
    336                 closesocket(jd->fd);
     354                proxy_disconnect(jd->fd);
    337355        }
    338356
     
    345363        }
    346364
    347         jabber_buddy_remove_all(ic);
     365        if (jd->buddies) {
     366                jabber_buddy_remove_all(ic);
     367        }
    348368
    349369        xt_free(jd->xt);
     
    355375        g_free(jd->internal_jid);
    356376        g_free(jd->gmail_tid);
     377        g_free(jd->muc_host);
    357378        g_free(jd->username);
    358379        g_free(jd->me);
     
    413434        }
    414435
     436        /* XEP-0364 suggests we add message processing hints (XEP-0334) to OTR messages,
     437           mostly to avoid carbons (XEP-0280) and server-side message archiving.
     438           OTR messages are roughly like this: /^\?OTR(.*\?| Error:|:)/
     439           But I'm going to simplify it to messages starting with "?OTR". */
     440        if (g_str_has_prefix(message, "?OTR")) {
     441                int i;
     442                char *hints[] = {
     443                        "no-copy", XMLNS_HINTS,
     444                        "no-permanent-store", XMLNS_HINTS,
     445                        "private", XMLNS_CARBONS,
     446                        NULL
     447                };
     448                       
     449                for (i = 0; hints[i]; i += 2) {
     450                        struct xt_node *hint;
     451                        hint = xt_new_node(hints[i], NULL, NULL);
     452                        xt_add_attr(hint, "xmlns", hints[i + 1]);
     453                        xt_add_child(node, hint);
     454                }
     455        }
     456
    415457        st = jabber_write_packet(ic, node);
    416458        xt_free_node(node);
     
    472514static void jabber_add_buddy(struct im_connection *ic, char *who, char *group)
    473515{
    474         struct jabber_data *jd = ic->proto_data;
    475 
    476516        if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) {
    477                 jd->flags |= JFLAG_XMLCONSOLE;
    478                 imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL);
     517                jabber_xmlconsole_enable(ic);
    479518                return;
    480519        }
     
    520559        }
    521560
     561        if (jd->flags & JFLAG_HIPCHAT && jd->muc_host && !g_str_has_suffix(room, jd->muc_host)) {
     562                char *guessed_name = hipchat_guess_channel_name(ic, room);
     563                if (guessed_name) {
     564                        set_setstr(sets, "room", guessed_name);
     565                        g_free(guessed_name);
     566
     567                        /* call this same function again with the fixed name */
     568                        return jabber_chat_join_(ic, set_getstr(sets, "room"), nick, password, sets);
     569                }
     570        }
     571
    522572        if (strchr(room, '@') == NULL) {
    523573                imcb_error(ic, "%s is not a valid Jabber room name. Maybe you mean %s@conference.%s?",
     
    526576                imcb_error(ic, "Already present in chat `%s'", room);
    527577        } else {
     578                /* jabber_chat_join without the underscore is the conference.c one */
    528579                return jabber_chat_join(ic, room, final_nick, set_getstr(sets, "password"));
    529580        }
     
    590641{
    591642        struct jabber_data *jd = ic->proto_data;
    592         struct jabber_buddy *bud;
     643        struct jabber_buddy *bud, *bare;
    593644
    594645        /* Enable typing notification related code from now. */
    595646        jd->flags |= JFLAG_WANT_TYPING;
    596647
    597         if ((bud = jabber_buddy_by_jid(ic, who, 0)) == NULL) {
     648        if ((bud = jabber_buddy_by_jid(ic, who, 0)) == NULL ||
     649            (bare = jabber_buddy_by_jid(ic, who, GET_BUDDY_BARE)) == NULL) {
    598650                /* Sending typing notifications to unknown buddies is
    599651                   unsupported for now. Shouldn't be a problem, I think. */
     
    601653        }
    602654
    603         if (bud->flags & JBFLAG_DOES_XEP85) {
     655
     656        if (bud->flags & JBFLAG_DOES_XEP85 || bare->flags & JBFLAG_DOES_XEP85) {
    604657                /* We're only allowed to send this stuff if we know the other
    605                    side supports it. */
     658                   side supports it. If the bare JID has the flag, all other
     659                   resources get it, too (That is the case in gtalk) */
    606660
    607661                struct xt_node *node;
  • protocols/jabber/jabber.h

    r63cad66 r3fbce97  
    5050        JFLAG_GTALK =  0x100000,        /* Is Google Talk, as confirmed by iq discovery */
    5151        JFLAG_HIPCHAT = 0x200000,       /* Is hipchat, because prpl->name says so */
    52 
    53         JFLAG_SASL_FB = 0x10000,        /* Trying Facebook authentication. */
    5452} jabber_flags_t;
    5553
     
    113111        GSList *streamhosts;
    114112        int have_streamhosts;
     113
     114        char *muc_host;
    115115};
    116116
     
    228228#define XMLNS_XDATA        "jabber:x:data"                                       /* XEP-0004 */
    229229#define XMLNS_GMAILNOTIFY  "google:mail:notify"                                  /* Not a XEP */
     230#define XMLNS_CARBONS      "urn:xmpp:carbons:2"                                  /* XEP-0280 */
     231#define XMLNS_FORWARDING   "urn:xmpp:forward:0"                                  /* XEP-0297 */
     232#define XMLNS_HINTS        "urn:xmpp:hints"                                      /* XEP-0334 */
    230233#define XMLNS_CHATSTATES   "http://jabber.org/protocol/chatstates"               /* XEP-0085 */
    231234#define XMLNS_DISCO_INFO   "http://jabber.org/protocol/disco#info"               /* XEP-0030 */
     
    338341
    339342extern const struct oauth2_service oauth2_service_google;
    340 extern const struct oauth2_service oauth2_service_facebook;
    341343
    342344/* conference.c */
     
    356358xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig);
    357359xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node);
     360char *hipchat_make_channel_slug(const char *name);
     361char *hipchat_guess_channel_name(struct im_connection *ic, const char *name);
    358362
    359363#endif
  • protocols/jabber/jabber_util.c

    r63cad66 r3fbce97  
    514514                } else if (bud->resource && (flags & GET_BUDDY_EXACT)) {
    515515                        /* We want an exact match, so in thise case there shouldn't be a /resource. */
    516                         return NULL;
     516                        if (head != bud && head->resource == NULL) {
     517                                return head;
     518                        } else {
     519                                return NULL;
     520                        }
    517521                } else if (bud->resource == NULL || bud->next == NULL) {
    518522                        /* No need for selection if there's only one option. */
  • protocols/jabber/message.c

    r63cad66 r3fbce97  
    2424#include "jabber.h"
    2525
    26 xt_status jabber_pkt_message(struct xt_node *node, gpointer data)
     26static xt_status jabber_pkt_message_normal(struct xt_node *node, gpointer data, gboolean carbons_sent)
    2727{
    2828        struct im_connection *ic = data;
    29         char *from = xt_find_attr(node, "from");
     29        struct jabber_data *jd = ic->proto_data;
     30        char *from = xt_find_attr(node, carbons_sent ? "to" : "from");
    3031        char *type = xt_find_attr(node, "type");
    3132        char *id = xt_find_attr(node, "id");
     
    3738        if (!from) {
    3839                return XT_HANDLED; /* Consider this packet corrupted. */
    39 
    40         }
    41         if (request && id) {
     40        }
     41
     42        /* try to detect hipchat's own version of self-messages */
     43        if (jd->flags & JFLAG_HIPCHAT) {
     44                struct xt_node *c;
     45
     46                if ((c = xt_find_node_by_attr(node->children, "delay", "xmlns", XMLNS_DELAY)) &&
     47                    (s = xt_find_attr(c, "from_jid")) &&
     48                    jabber_compare_jid(s, jd->me)) {
     49                        carbons_sent = TRUE;
     50                }
     51        }
     52
     53        if (request && id && g_strcmp0(type, "groupchat") != 0 && !carbons_sent) {
    4254                /* Send a message receipt (XEP-0184), looking like this:
    43                  * <message
    44                  *  from='kingrichard@royalty.england.lit/throne'
    45                  *  id='bi29sg183b4v'
    46                  *  to='northumberland@shakespeare.lit/westminster'>
     55                 * <message from='...' id='...' to='...'>
    4756                 *  <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/>
    48                  * </message> */
     57                 * </message>
     58                 *
     59                 * MUC messages are excluded, since receipts aren't supposed to be sent over MUCs
     60                 * (XEP-0184 section 5.3) and replying to those may result in 'forbidden' errors.
     61                 */
    4962                struct xt_node *received, *receipt;
    5063
     
    127140                if (fullmsg->len > 0) {
    128141                        imcb_buddy_msg(ic, from, fullmsg->str,
    129                                        0, jabber_get_timestamp(node));
     142                                       carbons_sent ? OPT_SELFMESSAGE : 0, jabber_get_timestamp(node));
    130143                }
    131144                if (room) {
     
    136149
    137150                /* Handling of incoming typing notifications. */
    138                 if (bud == NULL) {
    139                         /* Can't handle these for unknown buddies. */
     151                if (bud == NULL || carbons_sent) {
     152                        /* Can't handle these for unknown buddies.
     153                           And ignore them if it's just carbons */
    140154                } else if (xt_find_node(node->children, "composing")) {
    141155                        bud->flags |= JBFLAG_DOES_XEP85;
    142156                        imcb_buddy_typing(ic, from, OPT_TYPING);
    143157                }
    144                 /* No need to send a "stopped typing" signal when there's a message. */
    145                 else if (xt_find_node(node->children, "active") && (body == NULL)) {
     158                else if (xt_find_node(node->children, "active")) {
    146159                        bud->flags |= JBFLAG_DOES_XEP85;
    147                         imcb_buddy_typing(ic, from, 0);
     160
     161                        /* No need to send a "stopped typing" signal when there's a message. */
     162                        if (body == NULL) {
     163                                imcb_buddy_typing(ic, from, 0);
     164                        }
    148165                } else if (xt_find_node(node->children, "paused")) {
    149166                        bud->flags |= JBFLAG_DOES_XEP85;
     
    158175        return XT_HANDLED;
    159176}
     177
     178static xt_status jabber_carbons_message(struct xt_node *node, gpointer data)
     179{
     180        struct im_connection *ic = data;
     181        struct xt_node *wrap, *fwd, *msg;
     182        gboolean carbons_sent;
     183
     184        if ((wrap = xt_find_node(node->children, "received"))) {
     185                carbons_sent = FALSE;
     186        } else if ((wrap = xt_find_node(node->children, "sent"))) {
     187                carbons_sent = TRUE;
     188        }
     189
     190        if (wrap == NULL || g_strcmp0(xt_find_attr(wrap, "xmlns"), XMLNS_CARBONS) != 0) {
     191                return XT_NEXT;
     192        }
     193
     194        if (!(fwd = xt_find_node(wrap->children, "forwarded")) ||
     195             (g_strcmp0(xt_find_attr(fwd, "xmlns"), XMLNS_FORWARDING) != 0) ||
     196            !(msg = xt_find_node(fwd->children, "message"))) {
     197                imcb_log(ic, "Error: Invalid carbons message received");
     198                return XT_ABORT;
     199        }
     200
     201        return jabber_pkt_message_normal(msg, data, carbons_sent);
     202}
     203
     204xt_status jabber_pkt_message(struct xt_node *node, gpointer data)
     205{
     206        struct im_connection *ic = data;
     207        struct jabber_data *jd = ic->proto_data;
     208        char *from = xt_find_attr(node, "from");
     209
     210        if (jabber_compare_jid(jd->me, from)) {    /* Probably a Carbons message */
     211                xt_status st = jabber_carbons_message(node, data);
     212                if (st == XT_HANDLED || st == XT_ABORT) {
     213                        return st;
     214                }
     215        }
     216        return jabber_pkt_message_normal(node, data, FALSE);
     217}
  • protocols/jabber/presence.c

    r63cad66 r3fbce97  
    186186        char *prio = set_getstr(&ic->acc->set, "priority");
    187187
    188         if (jd->away_state->code != NULL) {
     188        if (jd->away_state && jd->away_state->full_name != NULL) {
    189189                int new_prio = (atoi(prio) - 5);
    190190                if (new_prio < 0) {
     
    222222        cap = xt_new_node("c", NULL, NULL);
    223223        xt_add_attr(cap, "xmlns", XMLNS_CAPS);
    224         xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps");
     224
     225        if (jd->flags & JFLAG_HIPCHAT) {
     226                /* hipchat specific node, whitelisted by request to receive self-messages */
     227                xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps/hipchat");
     228        } else {
     229                xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps");
     230        }
    225231        xt_add_attr(cap, "ver", BITLBEE_VERSION);   /* The XEP wants this hashed, but nobody's doing that. */
    226232        xt_add_child(node, cap);
  • protocols/jabber/s5bytestream.c

    r63cad66 r3fbce97  
    536536                 * that sends atyp=0 addrlen=0 and only 6 bytes (one less than one would expect).
    537537                 * Therefore I removed the wait for more bytes. Since we don't care about what else the proxy
    538                  * is sending, it shouldnt matter */
     538                 * is sending, it should not matter */
    539539
    540540                if (bt->tf->ft->sending) {
     
    559559 * An intelligent sender would probably specify himself as the first streamhost and
    560560 * a proxy as the second (Kopete and PSI are examples here). That way, a (potentially)
    561  * slow proxy is only used if neccessary. This of course also means, that the timeout
     561 * slow proxy is only used if necessary. This of course also means, that the timeout
    562562 * per streamhost should be kept short. If one or two firewalled adresses are specified,
    563563 * they have to timeout first before a proxy is tried.
  • protocols/jabber/sasl.c

    r63cad66 r3fbce97  
    3838        "6C-Zgf7Tr7gEQTPlBhMUgo7R",
    3939};
    40 const struct oauth2_service oauth2_service_facebook =
    41 {
    42         "https://www.facebook.com/dialog/oauth",
    43         "https://graph.facebook.com/oauth/access_token",
    44         "https://www.bitlbee.org/main.php/Facebook/oauth2.html",
    45         "offline_access,xmpp_login",
    46         "126828914005625",
    47         "4b100f0f244d620bf3f15f8b217d4c32",
    48 };
    4940
    5041xt_status sasl_pkt_mechanisms(struct xt_node *node, gpointer data)
     
    5445        struct xt_node *c, *reply;
    5546        char *s;
    56         int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0, sup_anonymous = 0;
     47        int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_anonymous = 0;
    5748        int want_oauth = FALSE, want_hipchat = FALSE, want_anonymous = FALSE;
    5849        GString *mechs;
     
    8980                } else if (c->text && g_strcasecmp(c->text, "X-OAUTH2") == 0) {
    9081                        sup_gtalk = 1;
    91                 } else if (c->text && g_strcasecmp(c->text, "X-FACEBOOK-PLATFORM") == 0) {
    92                         sup_fb = 1;
    9382                }
    9483
     
    10190
    10291        if (!want_oauth && !sup_plain && !sup_digest) {
    103                 if (!sup_gtalk && !sup_fb) {
     92                if (!sup_gtalk) {
    10493                        imcb_error(ic, "This server requires OAuth "
    10594                                   "(supported schemes:%s)", mechs->str);
     
    137126                reply->text_len = strlen(reply->text);
    138127                g_free(s);
    139         } else if (sup_fb && want_oauth) {
    140                 xt_add_attr(reply, "mechanism", "X-FACEBOOK-PLATFORM");
    141                 jd->flags |= JFLAG_SASL_FB;
    142128        } else if (want_oauth) {
    143129                imcb_error(ic, "OAuth requested, but not supported by server");
     
    154140                xt_free_node(reply);
    155141                return XT_ABORT;
    156         } else if (sup_digest) {
     142        } else if (sup_digest && !(jd->ssl && sup_plain)) {
     143                /* Only try DIGEST-MD5 if there's no SSL/TLS or if PLAIN isn't supported.
     144                 * Which in practice means "don't bother with DIGEST-MD5 most of the time".
     145                 * It's weak, pointless over TLS, and often breaks with some servers (hi openfire) */
     146
    157147                xt_add_attr(reply, "mechanism", "DIGEST-MD5");
    158148
     
    295285        dec = frombase64(node->text);
    296286
    297         if (jd->flags & JFLAG_SASL_FB) {
    298                 /* New-style Facebook OAauth2 support. Instead of sending a refresh
    299                    token, they just send an access token that should never expire. */
    300                 GSList *p_in = NULL, *p_out = NULL;
    301                 char time[33];
    302 
    303                 oauth_params_parse(&p_in, dec);
    304                 oauth_params_add(&p_out, "nonce", oauth_params_get(&p_in, "nonce"));
    305                 oauth_params_add(&p_out, "method", oauth_params_get(&p_in, "method"));
    306                 oauth_params_free(&p_in);
    307 
    308                 g_snprintf(time, sizeof(time), "%lld", (long long) (gettime() * 1000));
    309                 oauth_params_add(&p_out, "call_id", time);
    310                 oauth_params_add(&p_out, "api_key", oauth2_service_facebook.consumer_key);
    311                 oauth_params_add(&p_out, "v", "1.0");
    312                 oauth_params_add(&p_out, "format", "XML");
    313                 oauth_params_add(&p_out, "access_token", jd->oauth2_access_token);
    314 
    315                 reply = oauth_params_string(p_out);
    316                 oauth_params_free(&p_out);
    317         } else if (!(s = sasl_get_part(dec, "rspauth"))) {
     287        if (!(s = sasl_get_part(dec, "rspauth"))) {
    318288                /* See RFC 2831 for for information. */
    319289                md5_state_t A1, A2, H;
  • protocols/jabber/si.c

    r63cad66 r3fbce97  
    186186        jd->filetransfers = g_slist_prepend(jd->filetransfers, tf);
    187187
    188         /* query buddy's features and server's streaming proxies if neccessary */
     188        /* query buddy's features and server's streaming proxies if necessary */
    189189
    190190        if (!tf->bud->features) {
     
    283283
    284284        if (requestok) {
    285                 /* Figure out who the transfer should come frome... */
     285                /* Figure out who the transfer should come from... */
    286286
    287287                ext_jid = ini_jid;
     
    403403         * <iq from=... to=... id=...>
    404404         *      <si xmlns=si>
    405          *      [       <file xmlns=ft/>    ] <-- not neccessary
     405         *      [       <file xmlns=ft/>    ] <-- not necessary
    406406         *              <feature xmlns=feature>
    407407         *                      <x xmlns=xdata type=submit>
  • protocols/msn/gw.c

    r63cad66 r3fbce97  
    2222        gw->ssl = (GATEWAY_PORT == 443);
    2323        gw->poll_timeout = -1;
     24        gw->write_timeout = -1;
    2425        gw->ic = ic;
    2526        gw->md = ic->proto_data;
     
    3435                b_event_remove(gw->poll_timeout);
    3536        }
     37
     38        if (gw->write_timeout != -1) {
     39                b_event_remove(gw->write_timeout);
     40        }
     41
    3642        g_byte_array_free(gw->in, TRUE);
    3743        g_byte_array_free(gw->out, TRUE);
     
    189195}
    190196
    191 void msn_gw_write(struct msn_gw *gw, char *buf, size_t len)
    192 {
    193         g_byte_array_append(gw->out, (const guint8 *) buf, len);
     197static gboolean msn_gw_write_cb(gpointer data, gint source, b_input_condition cond)
     198{
     199        struct msn_gw *gw;
     200       
     201        if (!(gw = msn_gw_from_ic(data))) {
     202                return FALSE;
     203        }
     204
    194205        if (!gw->open) {
    195206                msn_gw_open(gw);
     
    197208                msn_gw_dorequest(gw, NULL);
    198209        }
    199 }
     210
     211        gw->write_timeout = -1;
     212        return FALSE;
     213}
     214
     215void msn_gw_write(struct msn_gw *gw, char *buf, size_t len)
     216{
     217        g_byte_array_append(gw->out, (const guint8 *) buf, len);
     218
     219        /* do a bit of buffering here to send several commands with a single request */
     220        if (gw->write_timeout == -1) {
     221                gw->write_timeout = b_timeout_add(1, msn_gw_write_cb, gw->ic);
     222        }
     223}
  • protocols/msn/msn.h

    r63cad66 r3fbce97  
    112112
    113113        int poll_timeout;
     114        int write_timeout;
    114115
    115116        b_event_handler callback;
  • protocols/msn/msn_util.c

    r63cad66 r3fbce97  
    4141        }
    4242
    43         return g_markup_printf_escaped("<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>",
     43        return g_markup_printf_escaped("<ml><d n=\"%s\"><c n=\"%s\" t=\"1\"><s n=\"IM\" l=\"%d\" /></c></d></ml>",
    4444                                       domain, handle, list);
    4545}
  • protocols/msn/ns.c

    r63cad66 r3fbce97  
    3939static void msn_ns_send_adl(struct im_connection *ic);
    4040static void msn_ns_structured_message(struct msn_data *md, char *msg, int msglen, char **cmd);
    41 static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action);
     41static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action, gboolean selfmessage);
    4242static void msn_ns_nfy(struct msn_data *md, char *who, char **parts, char *action, gboolean is_put);
    4343
     
    110110        struct im_connection *ic = md->ic;
    111111
     112        /* this should be taken from XFR, but hardcoding it for now. it also prevents more redirects. */
     113        const char *redir_data = "VmVyc2lvbjogMQ0KWGZyQ291bnQ6IDINCklzR2VvWGZyOiB0cnVlDQo=";
     114
    112115        if (source == -1 && !md->is_http) {
    113116                imcb_error(ic, "Could not connect to server");
     
    135138        }
    136139
    137         if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) {
     140        /* Having to handle potential errors in each write sure makes these ifs awkward...*/
     141
     142        if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER) &&
     143            msn_ns_write(ic, source, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s %s\r\n",
     144                         ++md->trId, ic->acc->user, redir_data) &&
     145            msn_ns_write(ic, md->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user)) {
     146
    138147                if (!md->is_http) {
    139148                        md->inpa = b_input_add(md->fd, B_EV_IO_READ, msn_ns_callback, md);
     
    208217                }
    209218
    210                 return(msn_ns_write(ic, md->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s VmVyc2lvbjogMQ0KWGZyQ291bnQ6IDINClhmclNlbnRVVENUaW1lOiA2MzU2MTQ3OTU5NzgzOTAwMDANCklzR2VvWGZyOiB0cnVlDQo=\r\n",
    211                                     ++md->trId, ic->acc->user));
    212219        } else if (strcmp(cmd[0], "CVR") == 0) {
    213220                /* We don't give a damn about the information we just received */
    214                 return msn_ns_write(ic, md->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user);
    215221        } else if (strcmp(cmd[0], "XFR") == 0) {
    216222                char *server;
     
    280286                        md->msglen = atoi(cmd[2]);
    281287                }
     288        } else if (strcmp(cmd[0], "RML") == 0) {
     289                /* Move along, nothing to see here */
    282290        } else if (strcmp(cmd[0], "CHL") == 0) {
    283291                char *resp;
     
    475483}
    476484
     485/* returns newly allocated string */
     486static char *msn_ns_parse_header_address(struct msn_data *md, char *headers, char *header_name)
     487{
     488        char *semicolon = NULL;
     489        char *header = NULL;
     490        char *address = NULL;
     491
     492        if (!(header = get_rfc822_header(headers, header_name, 0))) {
     493                return NULL;
     494        }
     495
     496        /* either the semicolon or the end of the string */
     497        semicolon = strchr(header, ';') ? : (header + strlen(header));
     498
     499        address = g_strndup(header + 2, semicolon - header - 2);
     500
     501        g_free(header);
     502        return address;
     503}
     504
    477505static void msn_ns_structured_message(struct msn_data *md, char *msg, int msglen, char **cmd)
    478506{
    479507        char **parts = NULL;
    480         char *semicolon = NULL;
    481508        char *action = NULL;
    482         char *from = NULL;
    483509        char *who = NULL;
     510        gboolean selfmessage = FALSE;
    484511
    485512        parts = g_strsplit(msg, "\r\n\r\n", 4);
    486513
    487         if (!(from = get_rfc822_header(parts[0], "From", 0))) {
     514        if (!(who = msn_ns_parse_header_address(md, parts[0], "From"))) {
    488515                goto cleanup;
    489516        }
    490517
    491         /* either the semicolon or the end of the string */
    492         semicolon = strchr(from, ';') ? : (from + strlen(from));
    493 
    494         who = g_strndup(from + 2, semicolon - from - 2);
     518        if (strcmp(who, md->ic->acc->user) == 0) {
     519                selfmessage = TRUE;
     520                g_free(who);
     521                if (!(who = msn_ns_parse_header_address(md, parts[0], "To"))) {
     522                        goto cleanup;
     523                }
     524        }
    495525
    496526        if ((strcmp(cmd[0], "SDG") == 0) && (action = get_rfc822_header(parts[2], "Message-Type", 0))) {
    497                 msn_ns_sdg(md, who, parts, action);
     527                msn_ns_sdg(md, who, parts, action, selfmessage);
    498528
    499529        } else if ((strcmp(cmd[0], "NFY") == 0) && (action = get_rfc822_header(parts[2], "Uri", 0))) {
     
    505535        g_strfreev(parts);
    506536        g_free(action);
    507         g_free(from);
    508537        g_free(who);
    509538}
    510539
    511 static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action)
     540static void msn_ns_sdg(struct msn_data *md, char *who, char **parts, char *action, gboolean selfmessage)
    512541{
    513542        struct im_connection *ic = md->ic;
    514543
    515         if (strcmp(action, "Control/Typing") == 0) {
     544        if (strcmp(action, "Control/Typing") == 0 && !selfmessage) {
    516545                imcb_buddy_typing(ic, who, OPT_TYPING);
    517546        } else if (strcmp(action, "Text") == 0) {
    518                 imcb_buddy_msg(ic, who, parts[3], 0, 0);
     547                imcb_buddy_msg(ic, who, parts[3], selfmessage ? OPT_SELFMESSAGE : 0, 0);
    519548        }
    520549}
     
    595624        } else {
    596625                imcb_error(ic, "Error during Passport authentication: %s", error);
    597                 imc_logout(ic, TRUE);
     626
     627                /* don't reconnect with auth errors */
     628                if (error && g_str_has_prefix(error, "wsse:FailedAuthentication")) {
     629                        imc_logout(ic, FALSE);
     630                } else {
     631                        imc_logout(ic, TRUE);
     632                }
    598633        }
    599634}
  • protocols/msn/soap.c

    r63cad66 r3fbce97  
    270270        struct im_connection *ic = soap_req->ic;
    271271        struct msn_data *md = ic->proto_data;
    272         char pass[MAX_PASSPORT_PWLEN + 1];
    273272
    274273        if (sd->redirect) {
     
    286285        }
    287286
    288         strncpy(pass, ic->acc->pass, MAX_PASSPORT_PWLEN);
    289         pass[MAX_PASSPORT_PWLEN] = '\0';
    290287        soap_req->payload = g_markup_printf_escaped(SOAP_PASSPORT_SSO_PAYLOAD,
    291                                                     ic->acc->user, pass, md->pp_policy);
     288                                                    ic->acc->user, ic->acc->pass, md->pp_policy);
    292289
    293290        return MSN_SOAP_OK;
     
    327324        struct xt_node *code = xt_find_node(node->children, "faultcode");
    328325        struct xt_node *string = xt_find_node(node->children, "faultstring");
     326        struct xt_node *reqstatus = xt_find_path(node, "psf:pp/psf:reqstatus");
    329327        struct xt_node *url;
    330328
     
    335333                   url->text_len > 0) {
    336334                sd->redirect = g_strdup(url->text);
     335        } else if (reqstatus && strcmp(reqstatus->text, "0x800488fe") == 0) {
     336                char *msg = "Location blocked. Log in to live.com, go to recent activity and click 'this was me'";
     337                sd->error = g_strdup_printf("%s (%s)", code->text, msg);
    337338        } else {
    338339                sd->error = g_strdup_printf("%s (%s)", code->text, string && string->text_len ?
     
    346347        { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token },
    347348        { "S:Fault", "S:Envelope", msn_soap_passport_failure },
     349        { "S:Fault", "wst:RequestSecurityTokenResponse", msn_soap_passport_failure },
    348350        { NULL, NULL, NULL }
    349351};
     
    774776                imcb_log(soap_req->ic, "Warning: %d contacts were in both your "
    775777                         "block and your allow list. Assuming they're all "
    776                          "allowed. Use the official WLM client once to fix "
    777                          "this.", wtf);
     778                         "allowed.", wtf);
    778779        }
    779780
  • protocols/msn/soap.h

    r63cad66 r3fbce97  
    6161#define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf"
    6262#define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp900/RST.srf"
    63 #define MAX_PASSPORT_PWLEN 16
    6463
    6564#define SOAP_PASSPORT_SSO_PAYLOAD \
  • protocols/nogaim.c

    r63cad66 r3fbce97  
    9090
    9191GList *protocols = NULL;
     92GList *disabled_protocols = NULL;
    9293
    9394void register_protocol(struct prpl *p)
     
    103104
    104105        if (refused) {
    105                 log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name);
     106                disabled_protocols = g_list_append(disabled_protocols, p);
    106107        } else {
    107108                protocols = g_list_append(protocols, p);
     
    109110}
    110111
     112static int proto_name_cmp(const void *proto_, const void *name)
     113{
     114        const struct prpl *proto = proto_;
     115        return g_strcasecmp(proto->name, name);
     116}
     117
    111118struct prpl *find_protocol(const char *name)
    112119{
    113         GList *gl;
    114 
    115         for (gl = protocols; gl; gl = gl->next) {
    116                 struct prpl *proto = gl->data;
    117 
    118                 if (g_strcasecmp(proto->name, name) == 0) {
    119                         return proto;
    120                 }
    121         }
    122 
    123         return NULL;
     120        GList *gl = g_list_find_custom(protocols, name, proto_name_cmp);
     121        return gl ? gl->data: NULL;
     122}
     123
     124gboolean is_protocol_disabled(const char *name)
     125{
     126        return g_list_find_custom(disabled_protocols, name, proto_name_cmp) != NULL;
    124127}
    125128
     
    209212        account_t *a;
    210213
     214        if (!ic->bee->ui->log) {
     215                return;
     216        }
     217
    211218        va_start(params, format);
    212219        text = g_strdup_vprintf(format, params);
     
    227234        /* If we found one, include the screenname in the message. */
    228235        if (a) {
    229                 /* FIXME(wilmer): ui_log callback or so */
    230                 irc_rootmsg(ic->bee->ui_data, "%s - %s", ic->acc->tag, text);
     236                ic->bee->ui->log(ic->bee, ic->acc->tag, text);
    231237        } else {
    232                 irc_rootmsg(ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text);
     238                ic->bee->ui->log(ic->bee, ic->acc->prpl->name, text);
    233239        }
    234240
     
    662668                GList *m = ic->acc->prpl->away_states(ic);
    663669                msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL;
    664                 away = imc_away_state_find(m, away, &msg) ? : m->data;
     670                away = imc_away_state_find(m, away, &msg) ? :
     671                       (imc_away_state_find(m, "away", &msg) ? : m->data);
    665672        } else if (ic->acc->flags & ACC_FLAG_STATUS_MESSAGE) {
    666673                away = NULL;
     
    781788}
    782789
     790/* Deprecated: using this function resulted in merging several handles accidentally
     791 * Also the irc layer handles this decently nowadays */
    783792void imcb_clean_handle(struct im_connection *ic, char *handle)
    784793{
    785         /* Accepts a handle and does whatever is necessary to make it
    786            BitlBee-friendly. Currently this means removing everything
    787            outside 33-127 (ASCII printable excl spaces), @ (only one
    788            is allowed) and ! and : */
    789         char out[strlen(handle) + 1];
    790         int s, d;
    791 
    792         s = d = 0;
    793         while (handle[s]) {
    794                 if (handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' &&
    795                     (handle[s] & 0x80) == 0) {
    796                         if (handle[s] == '@') {
    797                                 /* See if we got an @ already? */
    798                                 out[d] = 0;
    799                                 if (strchr(out, '@')) {
    800                                         continue;
    801                                 }
    802                         }
    803 
    804                         out[d++] = handle[s];
    805                 }
    806                 s++;
    807         }
    808         out[d] = handle[s];
    809 
    810         strcpy(handle, out);
    811 }
     794}
  • protocols/nogaim.h

    r63cad66 r3fbce97  
    7676#define OPT_PONGED      0x00020000 /* Received a keep-alive during last interval */
    7777#define OPT_LOCAL_CONTACTS_SENT 0x00040000 /* Protocol already requested local contact list, so don't send it after finishing login. */
     78#define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */
    7879
    7980/* ok. now the fun begins. first we create a connection structure */
     
    280281G_MODULE_EXPORT GSList *get_connections();
    281282G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
     283G_MODULE_EXPORT gboolean is_protocol_disabled(const char *name);
    282284/* When registering a new protocol, you should allocate space for a new prpl
    283285 * struct, initialize it (set the function pointers to point to your
     
    326328G_MODULE_EXPORT void imcb_add_buddy(struct im_connection *ic, const char *handle, const char *group);
    327329G_MODULE_EXPORT void imcb_remove_buddy(struct im_connection *ic, const char *handle, char *group);
    328 G_MODULE_EXPORT struct buddy *imcb_find_buddy(struct im_connection *ic, char *handle);
    329330G_MODULE_EXPORT void imcb_rename_buddy(struct im_connection *ic, const char *handle, const char *realname);
    330331G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick);
     
    332333G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic);
    333334
    334 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags);
     335G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags);
    335336G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle);
    336 G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);
     337
     338G_GNUC_DEPRECATED G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle);
    337339
    338340/* Actions, or whatever. */
  • protocols/oscar/aim.h

    r63cad66 r3fbce97  
    2121
    2222#include "bitlbee.h"
     23
     24#ifdef WITH_PURPLE
     25/* For compatibility with builds that include both purple and this oscar module */
     26#include "aim_prefixes.h"
     27#endif
    2328
    2429/* XXX adjust these based on autoconf-detected platform */
     
    871876 * SNAC Family: Internal Messages
    872877 *
    873  * This isn't truely a SNAC family either, but using
     878 * This isn't truly a SNAC family either, but using
    874879 * these, we can integrated non-SNAC services into
    875880 * the SNAC-centered libfaim callback structure.
  • protocols/oscar/auth.c

    r63cad66 r3fbce97  
    4141 * meaning you generally never call this.
    4242 *
    43  * But there are times when something might want it seperate. Specifically,
     43 * But there are times when something might want it separate. Specifically,
    4444 * libfaim sends this internally when doing SNAC login.
    4545 *
  • protocols/oscar/conn.c

    r63cad66 r3fbce97  
    1515 * In OSCAR, every connection has a set of SNAC groups associated
    1616 * with it.  These are the groups that you can send over this connection
    17  * without being guarenteed a "Not supported" SNAC error.
     17 * without being guaranteed a "Not supported" SNAC error.
    1818 *
    1919 * The grand theory of things says that these associations transcend
     
    3636 *
    3737 * Here comes the good bit.  Without even letting anyone know, particularly
    38  * the module that decided to send this SNAC, and definitly not that twit
     38 * the module that decided to send this SNAC, and definitely not that twit
    3939 * in Greenland, you send out a service request.  In this request, you have
    4040 * marked the need for a connection supporting group 0x000e.  A few seconds
     
    317317
    318318        if (deadconn->fd >= 3) {
    319                 closesocket(deadconn->fd);
     319                proxy_disconnect(deadconn->fd);
    320320        }
    321321        deadconn->fd = -1;
  • protocols/oscar/im.c

    r63cad66 r3fbce97  
    5050 * encoding for your message.  In UNICODE mode, _all_ characters must
    5151 * occupy 16bits, including ones that are not special.  (Remember that
    52  * the first 128 UNICODE symbols are equivelent to ASCII7, however they
     52 * the first 128 UNICODE symbols are equivalent to ASCII7, however they
    5353 * must be prefixed with a zero high order byte.)
    5454 *
     
    6464 * in all of libfaim, it is written with performance in mind.  As such,
    6565 * it is not as clear as it could be in respect to how this message is
    66  * supposed to be layed out. Most obviously, tlvlists should be used
     66 * supposed to be laid out. Most obviously, tlvlists should be used
    6767 * instead of writing out the bytes manually.
    6868 *
     
    476476 * examples of how to do this.
    477477 *
    478  * I would definitly recommend avoiding this feature unless you really
     478 * I would definitely recommend avoiding this feature unless you really
    479479 * know what you are doing, and/or you have something neat to do with it.
    480480 *
     
    638638                        }
    639639#if 0
    640                         /* XXX this isn't really necesary... */
     640                        /* XXX this isn't really necessary... */
    641641                        if (((args.flag1 != 0x0000) &&
    642642                             (args.flag1 != 0x0002) &&
     
    11611161         *
    11621162         * Channel 0x0001 is the message channel.  There are
    1163          * other channels for things called "rendevous"
     1163         * other channels for things called "rendezvous"
    11641164         * which represent chat and some of the other new
    11651165         * features of AIM2/3/3.5.
    11661166         *
    1167          * Channel 0x0002 is the Rendevous channel, which
     1167         * Channel 0x0002 is the Rendezvous channel, which
    11681168         * is where Chat Invitiations and various client-client
    11691169         * connection negotiations come from.
     
    11811181         * with the TLVs read below, they are two different pieces.  The
    11821182         * userinfo block contains the number of TLVs that contain user
    1183          * information, the rest are not even though there is no seperation.
     1183         * information, the rest are not even though there is no separation.
    11841184         * aim_extractuserinfo() returns the number of bytes used by the
    11851185         * userinfo tlvs, so you can start reading the rest of them right
     
    12531253/*
    12541254 *
    1255  * I definitly recommend sending this.  If you don't, you'll be stuck
     1255 * I definitely recommend sending this.  If you don't, you'll be stuck
    12561256 * with the rather unreasonable defaults.  You don't want those.  Send this.
    12571257 *
  • protocols/oscar/misc.c

    r63cad66 r3fbce97  
    33 * aim_misc.c
    44 *
    5  * TODO: Seperate a lot of this into an aim_bos.c.
     5 * TODO: Separate a lot of this into an aim_bos.c.
    66 *
    77 * Other things...
  • protocols/oscar/msgcookie.c

    r63cad66 r3fbce97  
    142142 * @cookiep: the address of a pointer to the cookie struct to remove
    143143 *
    144  * this function removes the cookie *cookie from teh list of cookies
     144 * this function removes the cookie *cookie from the list of cookies
    145145 * in sess, and then frees all memory associated with it. including
    146146 * its data! if you want to use the private data after calling this,
  • protocols/oscar/oscar.c

    r63cad66 r3fbce97  
    12661266        } break;
    12671267
    1268         case 2: {         /* rendevous */
     1268        case 2: {         /* rendezvous */
    12691269                struct aim_incomingim_ch2_args *args;
    12701270                args = va_arg(ap, struct aim_incomingim_ch2_args *);
  • protocols/oscar/rxhandlers.c

    r63cad66 r3fbce97  
    381381        /*
    382382         * This doesn't have to be called here.  It could easily be done
    383          * by a seperate thread or something. It's an administrative operation,
     383         * by a separate thread or something. It's an administrative operation,
    384384         * and can take a while. Though the less you call it the less memory
    385385         * you'll have :)
  • protocols/oscar/rxqueue.c

    r63cad66 r3fbce97  
    361361/*
    362362 * Grab a single command sequence off the socket, and enqueue
    363  * it in the incoming event queue in a seperate struct.
     363 * it in the incoming event queue in a separate struct.
    364364 */
    365365int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
     
    479479
    480480/*
    481  * Purge recieve queue of all handled commands (->handled==1).  Also
     481 * Purge receive queue of all handled commands (->handled==1).  Also
    482482 * allows for selective freeing using ->nofree so that the client can
    483483 * keep the data for various purposes.
  • protocols/oscar/service.c

    r63cad66 r3fbce97  
    157157
    158158/*
    159  * OSCAR defines several 'rate classes'.  Each class has seperate
     159 * OSCAR defines several 'rate classes'.  Each class has separate
    160160 * rate limiting properties (limit level, alert level, disconnect
    161161 * level, etc), and a set of SNAC family/type pairs associated with
     
    709709 * of memory.  (I won't put it past them to start requesting data in
    710710 * less static regions -- regions that are initialized at run time, but still
    711  * before the client recieves this request.)
    712  *
    713  * When the client recieves the request, it adds it to the current ds
     711 * before the client receives this request.)
     712 *
     713 * When the client receives the request, it adds it to the current ds
    714714 * (0x00400000) and dereferences it, copying the data into a buffer which
    715715 * it then runs directly through the MD5 hasher.  The 16 byte output of
     
    723723 *     download a FREE, fully featured, and authorized client, here
    724724 *     http://www.aol.com/aim/download2.html"
    725  * The connection is then closed, recieving disconnect code 1, URL
     725 * The connection is then closed, receiving disconnect code 1, URL
    726726 * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
    727727 *
    728728 * Note, however, that numerous inconsistencies can cause the above error,
    729  * not just sending back a bad hash.  Do not immediatly suspect this code
     729 * not just sending back a bad hash.  Do not immediately suspect this code
    730730 * if you get disconnected.  AOL and the open/free software community have
    731731 * played this game for a couple years now, generating the above message
    732  * on numerous ocassions.
     732 * on numerous occasions.
    733733 *
    734734 * Anyway, neener.  We win again.
  • protocols/oscar/tlv.c

    r63cad66 r3fbce97  
    2525 * bstream references, so that at least the ->value portion of each
    2626 * element doesn't need to be malloc/memcpy'd.  This could prove to be
    27  * just as effecient as the in-place TLV parsing used in a couple places
     27 * just as efficient as the in-place TLV parsing used in a couple places
    2828 * in libfaim.
    2929 *
     
    135135/**
    136136 * aim_addtlvtochain_str - Add a string to a TLV chain
    137  * @list: Desination chain (%NULL pointer if empty)
     137 * @list: Designation chain (%NULL pointer if empty)
    138138 * @type: TLV type
    139139 * @str: String to add
  • protocols/oscar/txqueue.c

    r63cad66 r3fbce97  
    6767 * The overall purpose here is to enqueue the passed in command struct
    6868 * into the outgoing (tx) queue.  Basically...
    69  *   1) Make a scope-irrelevent copy of the struct
     69 *   1) Make a scope-irrelevant copy of the struct
    7070 *   3) Mark as not-sent-yet
    7171 *   4) Enqueue the struct into the list
  • protocols/purple/ft-direct.c

    r63cad66 r3fbce97  
    193193PurpleXferUiOps bee_xfer_uiops =
    194194{
    195         prplcb_xfer_new,
    196         prplcb_xfer_dbg,
    197         prplcb_xfer_dbg,
    198         prplcb_xfer_progress,
    199         prplcb_xfer_dbg,
    200         prplcb_xfer_dbg,
    201         prplcb_xfer_write,
    202         prplcb_xfer_read,
    203         prplcb_xfer_dbg,
     195        prplcb_xfer_new,           /* new_xfer */
     196        prplcb_xfer_dbg,           /* destroy */
     197        prplcb_xfer_dbg,           /* add_xfer */
     198        prplcb_xfer_progress,      /* update_progress */
     199        prplcb_xfer_dbg,           /* cancel_local */
     200        prplcb_xfer_dbg,           /* cancel_remote */
     201        prplcb_xfer_write,         /* ui_write */
     202        prplcb_xfer_read,          /* ui_read */
     203        prplcb_xfer_dbg,           /* data_not_sent */
    204204};
    205205
  • protocols/purple/ft.c

    r63cad66 r3fbce97  
    232232}
    233233
    234 static void prplcb_xfer_dbg(PurpleXfer *xfer)
    235 {
    236         fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer);
    237 }
    238 
    239234
    240235/* Sending files (UI->IM): */
     
    337332PurpleXferUiOps bee_xfer_uiops =
    338333{
    339         prplcb_xfer_new,
    340         prplcb_xfer_destroy,
    341         NULL, /* prplcb_xfer_add, */
    342         prplcb_xfer_progress,
    343         prplcb_xfer_dbg,
    344         prplcb_xfer_cancel_remote,
    345         NULL,
    346         NULL,
    347         prplcb_xfer_dbg,
     334        prplcb_xfer_new,           /* new_xfer */
     335        prplcb_xfer_destroy,       /* destroy */
     336        NULL,                      /* add_xfer */
     337        prplcb_xfer_progress,      /* update_progress */
     338        NULL,                      /* cancel_local */
     339        prplcb_xfer_cancel_remote, /* cancel_remote */
     340        NULL,                      /* ui_write */
     341        NULL,                      /* ui_read */
     342        NULL,                      /* data_not_sent */
    348343};
  • protocols/purple/purple.c

    r63cad66 r3fbce97  
    113113           servers anyway! */
    114114        if (!dir_fixed) {
     115                PurpleCertificatePool *pool;
    115116                irc_t *irc = acc->bee->ui_data;
    116117                char *dir;
     
    122123                purple_blist_load();
    123124                purple_prefs_load();
     125
     126                if (proxytype == PROXY_SOCKS4A) {
     127                        /* do this here after loading prefs. yes, i know, it sucks */
     128                        purple_prefs_set_bool("/purple/proxy/socks4_remotedns", TRUE);
     129                }
     130
     131                /* re-create the certificate cache directory */
     132                pool = purple_certificate_find_pool("x509", "tls_peers");
     133                dir = purple_certificate_pool_mkpath(pool, NULL);
     134                purple_build_dir(dir, 0700);
     135                g_free(dir);
     136
    124137                dir_fixed = TRUE;
    125138        }
     
    352365        if (!pd) {
    353366                return;
     367        }
     368
     369        while (ic->groupchats) {
     370                imcb_chat_free(ic->groupchats->data);
    354371        }
    355372
     
    639656        /* Call the fucker. */
    640657        callback = (void *) mi->callback;
    641         callback(&pb->node, menu->data);
     658        callback(&pb->node, mi->data);
    642659
    643660        return NULL;
     
    707724                        g_hash_table_replace(chat_hash, "passwd", g_strdup(password));
    708725                }
    709         }
     726
     727                g_free(pce);
     728        }
     729
     730        g_list_free(info);
    710731
    711732        serv_join_chat(purple_account_get_connection(pd->account), chat_hash);
    712733
    713         return NULL;
     734        g_hash_table_destroy(chat_hash);
     735
     736        return imcb_chat_new(ic, room);
    714737}
    715738
     
    733756static PurpleCoreUiOps bee_core_uiops =
    734757{
    735         NULL,
    736         NULL,
    737         purple_ui_init,
    738         NULL,
    739         prplcb_ui_info,
     758        NULL,                      /* ui_prefs_init */
     759        NULL,                      /* debug_ui_init */
     760        purple_ui_init,            /* ui_init */
     761        NULL,                      /* quit */
     762        prplcb_ui_info,            /* get_ui_info */
    740763};
    741764
     
    764787        purple_gg_buddylist_import(gc);
    765788
    766         if (gc->flags & PURPLE_CONNECTION_HTML) {
    767                 ic->flags |= OPT_DOES_HTML;
    768         }
     789        ic->flags |= OPT_DOES_HTML;
    769790}
    770791
     
    800821static PurpleConnectionUiOps bee_conn_uiops =
    801822{
    802         prplcb_conn_progress,
    803         prplcb_conn_connected,
    804         prplcb_conn_disconnected,
    805         prplcb_conn_notice,
    806         NULL,
    807         NULL,
    808         NULL,
    809         prplcb_conn_report_disconnect_reason,
     823        prplcb_conn_progress,                    /* connect_progress */
     824        prplcb_conn_connected,                   /* connected */
     825        prplcb_conn_disconnected,                /* disconnected */
     826        prplcb_conn_notice,                      /* notice */
     827        NULL,                                    /* report_disconnect */
     828        NULL,                                    /* network_connected */
     829        NULL,                                    /* network_disconnected */
     830        prplcb_conn_report_disconnect_reason,    /* report_disconnect_reason */
    810831};
    811832
     
    882903static PurpleBlistUiOps bee_blist_uiops =
    883904{
    884         NULL,
    885         prplcb_blist_new,
    886         NULL,
    887         prplcb_blist_update,
    888         prplcb_blist_remove,
     905        NULL,                      /* new_list */
     906        prplcb_blist_new,          /* new_node */
     907        NULL,                      /* show */
     908        prplcb_blist_update,       /* update */
     909        prplcb_blist_remove,       /* remove */
    889910};
    890911
     
    895916                struct groupchat *gc;
    896917
    897                 gc = imcb_chat_new(ic, conv->name);
    898                 if (conv->title != NULL) {
    899                         imcb_chat_name_hint(gc, conv->title);
     918                gc = bee_chat_by_title(ic->bee, ic, conv->name);
     919
     920                if (!gc) {
     921                        gc = imcb_chat_new(ic, conv->name);
     922                        if (conv->title != NULL) {
     923                                imcb_chat_name_hint(gc, conv->title);
     924                        }
     925                }
     926
     927                /* don't set the topic if it's just the name */
     928                if (conv->title != NULL && strcmp(conv->name, conv->title) != 0) {
    900929                        imcb_chat_topic(gc, NULL, conv->title, 0);
    901930                }
     
    940969}
    941970
    942 void prplcb_conv_chat_msg(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags,
    943                           time_t mtime)
    944 {
     971/* Generic handler for IM or chat messages, covers write_chat, write_im and write_conv */
     972static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message, guint32 bee_flags, time_t mtime)
     973{
     974        struct im_connection *ic = purple_ic_by_pa(conv->account);
    945975        struct groupchat *gc = conv->ui_data;
    946976        PurpleBuddy *buddy;
    947 
    948         /* ..._SEND means it's an outgoing message, no need to echo those. */
    949         if (flags & PURPLE_MESSAGE_SEND) {
    950                 return;
    951         }
    952977
    953978        buddy = purple_find_buddy(conv->account, who);
     
    956981        }
    957982
    958         imcb_chat_msg(gc, who, (char *) message, 0, mtime);
    959 }
    960 
    961 static void prplcb_conv_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags,
    962                            time_t mtime)
    963 {
    964         struct im_connection *ic = purple_ic_by_pa(conv->account);
    965         PurpleBuddy *buddy;
    966 
    967         /* ..._SEND means it's an outgoing message, no need to echo those. */
     983        if (conv->type == PURPLE_CONV_TYPE_IM) {
     984                imcb_buddy_msg(ic, (char *) who, (char *) message, bee_flags, mtime);
     985        } else if (gc) {
     986                imcb_chat_msg(gc, who, (char *) message, bee_flags, mtime);
     987        }
     988}
     989
     990/* Handles write_im and write_chat. Removes echoes of locally sent messages */
     991static void prplcb_conv_msg(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime)
     992{
     993        if (!(flags & PURPLE_MESSAGE_SEND)) {
     994                handle_conv_msg(conv, who, message, 0, mtime);
     995        }
     996}
     997
     998/* Handles write_conv. Only passes self messages from other locations through.
     999 * That is, only writes of PURPLE_MESSAGE_SEND.
     1000 * There are more events which might be handled in the future, but some are tricky.
     1001 * (images look like <img id="123">, what do i do with that?) */
     1002static void prplcb_conv_write(PurpleConversation *conv, const char *who, const char *alias, const char *message,
     1003                              PurpleMessageFlags flags, time_t mtime)
     1004{
    9681005        if (flags & PURPLE_MESSAGE_SEND) {
    969                 return;
    970         }
    971 
    972         buddy = purple_find_buddy(conv->account, who);
    973         if (buddy != NULL) {
    974                 who = purple_buddy_get_name(buddy);
    975         }
    976 
    977         imcb_buddy_msg(ic, (char *) who, (char *) message, 0, mtime);
     1006                handle_conv_msg(conv, who, message, OPT_SELFMESSAGE, mtime);
     1007        }
    9781008}
    9791009
     
    10081038        prplcb_conv_new,           /* create_conversation  */
    10091039        prplcb_conv_free,          /* destroy_conversation */
    1010         prplcb_conv_chat_msg,      /* write_chat           */
    1011         prplcb_conv_im,            /* write_im             */
    1012         NULL,                      /* write_conv           */
     1040        prplcb_conv_msg,           /* write_chat           */
     1041        prplcb_conv_msg,           /* write_im             */
     1042        prplcb_conv_write,         /* write_conv           */
    10131043        prplcb_conv_add_users,     /* chat_add_users       */
    10141044        NULL,                      /* chat_rename_user     */
     
    11751205static PurpleRequestUiOps bee_request_uiops =
    11761206{
    1177         prplcb_request_input,
    1178         NULL,
    1179         prplcb_request_action,
    1180         NULL,
    1181         NULL,
    1182         prplcb_close_request,
    1183         NULL,
     1207        prplcb_request_input,      /* request_input */
     1208        NULL,                      /* request_choice */
     1209        prplcb_request_action,     /* request_action */
     1210        NULL,                      /* request_fields */
     1211        NULL,                      /* request_file */
     1212        prplcb_close_request,      /* close_request */
     1213        NULL,                      /* request_folder */
    11841214};
    11851215
     
    12221252static PurplePrivacyUiOps bee_privacy_uiops =
    12231253{
    1224         prplcb_privacy_permit_added,
    1225         prplcb_privacy_permit_removed,
    1226         prplcb_privacy_deny_added,
    1227         prplcb_privacy_deny_removed,
     1254        prplcb_privacy_permit_added,       /* permit_added */
     1255        prplcb_privacy_permit_removed,     /* permit_removed */
     1256        prplcb_privacy_deny_added,         /* deny_added */
     1257        prplcb_privacy_deny_removed,       /* deny_removed */
    12281258};
    12291259
     
    12351265static PurpleDebugUiOps bee_debug_uiops =
    12361266{
    1237         prplcb_debug_print,
     1267        prplcb_debug_print,        /* print */
    12381268};
    12391269
     
    12561286static PurpleEventLoopUiOps glib_eventloops =
    12571287{
    1258         prplcb_ev_timeout_add,
    1259         prplcb_ev_remove,
    1260         prplcb_ev_input_add,
    1261         prplcb_ev_remove,
     1288        prplcb_ev_timeout_add,     /* timeout_add */
     1289        prplcb_ev_remove,          /* timeout_remove */
     1290        prplcb_ev_input_add,       /* input_add */
     1291        prplcb_ev_remove,          /* input_remove */
    12621292};
     1293
     1294/* Absolutely no connection context at all. Thanks purple! brb crying */
     1295static void *prplcb_notify_message(PurpleNotifyMsgType type, const char *title,
     1296                                   const char *primary, const char *secondary)
     1297{
     1298        char *text = g_strdup_printf("%s%s - %s%s%s",
     1299                (type == PURPLE_NOTIFY_MSG_ERROR) ? "Error: " : "",
     1300                title,
     1301                primary ?: "",
     1302                (primary && secondary) ? " - " : "",
     1303                secondary ?: ""
     1304        );
     1305
     1306        if (local_bee->ui->log) {
     1307                local_bee->ui->log(local_bee, "purple", text);
     1308        }
     1309
     1310        g_free(text);
     1311
     1312        return NULL;
     1313}
    12631314
    12641315static void *prplcb_notify_email(PurpleConnection *gc, const char *subject, const char *from,
     
    13221373static PurpleNotifyUiOps bee_notify_uiops =
    13231374{
    1324         NULL,
    1325         prplcb_notify_email,
    1326         NULL,
    1327         NULL,
    1328         NULL,
    1329         NULL,
    1330         prplcb_notify_userinfo,
     1375        prplcb_notify_message,     /* notify_message */
     1376        prplcb_notify_email,       /* notify_email */
     1377        NULL,                      /* notify_emails */
     1378        NULL,                      /* notify_formatted */
     1379        NULL,                      /* notify_searchresults */
     1380        NULL,                      /* notify_searchresults_new_rows */
     1381        prplcb_notify_userinfo,    /* notify_userinfo */
    13311382};
    13321383
     
    13551406static PurpleAccountUiOps bee_account_uiops =
    13561407{
    1357         NULL,
    1358         NULL,
    1359         NULL,
    1360         prplcb_account_request_authorize,
    1361         NULL,
     1408        NULL,                              /* notify_added */
     1409        NULL,                              /* status_changed */
     1410        NULL,                              /* request_add */
     1411        prplcb_account_request_authorize,  /* request_authorize */
     1412        NULL,                              /* close_account_request */
    13621413};
    13631414
     
    13871438        char *dir;
    13881439
    1389         if (B_EV_IO_READ != PURPLE_INPUT_READ ||
    1390             B_EV_IO_WRITE != PURPLE_INPUT_WRITE) {
    1391                 /* FIXME FIXME FIXME FIXME FIXME :-) */
    1392                 exit(1);
    1393         }
     1440        g_assert((int) B_EV_IO_READ == (int) PURPLE_INPUT_READ);
     1441        g_assert((int) B_EV_IO_WRITE == (int) PURPLE_INPUT_WRITE);
    13941442
    13951443        dir = g_strdup_printf("%s/purple", global.conf->configdir);
     
    14091457                PurpleProxyInfo *pi = purple_global_proxy_get_info();
    14101458                switch (proxytype) {
     1459                case PROXY_SOCKS4A:
    14111460                case PROXY_SOCKS4:
    14121461                        purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS4);
  • protocols/skype/README

    r63cad66 r3fbce97  
    203203
    204204  * `account skype set skypeconsole_receive true` will make the
    205     `skypeconsole` account dump all the recieved raw traffic for you
     205    `skypeconsole` account dump all the received raw traffic for you
    206206
    207207- If you want to automatically join bookmarked groupchats right after
  • protocols/skype/skype.c

    r63cad66 r3fbce97  
    2121
    2222#define _XOPEN_SOURCE
    23 #define _BSD_SOURCE
    2423#include <poll.h>
    2524#include <stdio.h>
     
    188187
    189188        va_start(args, fmt);
    190         vsnprintf(str, IRC_LINE_SIZE, fmt, args);
     189        g_vsnprintf(str, IRC_LINE_SIZE, fmt, args);
    191190        va_end(args);
    192191
     
    322321        }
    323322        return NULL;
     323}
     324
     325static struct groupchat *skype_chat_get_or_create(struct im_connection *ic, char *id)
     326{
     327        struct skype_data *sd = ic->proto_data;
     328        struct groupchat *gc = bee_chat_by_title(ic->bee, ic, id);
     329
     330        if (!gc) {
     331                gc = imcb_chat_new(ic, id);
     332                imcb_chat_name_hint(gc, id);
     333                imcb_chat_add_buddy(gc, sd->username);
     334
     335                skype_printf(ic, "GET CHAT %s ADDER\n", id);
     336                skype_printf(ic, "GET CHAT %s TOPIC\n", id);
     337                skype_printf(ic, "GET CHAT %s ACTIVEMEMBERS\n", id);
     338        }
     339
     340        return gc;
    324341}
    325342
     
    688705                info += 9;
    689706                if (sd->handle && sd->body && sd->type) {
    690                         struct groupchat *gc = bee_chat_by_title(ic->bee, ic, info);
     707                        struct groupchat *gc = skype_chat_get_or_create(ic, info);
    691708                        int i;
    692709                        for (i = 0; i < g_list_length(sd->body); i++) {
     
    10261043        }
    10271044        if (!strcmp(info, "STATUS MULTI_SUBSCRIBED")) {
    1028                 gc = bee_chat_by_title(ic->bee, ic, id);
    1029                 if (!gc) {
    1030                         gc = imcb_chat_new(ic, id);
    1031                         imcb_chat_name_hint(gc, id);
    1032                 }
    1033                 skype_printf(ic, "GET CHAT %s ADDER\n", id);
    1034                 skype_printf(ic, "GET CHAT %s TOPIC\n", id);
     1045                skype_chat_get_or_create(ic, id);
    10351046        } else if (!strcmp(info, "STATUS DIALOG") && sd->groupchat_with) {
    1036                 gc = imcb_chat_new(ic, id);
    1037                 imcb_chat_name_hint(gc, id);
     1047                gc = skype_chat_get_or_create(ic, id);
    10381048                /* According to the docs this
    10391049                 * is necessary. However it
     
    10461056                           sd->groupchat_with);
    10471057                imcb_chat_add_buddy(gc, buf);
    1048                 imcb_chat_add_buddy(gc, sd->username);
    10491058                g_free(sd->groupchat_with);
    10501059                sd->groupchat_with = NULL;
    1051                 skype_printf(ic, "GET CHAT %s ADDER\n", id);
    1052                 skype_printf(ic, "GET CHAT %s TOPIC\n", id);
    10531060        } else if (!strcmp(info, "STATUS UNSUBSCRIBED")) {
    10541061                gc = bee_chat_by_title(ic->bee, ic, id);
     
    12571264                }
    12581265                g_strfreev(lines);
    1259         } else if (st == 0 || (st < 0 && !sockerr_again())) {
     1266        } else if (st == 0 || (st < 0 && !ssl_sockerr_again(sd->ssl))) {
    12601267                ssl_disconnect(sd->ssl);
    12611268                sd->fd = -1;
  • protocols/skype/t/add-yes-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/added-no-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/added-yes-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/away-set-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/call-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :alice
  • protocols/skype/t/call-failed-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :alice
  • protocols/skype/t/called-no-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/called-yes-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/ctcp-help-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/filetransfer-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/group-add-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/group-read-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/groupchat-invite-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    77>> :bob!bob@skype.com JOIN :&bitlbee
    88<< PRIVMSG &bitlbee :chat with bob
    9 >> 353 alice = ##alice/$bob;a7ab206ec780 :@alice bob @root
    10 << INVITE cecil ##alice/$bob;a7ab206ec780
    11 >> cecil@skype.com JOIN :##alice/$bob;a7ab206ec780
     9>> 353 alice = ##alice/$bob;a7ab206ec78 :@alice @root
     10<< INVITE cecil ##alice/$bob;a7ab206ec78
     11>> cecil@skype.com JOIN :##alice/$bob;a7ab206ec78
  • protocols/skype/t/groupchat-invite-skyped.mock

    r63cad66 r3fbce97  
    2626>> GET CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
    2727<< CHAT #alice/$bob;a7ab206ec78060f1 TOPIC
     28>> GET CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS
     29<< CHAT #alice/$bob;a7ab206ec78060f1 ACTIVEMEMBERS
    2830<< CHATMESSAGE 206 STATUS SENDING
    2931<< CHAT #alice/$bob;a7ab206ec78060f1 STATUS DIALOG
  • protocols/skype/t/groupchat-invited-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    55<< PRIVMSG &bitlbee :account add skype alice foo
    66<< PRIVMSG &bitlbee :account skype on
    7 >> JOIN :##cecil/$bob;4d8cc9965791
    8 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
     7>> JOIN :##cecil/$bob;4d8cc996579
     8>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
  • protocols/skype/t/groupchat-leave-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    66<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
    77<< PRIVMSG &bitlbee :account skype on
    8 >> JOIN :##cecil/$bob;4d8cc9965791
    9 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    10 << PART ##cecil/$bob;4d8cc9965791
     8>> JOIN :##cecil/$bob;4d8cc996579
     9>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     10<< PART ##cecil/$bob;4d8cc996579
    1111>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 STATUS UNSUBSCRIBED
  • protocols/skype/t/groupchat-leave-skyped.mock

    r63cad66 r3fbce97  
    3636>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    3737<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    38 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    39 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    40 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    41 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    42 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    43 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    44 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    45 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
     38>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
     39<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
    4640>> GET CHATMESSAGE 188 FROM_HANDLE
    4741<< CHATMESSAGE 188 FROM_HANDLE bob
  • protocols/skype/t/groupchat-msg-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    66<< PRIVMSG &bitlbee :account skype set skypeconsole_receive true
    77<< PRIVMSG &bitlbee :account skype on
    8 >> JOIN :##cecil/$bob;4d8cc9965791
    9 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    10 << PRIVMSG ##cecil/$bob;4d8cc9965791 :hello
     8>> JOIN :##cecil/$bob;4d8cc996579
     9>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     10<< PRIVMSG ##cecil/$bob;4d8cc996579 :hello
    1111>> PRIVMSG &bitlbee :alice: CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVITY_TIMESTAMP
  • protocols/skype/t/groupchat-msg-skyped.mock

    r63cad66 r3fbce97  
    3636>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    3737<< CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    38 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    39 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    40 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    41 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    42 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER
    43 << CHAT #cecil/$bob;4d8cc9965791c6b9 ADDER bob
    44 >> GET CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
    45 << CHAT #cecil/$bob;4d8cc9965791c6b9 TOPIC
     38>> GET CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS
     39<< CHAT #cecil/$bob;4d8cc9965791c6b9 ACTIVEMEMBERS bob cecil alice
    4640>> GET CHATMESSAGE 188 FROM_HANDLE
    4741<< CHATMESSAGE 188 FROM_HANDLE bob
  • protocols/skype/t/groupchat-topic-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
     
    55<< PRIVMSG &bitlbee :account add skype alice foo
    66<< PRIVMSG &bitlbee :account skype on
    7 >> JOIN :##cecil/$bob;4d8cc9965791
    8 >> 353 alice = ##cecil/$bob;4d8cc9965791 :@alice bob cecil @root
    9 << TOPIC ##cecil/$bob;4d8cc9965791 :topic
    10 >> TOPIC ##cecil/$bob;4d8cc9965791 :topic
     7>> JOIN :##cecil/$bob;4d8cc996579
     8>> 353 alice = ##cecil/$bob;4d8cc996579 :@alice @root
     9<< TOPIC ##cecil/$bob;4d8cc996579 :topic
     10>> TOPIC ##cecil/$bob;4d8cc996579 :topic
  • protocols/skype/t/info-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/login-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/msg-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/skype/t/set-mood-text-bitlbee.mock

    r63cad66 r3fbce97  
    1 >> NOTICE AUTH
     1>> NOTICE *
    22<< NICK alice
    33<< USER alice alice localhost :Alice
  • protocols/twitter/twitter.c

    r63cad66 r3fbce97  
    678678        ic->flags &= ~OPT_LOGGED_IN;
    679679
    680         // Remove the main_loop function from the function queue.
    681         b_event_remove(td->main_loop_id);
    682 
    683         if (td->timeline_gc) {
    684                 imcb_chat_free(td->timeline_gc);
    685         }
    686 
    687680        if (td) {
     681                // Remove the main_loop function from the function queue.
     682                b_event_remove(td->main_loop_id);
     683
     684                if (td->timeline_gc) {
     685                        imcb_chat_free(td->timeline_gc);
     686                }
     687
    688688                if (td->filter_update_id > 0) {
    689689                        b_event_remove(td->filter_update_id);
  • protocols/twitter/twitter_http.c

    r63cad66 r3fbce97  
    2424/***************************************************************************\
    2525*                                                                           *
    26 *  Some funtions within this file have been copied from other files within  *
     26*  Some functions within this file have been copied from other files within  *
    2727*  BitlBee.                                                                 *
    2828*                                                                           *
     
    5353        char *tmp;
    5454        GString *request = g_string_new("");
    55         void *ret;
     55        void *ret = NULL;
    5656        char *url_arguments;
    5757        url_t *base_url = NULL;
     
    7272                base_url = g_new0(url_t, 1);
    7373                if (!url_set(base_url, url_string)) {
    74                         g_free(base_url);
    75                         return NULL;
     74                        goto error;
    7675                }
    7776        }
     
    132131        }
    133132
     133error:
    134134        g_free(url_arguments);
    135135        g_string_free(request, TRUE);
  • protocols/twitter/twitter_lib.c

    r63cad66 r3fbce97  
    314314        td = ic->proto_data;
    315315
     316        // Parse the data.
     317        if (!(parsed = twitter_parse_response(ic, req))) {
     318                return;
     319        }
     320
    316321        txl = g_new0(struct twitter_xml_list, 1);
    317322        txl->list = td->follow_ids;
    318 
    319         // Parse the data.
    320         if (!(parsed = twitter_parse_response(ic, req))) {
    321                 return;
    322         }
    323323
    324324        twitter_xt_get_friends_id_list(parsed, txl);
     
    390390        }
    391391
     392        // Get the user list from the parsed xml feed.
     393        if (!(parsed = twitter_parse_response(ic, req))) {
     394                return;
     395        }
     396
    392397        txl = g_new0(struct twitter_xml_list, 1);
    393398        txl->list = NULL;
    394399
    395         // Get the user list from the parsed xml feed.
    396         if (!(parsed = twitter_parse_response(ic, req))) {
    397                 return;
    398         }
    399400        twitter_xt_get_users(parsed, txl);
    400401        json_value_free(parsed);
     
    13891390        td = ic->proto_data;
    13901391
    1391         txl = g_new0(struct twitter_xml_list, 1);
    1392         txl->list = NULL;
    1393 
    13941392        // The root <statuses> node should hold the list of statuses <status>
    13951393        if (!(parsed = twitter_parse_response(ic, req))) {
    13961394                goto end;
    13971395        }
     1396
     1397        txl = g_new0(struct twitter_xml_list, 1);
     1398        txl->list = NULL;
     1399
    13981400        twitter_xt_get_status_list(ic, parsed, txl);
    13991401        json_value_free(parsed);
     
    14281430        td = ic->proto_data;
    14291431
    1430         txl = g_new0(struct twitter_xml_list, 1);
    1431         txl->list = NULL;
    1432 
    14331432        // The root <statuses> node should hold the list of statuses <status>
    14341433        if (!(parsed = twitter_parse_response(ic, req))) {
    14351434                goto end;
    14361435        }
     1436
     1437        txl = g_new0(struct twitter_xml_list, 1);
     1438        txl->list = NULL;
     1439
    14371440        twitter_xt_get_status_list(ic, parsed, txl);
    14381441        json_value_free(parsed);
  • protocols/yahoo/libyahoo2.c

    r63cad66 r3fbce97  
    1212 * GNU GPL.
    1313 *
    14  * This code is derivitive of Gaim <http://gaim.sourceforge.net>
     14 * This code is derivative of Gaim <http://gaim.sourceforge.net>
    1515 * copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
    1616 *             1998-1999, Adam Fritzler <afritz@marko.net>
     
    14021402
    14031403        /*
    1404          * Status updates may be spread accross multiple packets and not
     1404         * Status updates may be spread across multiple packets and not
    14051405         * even on buddy boundaries, so keeping some state is important.
    14061406         * So, continue where we left off, and only add a user entry to
  • protocols/yahoo/yahoo.c

    r63cad66 r3fbce97  
    440440{
    441441        struct byahoo_connect_callback_data *d = data;
    442 
    443         if (!byahoo_get_ic_by_id(d->id)) {
     442        struct im_connection *ic;
     443
     444        if (!(ic = byahoo_get_ic_by_id(d->id))) {
     445                g_free(d);
     446                return;
     447        }
     448
     449        if (source == -1) {
     450                d->callback(NULL, 0, d->data);
     451                imcb_error(ic, "Could not connect to server");
     452                imc_logout(ic, TRUE);
    444453                g_free(d);
    445454                return;
  • protocols/yahoo/yahoo2_callbacks.h

    r63cad66 r3fbce97  
    685685 * Name: ext_yahoo_connect_async
    686686 *      Connect to a host:port asynchronously. This function should return
    687  *      immediately returing a tag used to identify the connection handler,
     687 *      immediately returning a tag used to identify the connection handler,
    688688 *      or a pre-connect error (eg: host name lookup failure).
    689689 *      Once the connect completes (successfully or unsuccessfully), callback
Note: See TracChangeset for help on using the changeset viewer.