Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/purple/purple.c

    rba7618d r9f03c47  
    4343                                   const char *message, const char *who);
    4444
     45void purple_transfer_cancel_all(struct im_connection *ic);
     46
    4547/* purple_request_input specific stuff */
    4648typedef void (*ri_callback_t)(gpointer, const gchar *);
     
    5456};
    5557
     58struct purple_roomlist_data {
     59        GSList *chats;
     60        gint topic;
     61        gboolean initialized;
     62};
     63
     64
    5665struct im_connection *purple_ic_by_pa(PurpleAccount *pa)
    5766{
     
    94103}
    95104
     105static char *purple_get_account_prpl_id(account_t *acc)
     106{
     107        /* "oscar" is how non-purple bitlbee calls it,
     108         * and it might be icq or aim, depending on the username */
     109        if (g_strcmp0(acc->prpl->name, "oscar") == 0) {
     110                return (g_ascii_isdigit(acc->user[0])) ? "prpl-icq" : "prpl-aim";
     111        }
     112
     113        return acc->prpl->data;
     114}
     115
    96116static void purple_init(account_t *acc)
    97117{
    98         PurplePlugin *prpl = purple_plugins_find_with_id((char *) acc->prpl->data);
     118        char *prpl_id = purple_get_account_prpl_id(acc);
     119        PurplePlugin *prpl = purple_plugins_find_with_id(prpl_id);
    99120        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    100121        PurpleAccount *pa;
     
    262283        /* Go through all away states to figure out if away/status messages
    263284           are possible. */
    264         pa = purple_account_new(acc->user, (char *) acc->prpl->data);
     285        pa = purple_account_new(acc->user, prpl_id);
    265286        for (st = purple_account_get_status_types(pa); st; st = st->next) {
    266287                PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data);
     
    340361
    341362        ic->proto_data = pd = g_new0(struct purple_data, 1);
    342         pd->account = purple_account_new(acc->user, (char *) acc->prpl->data);
     363        pd->account = purple_account_new(acc->user, purple_get_account_prpl_id(acc));
    343364        pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
    344365                                                   NULL, g_free);
     
    366387        }
    367388
     389        if (pd->filetransfers) {
     390                purple_transfer_cancel_all(ic);
     391        }
     392
    368393        purple_account_set_enabled(pd->account, "BitlBee", FALSE);
    369394        purple_connections = g_slist_remove(purple_connections, ic);
    370395        purple_accounts_remove(pd->account);
     396        imcb_chat_list_free(ic);
     397        g_free(pd->chat_list_server);
    371398        g_hash_table_destroy(pd->input_requests);
    372399        g_free(pd);
     
    668695}
    669696
     697void purple_chat_set_topic(struct groupchat *gc, char *topic)
     698{
     699        PurpleConversation *pc = gc->data;
     700        PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc);
     701        struct purple_data *pd = gc->ic->proto_data;
     702        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
     703        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
     704
     705        if (pi->set_chat_topic) {
     706                pi->set_chat_topic(purple_account_get_connection(pd->account),
     707                                   purple_conv_chat_get_id(pcc),
     708                                   topic);
     709        }
     710}
     711
    670712void purple_chat_kick(struct groupchat *gc, char *who, const char *message)
    671713{
     
    692734        GHashTable *chat_hash;
    693735        PurpleConversation *conv;
     736        struct groupchat *gc;
    694737        GList *info, *l;
    695738
     
    725768        g_list_free(info);
    726769
     770        /* do this before serv_join_chat to handle cases where prplcb_conv_new is called immediately (not async) */
     771        gc = imcb_chat_new(ic, room);
     772
    727773        serv_join_chat(purple_account_get_connection(pd->account), chat_hash);
    728774
    729775        g_hash_table_destroy(chat_hash);
    730776
    731         return imcb_chat_new(ic, room);
     777        return gc;
     778}
     779
     780void purple_chat_list(struct im_connection *ic, const char *server)
     781{
     782        PurpleRoomlist *list;
     783        struct purple_data *pd = ic->proto_data;
     784        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
     785        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
     786
     787        if (!pi || !pi->roomlist_get_list) {
     788                imcb_log(ic, "Room listing unsupported by this purple plugin");
     789                return;
     790        }
     791
     792        g_free(pd->chat_list_server);
     793        pd->chat_list_server = (server && *server) ? g_strdup(server) : NULL;
     794
     795        list = purple_roomlist_get_list(pd->account->gc);
     796
     797        if (list) {
     798                struct purple_roomlist_data *rld = list->ui_data;
     799                rld->initialized = TRUE;
     800
     801                purple_roomlist_ref(list);
     802        }
    732803}
    733804
     
    9651036
    9661037/* Generic handler for IM or chat messages, covers write_chat, write_im and write_conv */
    967 static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message, guint32 bee_flags, time_t mtime)
     1038static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message_, guint32 bee_flags, time_t mtime)
    9681039{
    9691040        struct im_connection *ic = purple_ic_by_pa(conv->account);
    9701041        struct groupchat *gc = conv->ui_data;
     1042        char *message = g_strdup(message_);
    9711043        PurpleBuddy *buddy;
    9721044
     
    9771049
    9781050        if (conv->type == PURPLE_CONV_TYPE_IM) {
    979                 imcb_buddy_msg(ic, (char *) who, (char *) message, bee_flags, mtime);
     1051                imcb_buddy_msg(ic, who, message, bee_flags, mtime);
    9801052        } else if (gc) {
    981                 imcb_chat_msg(gc, who, (char *) message, bee_flags, mtime);
    982         }
     1053                imcb_chat_msg(gc, who, message, bee_flags, mtime);
     1054        }
     1055
     1056        g_free(message);
    9831057}
    9841058
     
    11661240        struct im_connection *ic = purple_ic_by_pa(account);
    11671241        struct purple_data *pd = ic->proto_data;
    1168         struct request_input_data *ri = g_new0(struct request_input_data, 1);
    1169         guint id = pd->next_request_id++;
     1242        struct request_input_data *ri;
     1243        guint id;
     1244
     1245        /* hack so that jabber's chat list doesn't ask for conference server twice */
     1246        if (pd->chat_list_server && title && g_strcmp0(title, "Enter a Conference Server") == 0) {
     1247                ((ri_callback_t) ok_cb)(user_data, pd->chat_list_server);
     1248                g_free(pd->chat_list_server);
     1249                pd->chat_list_server = NULL;
     1250                return NULL;
     1251        }
     1252
     1253        id = pd->next_request_id++;
     1254        ri = g_new0(struct request_input_data, 1);
    11701255
    11711256        ri->id = id;
     
    11771262
    11781263        imcb_add_buddy(ic, ri->buddy, NULL);
    1179         imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
     1264
     1265        if (title && *title) {
     1266                imcb_buddy_msg(ic, ri->buddy, title, 0, 0);
     1267        }
     1268
     1269        if (primary && *primary) {
     1270                imcb_buddy_msg(ic, ri->buddy, primary, 0, 0);
     1271        }
     1272
     1273        if (secondary && *secondary) {
     1274                imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
     1275        }
    11801276
    11811277        return ri;
     
    12511347        prplcb_privacy_deny_added,         /* deny_added */
    12521348        prplcb_privacy_deny_removed,       /* deny_removed */
     1349};
     1350
     1351static void prplcb_roomlist_create(PurpleRoomlist *list)
     1352{
     1353        struct purple_roomlist_data *rld;
     1354
     1355        list->ui_data = rld = g_new0(struct purple_roomlist_data, 1);
     1356        rld->topic = -1;
     1357}
     1358
     1359static void prplcb_roomlist_set_fields(PurpleRoomlist *list, GList *fields)
     1360{
     1361        gint topic = -1;
     1362        GList *l;
     1363        guint i;
     1364        PurpleRoomlistField *field;
     1365        struct purple_roomlist_data *rld = list->ui_data;
     1366
     1367        for (i = 0, l = fields; l; i++, l = l->next) {
     1368                field = l->data;
     1369
     1370                /* Use the first visible string field as a fallback topic */
     1371                if (i != 0 && topic < 0 && !field->hidden &&
     1372                    field->type == PURPLE_ROOMLIST_FIELD_STRING) {
     1373                        topic = i;
     1374                }
     1375
     1376                if ((g_strcasecmp(field->name, "description") == 0) ||
     1377                    (g_strcasecmp(field->name, "topic") == 0)) {
     1378                        if (field->type == PURPLE_ROOMLIST_FIELD_STRING) {
     1379                                rld->topic = i;
     1380                        }
     1381                }
     1382        }
     1383
     1384        if (rld->topic < 0) {
     1385                rld->topic = topic;
     1386        }
     1387}
     1388
     1389static void prplcb_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room)
     1390{
     1391        bee_chat_info_t *ci;
     1392        const char *title;
     1393        const char *topic;
     1394        GList *fields;
     1395        struct purple_roomlist_data *rld = list->ui_data;
     1396
     1397        fields = purple_roomlist_room_get_fields(room);
     1398        title = purple_roomlist_room_get_name(room);
     1399
     1400        if (rld->topic >= 0) {
     1401                topic = g_list_nth_data(fields, rld->topic);
     1402        } else {
     1403                topic = NULL;
     1404        }
     1405
     1406        ci = g_new(bee_chat_info_t, 1);
     1407        ci->title = g_strdup(title);
     1408        ci->topic = g_strdup(topic);
     1409        rld->chats = g_slist_prepend(rld->chats, ci);
     1410}
     1411
     1412static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress)
     1413{
     1414        struct im_connection *ic;
     1415        struct purple_data *pd;
     1416        struct purple_roomlist_data *rld = list->ui_data;
     1417
     1418        if (in_progress || !rld) {
     1419                return;
     1420        }
     1421
     1422        ic = purple_ic_by_pa(list->account);
     1423        imcb_chat_list_free(ic);
     1424
     1425        pd = ic->proto_data;
     1426        g_free(pd->chat_list_server);
     1427        pd->chat_list_server = NULL;
     1428
     1429        ic->chatlist = g_slist_reverse(rld->chats);
     1430        rld->chats = NULL;
     1431
     1432        imcb_chat_list_finish(ic);
     1433
     1434        if (rld->initialized) {
     1435                purple_roomlist_unref(list);
     1436        }
     1437}
     1438
     1439static void prplcb_roomlist_destroy(PurpleRoomlist *list)
     1440{
     1441        g_free(list->ui_data);
     1442        list->ui_data = NULL;
     1443}
     1444
     1445static PurpleRoomlistUiOps bee_roomlist_uiops =
     1446{
     1447        NULL,                         /* show_with_account */
     1448        prplcb_roomlist_create,       /* create */
     1449        prplcb_roomlist_set_fields,   /* set_fields */
     1450        prplcb_roomlist_add_room,     /* add_room */
     1451        prplcb_roomlist_in_progress,  /* in_progress */
     1452        prplcb_roomlist_destroy,      /* destroy */
    12531453};
    12541454
     
    14171617        purple_request_set_ui_ops(&bee_request_uiops);
    14181618        purple_privacy_set_ui_ops(&bee_privacy_uiops);
     1619        purple_roomlist_set_ui_ops(&bee_roomlist_uiops);
    14191620        purple_notify_set_ui_ops(&bee_notify_uiops);
    14201621        purple_accounts_set_ui_ops(&bee_account_uiops);
     
    14331634        char *dir;
    14341635
     1636        if (purple_get_core() != NULL) {
     1637                log_message(LOGLVL_ERROR, "libpurple already initialized. "
     1638                            "Please use inetd or ForkDaemon mode instead.");
     1639                return;
     1640        }
     1641
    14351642        g_assert((int) B_EV_IO_READ == (int) PURPLE_INPUT_READ);
    14361643        g_assert((int) B_EV_IO_WRITE == (int) PURPLE_INPUT_WRITE);
     
    14381645        dir = g_strdup_printf("%s/purple", global.conf->configdir);
    14391646        purple_util_set_user_dir(dir);
     1647        g_free(dir);
     1648
     1649        dir = g_strdup_printf("%s/purple", global.conf->plugindir);
     1650        purple_plugins_add_search_path(dir);
    14401651        g_free(dir);
    14411652
     
    15011712        funcs.chat_with = purple_chat_with;
    15021713        funcs.chat_invite = purple_chat_invite;
     1714        funcs.chat_topic = purple_chat_set_topic;
    15031715        funcs.chat_kick = purple_chat_kick;
    15041716        funcs.chat_leave = purple_chat_leave;
    15051717        funcs.chat_join = purple_chat_join;
     1718        funcs.chat_list = purple_chat_list;
    15061719        funcs.transfer_request = purple_transfer_request;
    15071720
     
    15121725        for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) {
    15131726                PurplePlugin *prot = prots->data;
     1727                PurplePluginProtocolInfo *pi = prot->info->extra_info;
    15141728                struct prpl *ret;
    15151729
     
    15251739                        ret->name += 5;
    15261740                }
     1741
     1742                if (pi->options & OPT_PROTO_NO_PASSWORD) {
     1743                        ret->options |= PRPL_OPT_NO_PASSWORD;
     1744                }
     1745
     1746                if (pi->options & OPT_PROTO_PASSWORD_OPTIONAL) {
     1747                        ret->options |= PRPL_OPT_PASSWORD_OPTIONAL;
     1748                }
     1749
    15271750                register_protocol(ret);
    15281751
     
    15341757                        ret = g_memdup(&funcs, sizeof(funcs));
    15351758                        ret->name = "oscar";
    1536                         ret->data = prot->info->id;
     1759                        /* purple_get_account_prpl_id() determines the actual protocol ID (icq/aim) */
     1760                        ret->data = NULL;
    15371761                        register_protocol(ret);
    15381762                }
Note: See TracChangeset for help on using the changeset viewer.