Changeset 537d9b9 for protocols/purple


Ignore:
Timestamp:
2016-11-20T08:40:36Z (8 years ago)
Author:
dequis <dx@…>
Children:
3f44e43
Parents:
ba52ac5 (diff), 9f03c47 (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 master up to commit '9f03c47' into parson

Location:
protocols/purple
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • protocols/purple/bpurple.h

    rba52ac5 r537d9b9  
    1313    GHashTable *input_requests;
    1414    guint next_request_id;
     15    char *chat_list_server;
     16    GSList *filetransfers;
    1517};
    1618
  • protocols/purple/ft.c

    rba52ac5 r537d9b9  
    4242        char *fn, *handle;
    4343        gboolean ui_wants_data;
     44        int timeout;
    4445};
    4546
     
    6465        struct prpl_xfer_data *px = ft->data;
    6566
    66         purple_xfer_request_denied(px->xfer);
     67        if (px->xfer) {
     68                if (!purple_xfer_is_completed(px->xfer) && !purple_xfer_is_canceled(px->xfer)) {
     69                        purple_xfer_cancel_local(px->xfer);
     70                }
     71                px->xfer->ui_data = NULL;
     72                purple_xfer_unref(px->xfer);
     73                px->xfer = NULL;
     74        }
     75}
     76
     77static void prpl_xfer_free(struct file_transfer *ft)
     78{
     79        struct prpl_xfer_data *px = ft->data;
     80        struct purple_data *pd = px->ic->proto_data;
     81
     82        pd->filetransfers = g_slist_remove(pd->filetransfers, px);
     83
     84        if (px->xfer) {
     85                px->xfer->ui_data = NULL;
     86                purple_xfer_unref(px->xfer);
     87        }
     88
     89        if (px->timeout) {
     90                b_event_remove(px->timeout);
     91        }
     92
     93        g_free(px->fn);
     94        g_free(px->handle);
     95        if (px->fd >= 0) {
     96                close(px->fd);
     97        }
     98        g_free(px);
    6799}
    68100
    69101static void prplcb_xfer_new(PurpleXfer *xfer)
    70102{
     103        purple_xfer_ref(xfer);
     104
    71105        if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
    72106                struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
     107                struct purple_data *pd;
    73108
    74109                xfer->ui_data = px;
     
    77112                px->fd = -1;
    78113                px->ic = purple_ic_by_pa(xfer->account);
     114
     115                pd = px->ic->proto_data;
     116                pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
    79117
    80118                purple_xfer_set_local_filename(xfer, px->fn);
     
    112150        px->ft->accept = prpl_xfer_accept;
    113151        px->ft->canceled = prpl_xfer_canceled;
     152        px->ft->free = prpl_xfer_free;
    114153        px->ft->write_request = prpl_xfer_write_request;
    115154
     
    164203
    165204
    166 /* Generic (IM<>UI): */
    167205static void prplcb_xfer_destroy(PurpleXfer *xfer)
    168206{
    169207        struct prpl_xfer_data *px = xfer->ui_data;
    170208
    171         g_free(px->fn);
    172         g_free(px->handle);
    173         if (px->fd >= 0) {
    174                 close(px->fd);
    175         }
    176         g_free(px);
     209        if (px) {
     210                px->xfer = NULL;
     211        }
    177212}
    178213
     
    224259        struct prpl_xfer_data *px = xfer->ui_data;
    225260
    226         if (px->ft) {
     261        if (px && px->ft) {
    227262                imcb_file_canceled(px->ic, px->ft, "Canceled by remote end");
    228         } else {
     263        } else if (px) {
    229264                /* px->ft == NULL for sends, because of the two stages. :-/ */
    230265                imcb_error(px->ic, "File transfer cancelled by remote end");
     
    240275{
    241276        struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
     277        struct purple_data *pd;
    242278        char *dir, *basename;
    243279
    244280        ft->data = px;
    245281        px->ft = ft;
     282        px->ft->free = prpl_xfer_free;
    246283
    247284        dir = g_strdup("/tmp/bitlbee-purple-ft.XXXXXX");
     
    272309        px->handle = g_strdup(handle);
    273310
     311        pd = px->ic->proto_data;
     312        pd->filetransfers = g_slist_prepend(pd->filetransfers, px);
     313
    274314        imcb_log(ic,
    275315                 "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait...");
    276316
    277         b_timeout_add(0, purple_transfer_request_cb, ft);
     317        px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
    278318}
    279319
     
    295335        struct prpl_xfer_data *px = ft->data;
    296336
     337        px->timeout = 0;
     338
    297339        if (ft->write == NULL) {
    298340                ft->write = prpl_xfer_write;
     
    322364                px->ft = NULL;
    323365        } else {
    324                 b_timeout_add(0, purple_transfer_request_cb, ft);
     366                px->timeout = b_timeout_add(0, purple_transfer_request_cb, ft);
    325367        }
    326368
    327369        return TRUE;
     370}
     371
     372void purple_transfer_cancel_all(struct im_connection *ic)
     373{
     374        struct purple_data *pd = ic->proto_data;
     375
     376        while (pd->filetransfers) {
     377                struct prpl_xfer_data *px = pd->filetransfers->data;
     378
     379                if (px->ft) {
     380                        imcb_file_canceled(ic, px->ft, "Logging out");
     381                }
     382
     383                pd->filetransfers = g_slist_remove(pd->filetransfers, px);
     384        }
    328385}
    329386
  • protocols/purple/purple.c

    rba52ac5 r537d9b9  
    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);
     
    345366
    346367        ic->proto_data = pd = g_new0(struct purple_data, 1);
    347         pd->account = purple_account_new(acc->user, (char *) acc->prpl->data);
     368        pd->account = purple_account_new(acc->user, purple_get_account_prpl_id(acc));
    348369        pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
    349370                                                   NULL, g_free);
     
    371392        }
    372393
     394        if (pd->filetransfers) {
     395                purple_transfer_cancel_all(ic);
     396        }
     397
    373398        purple_account_set_enabled(pd->account, "BitlBee", FALSE);
    374399        purple_connections = g_slist_remove(purple_connections, ic);
    375400        purple_accounts_remove(pd->account);
     401        imcb_chat_list_free(ic);
     402        g_free(pd->chat_list_server);
    376403        g_hash_table_destroy(pd->input_requests);
    377404        g_free(pd);
     
    673700}
    674701
     702void purple_chat_set_topic(struct groupchat *gc, char *topic)
     703{
     704        PurpleConversation *pc = gc->data;
     705        PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc);
     706        struct purple_data *pd = gc->ic->proto_data;
     707        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
     708        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
     709
     710        if (pi->set_chat_topic) {
     711                pi->set_chat_topic(purple_account_get_connection(pd->account),
     712                                   purple_conv_chat_get_id(pcc),
     713                                   topic);
     714        }
     715}
     716
    675717void purple_chat_kick(struct groupchat *gc, char *who, const char *message)
    676718{
     
    697739        GHashTable *chat_hash;
    698740        PurpleConversation *conv;
     741        struct groupchat *gc;
    699742        GList *info, *l;
    700743
     
    730773        g_list_free(info);
    731774
     775        /* do this before serv_join_chat to handle cases where prplcb_conv_new is called immediately (not async) */
     776        gc = imcb_chat_new(ic, room);
     777
    732778        serv_join_chat(purple_account_get_connection(pd->account), chat_hash);
    733779
    734780        g_hash_table_destroy(chat_hash);
    735781
    736         return imcb_chat_new(ic, room);
     782        return gc;
     783}
     784
     785void purple_chat_list(struct im_connection *ic, const char *server)
     786{
     787        PurpleRoomlist *list;
     788        struct purple_data *pd = ic->proto_data;
     789        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
     790        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
     791
     792        if (!pi || !pi->roomlist_get_list) {
     793                imcb_log(ic, "Room listing unsupported by this purple plugin");
     794                return;
     795        }
     796
     797        g_free(pd->chat_list_server);
     798        pd->chat_list_server = (server && *server) ? g_strdup(server) : NULL;
     799
     800        list = purple_roomlist_get_list(pd->account->gc);
     801
     802        if (list) {
     803                struct purple_roomlist_data *rld = list->ui_data;
     804                rld->initialized = TRUE;
     805
     806                purple_roomlist_ref(list);
     807        }
    737808}
    738809
     
    9701041
    9711042/* Generic handler for IM or chat messages, covers write_chat, write_im and write_conv */
    972 static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message, guint32 bee_flags, time_t mtime)
     1043static void handle_conv_msg(PurpleConversation *conv, const char *who, const char *message_, guint32 bee_flags, time_t mtime)
    9731044{
    9741045        struct im_connection *ic = purple_ic_by_pa(conv->account);
    9751046        struct groupchat *gc = conv->ui_data;
     1047        char *message = g_strdup(message_);
    9761048        PurpleBuddy *buddy;
    9771049
     
    9821054
    9831055        if (conv->type == PURPLE_CONV_TYPE_IM) {
    984                 imcb_buddy_msg(ic, (char *) who, (char *) message, bee_flags, mtime);
     1056                imcb_buddy_msg(ic, who, message, bee_flags, mtime);
    9851057        } else if (gc) {
    986                 imcb_chat_msg(gc, who, (char *) message, bee_flags, mtime);
    987         }
     1058                imcb_chat_msg(gc, who, message, bee_flags, mtime);
     1059        }
     1060
     1061        g_free(message);
    9881062}
    9891063
     
    11711245        struct im_connection *ic = purple_ic_by_pa(account);
    11721246        struct purple_data *pd = ic->proto_data;
    1173         struct request_input_data *ri = g_new0(struct request_input_data, 1);
    1174         guint id = pd->next_request_id++;
     1247        struct request_input_data *ri;
     1248        guint id;
     1249
     1250        /* hack so that jabber's chat list doesn't ask for conference server twice */
     1251        if (pd->chat_list_server && title && g_strcmp0(title, "Enter a Conference Server") == 0) {
     1252                ((ri_callback_t) ok_cb)(user_data, pd->chat_list_server);
     1253                g_free(pd->chat_list_server);
     1254                pd->chat_list_server = NULL;
     1255                return NULL;
     1256        }
     1257
     1258        id = pd->next_request_id++;
     1259        ri = g_new0(struct request_input_data, 1);
    11751260
    11761261        ri->id = id;
     
    11821267
    11831268        imcb_add_buddy(ic, ri->buddy, NULL);
    1184         imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
     1269
     1270        if (title && *title) {
     1271                imcb_buddy_msg(ic, ri->buddy, title, 0, 0);
     1272        }
     1273
     1274        if (primary && *primary) {
     1275                imcb_buddy_msg(ic, ri->buddy, primary, 0, 0);
     1276        }
     1277
     1278        if (secondary && *secondary) {
     1279                imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
     1280        }
    11851281
    11861282        return ri;
     
    12561352        prplcb_privacy_deny_added,         /* deny_added */
    12571353        prplcb_privacy_deny_removed,       /* deny_removed */
     1354};
     1355
     1356static void prplcb_roomlist_create(PurpleRoomlist *list)
     1357{
     1358        struct purple_roomlist_data *rld;
     1359
     1360        list->ui_data = rld = g_new0(struct purple_roomlist_data, 1);
     1361        rld->topic = -1;
     1362}
     1363
     1364static void prplcb_roomlist_set_fields(PurpleRoomlist *list, GList *fields)
     1365{
     1366        gint topic = -1;
     1367        GList *l;
     1368        guint i;
     1369        PurpleRoomlistField *field;
     1370        struct purple_roomlist_data *rld = list->ui_data;
     1371
     1372        for (i = 0, l = fields; l; i++, l = l->next) {
     1373                field = l->data;
     1374
     1375                /* Use the first visible string field as a fallback topic */
     1376                if (i != 0 && topic < 0 && !field->hidden &&
     1377                    field->type == PURPLE_ROOMLIST_FIELD_STRING) {
     1378                        topic = i;
     1379                }
     1380
     1381                if ((g_strcasecmp(field->name, "description") == 0) ||
     1382                    (g_strcasecmp(field->name, "topic") == 0)) {
     1383                        if (field->type == PURPLE_ROOMLIST_FIELD_STRING) {
     1384                                rld->topic = i;
     1385                        }
     1386                }
     1387        }
     1388
     1389        if (rld->topic < 0) {
     1390                rld->topic = topic;
     1391        }
     1392}
     1393
     1394static void prplcb_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room)
     1395{
     1396        bee_chat_info_t *ci;
     1397        const char *title;
     1398        const char *topic;
     1399        GList *fields;
     1400        struct purple_roomlist_data *rld = list->ui_data;
     1401
     1402        fields = purple_roomlist_room_get_fields(room);
     1403        title = purple_roomlist_room_get_name(room);
     1404
     1405        if (rld->topic >= 0) {
     1406                topic = g_list_nth_data(fields, rld->topic);
     1407        } else {
     1408                topic = NULL;
     1409        }
     1410
     1411        ci = g_new(bee_chat_info_t, 1);
     1412        ci->title = g_strdup(title);
     1413        ci->topic = g_strdup(topic);
     1414        rld->chats = g_slist_prepend(rld->chats, ci);
     1415}
     1416
     1417static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress)
     1418{
     1419        struct im_connection *ic;
     1420        struct purple_data *pd;
     1421        struct purple_roomlist_data *rld = list->ui_data;
     1422
     1423        if (in_progress || !rld) {
     1424                return;
     1425        }
     1426
     1427        ic = purple_ic_by_pa(list->account);
     1428        imcb_chat_list_free(ic);
     1429
     1430        pd = ic->proto_data;
     1431        g_free(pd->chat_list_server);
     1432        pd->chat_list_server = NULL;
     1433
     1434        ic->chatlist = g_slist_reverse(rld->chats);
     1435        rld->chats = NULL;
     1436
     1437        imcb_chat_list_finish(ic);
     1438
     1439        if (rld->initialized) {
     1440                purple_roomlist_unref(list);
     1441        }
     1442}
     1443
     1444static void prplcb_roomlist_destroy(PurpleRoomlist *list)
     1445{
     1446        g_free(list->ui_data);
     1447        list->ui_data = NULL;
     1448}
     1449
     1450static PurpleRoomlistUiOps bee_roomlist_uiops =
     1451{
     1452        NULL,                         /* show_with_account */
     1453        prplcb_roomlist_create,       /* create */
     1454        prplcb_roomlist_set_fields,   /* set_fields */
     1455        prplcb_roomlist_add_room,     /* add_room */
     1456        prplcb_roomlist_in_progress,  /* in_progress */
     1457        prplcb_roomlist_destroy,      /* destroy */
    12581458};
    12591459
     
    14221622        purple_request_set_ui_ops(&bee_request_uiops);
    14231623        purple_privacy_set_ui_ops(&bee_privacy_uiops);
     1624        purple_roomlist_set_ui_ops(&bee_roomlist_uiops);
    14241625        purple_notify_set_ui_ops(&bee_notify_uiops);
    14251626        purple_accounts_set_ui_ops(&bee_account_uiops);
     
    14381639        char *dir;
    14391640
     1641        if (purple_get_core() != NULL) {
     1642                log_message(LOGLVL_ERROR, "libpurple already initialized. "
     1643                            "Please use inetd or ForkDaemon mode instead.");
     1644                return;
     1645        }
     1646
    14401647        g_assert((int) B_EV_IO_READ == (int) PURPLE_INPUT_READ);
    14411648        g_assert((int) B_EV_IO_WRITE == (int) PURPLE_INPUT_WRITE);
     
    14431650        dir = g_strdup_printf("%s/purple", global.conf->configdir);
    14441651        purple_util_set_user_dir(dir);
     1652        g_free(dir);
     1653
     1654        dir = g_strdup_printf("%s/purple", global.conf->plugindir);
     1655        purple_plugins_add_search_path(dir);
    14451656        g_free(dir);
    14461657
     
    15061717        funcs.chat_with = purple_chat_with;
    15071718        funcs.chat_invite = purple_chat_invite;
     1719        funcs.chat_topic = purple_chat_set_topic;
    15081720        funcs.chat_kick = purple_chat_kick;
    15091721        funcs.chat_leave = purple_chat_leave;
    15101722        funcs.chat_join = purple_chat_join;
     1723        funcs.chat_list = purple_chat_list;
    15111724        funcs.transfer_request = purple_transfer_request;
    15121725
     
    15171730        for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) {
    15181731                PurplePlugin *prot = prots->data;
     1732                PurplePluginProtocolInfo *pi = prot->info->extra_info;
    15191733                struct prpl *ret;
    15201734
     
    15301744                        ret->name += 5;
    15311745                }
     1746
     1747                if (pi->options & OPT_PROTO_NO_PASSWORD) {
     1748                        ret->options |= PRPL_OPT_NO_PASSWORD;
     1749                }
     1750
     1751                if (pi->options & OPT_PROTO_PASSWORD_OPTIONAL) {
     1752                        ret->options |= PRPL_OPT_PASSWORD_OPTIONAL;
     1753                }
     1754
    15321755                register_protocol(ret);
    15331756
     
    15391762                        ret = g_memdup(&funcs, sizeof(funcs));
    15401763                        ret->name = "oscar";
    1541                         ret->data = prot->info->id;
     1764                        /* purple_get_account_prpl_id() determines the actual protocol ID (icq/aim) */
     1765                        ret->data = NULL;
    15421766                        register_protocol(ret);
    15431767                }
Note: See TracChangeset for help on using the changeset viewer.