Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/purple/purple.c

    r5ebff60 r2dd23da  
    2323
    2424#include "bitlbee.h"
     25#include "bpurple.h"
    2526#include "help.h"
    2627
     
    3940static char *set_eval_display_name(set_t *set, char *value);
    4041
     42void purple_request_input_callback(guint id, struct im_connection *ic,
     43                                   const char *message, const char *who);
     44
     45/* purple_request_input specific stuff */
     46typedef void (*ri_callback_t)(gpointer, const gchar *);
     47
     48struct request_input_data {
     49        ri_callback_t data_callback;
     50        void *user_data;
     51        struct im_connection *ic;
     52        char *buddy;
     53        guint id;
     54};
     55
    4156struct im_connection *purple_ic_by_pa(PurpleAccount *pa)
    4257{
    4358        GSList *i;
     59        struct purple_data *pd;
    4460
    4561        for (i = purple_connections; i; i = i->next) {
    46                 if (((struct im_connection *) i->data)->proto_data == pa) {
     62                pd = ((struct im_connection *) i->data)->proto_data;
     63                if (pd->account == pa) {
    4764                        return i->data;
    4865                }
     
    290307{
    291308        struct im_connection *ic = imcb_new(acc);
    292         PurpleAccount *pa;
     309        struct purple_data *pd;
    293310
    294311        if ((local_bee != NULL && local_bee != acc->bee) ||
     
    306323        purple_connections = g_slist_prepend(purple_connections, ic);
    307324
    308         ic->proto_data = pa = purple_account_new(acc->user, (char *) acc->prpl->data);
    309         purple_account_set_password(pa, acc->pass);
    310         purple_sync_settings(acc, pa);
    311 
    312         purple_account_set_enabled(pa, "BitlBee", TRUE);
     325        ic->proto_data = pd = g_new0(struct purple_data, 1);
     326        pd->account = purple_account_new(acc->user, (char *) acc->prpl->data);
     327        pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
     328                                                   NULL, g_free);
     329        pd->next_request_id = 0;
     330        purple_account_set_password(pd->account, acc->pass);
     331        purple_sync_settings(acc, pd->account);
     332
     333        purple_account_set_enabled(pd->account, "BitlBee", TRUE);
    313334}
    314335
    315336static void purple_logout(struct im_connection *ic)
    316337{
    317         PurpleAccount *pa = ic->proto_data;
    318 
    319         purple_account_set_enabled(pa, "BitlBee", FALSE);
     338        struct purple_data *pd = ic->proto_data;
     339
     340        if (!pd) {
     341                return;
     342        }
     343
     344        purple_account_set_enabled(pd->account, "BitlBee", FALSE);
    320345        purple_connections = g_slist_remove(purple_connections, ic);
    321         purple_accounts_remove(pa);
     346        purple_accounts_remove(pd->account);
     347        g_hash_table_destroy(pd->input_requests);
     348        g_free(pd);
    322349}
    323350
     
    325352{
    326353        PurpleConversation *conv;
     354        struct purple_data *pd = ic->proto_data;
     355
     356        if (!strncmp(who, PURPLE_REQUEST_HANDLE, sizeof(PURPLE_REQUEST_HANDLE) - 1)) {
     357                guint request_id = atoi(who + sizeof(PURPLE_REQUEST_HANDLE));
     358                purple_request_input_callback(request_id, ic, message, who);
     359                return 1;
     360        }
    327361
    328362        if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
    329                                                           who, ic->proto_data)) == NULL) {
     363                                                          who, pd->account)) == NULL) {
    330364                conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
    331                                                ic->proto_data, who);
     365                                               pd->account, who);
    332366        }
    333367
     
    339373static GList *purple_away_states(struct im_connection *ic)
    340374{
    341         PurpleAccount *pa = ic->proto_data;
     375        struct purple_data *pd = ic->proto_data;
    342376        GList *st, *ret = NULL;
    343377
    344         for (st = purple_account_get_status_types(pa); st; st = st->next) {
     378        for (st = purple_account_get_status_types(pd->account); st; st = st->next) {
    345379                PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data);
    346380                if (prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE) {
     
    354388static void purple_set_away(struct im_connection *ic, char *state_txt, char *message)
    355389{
    356         PurpleAccount *pa = ic->proto_data;
    357         GList *status_types = purple_account_get_status_types(pa), *st;
     390        struct purple_data *pd = ic->proto_data;
     391        GList *status_types = purple_account_get_status_types(pd->account), *st;
    358392        PurpleStatusType *pst = NULL;
    359393        GList *args = NULL;
     
    378412        }
    379413
    380         purple_account_set_status_list(pa, st ? purple_status_type_get_id(pst) : "away",
     414        purple_account_set_status_list(pd->account,
     415                                       st ? purple_status_type_get_id(pst) : "away",
    381416                                       TRUE, args);
    382417
     
    447482        PurpleBuddy *pb;
    448483        PurpleGroup *pg = NULL;
     484        struct purple_data *pd = ic->proto_data;
    449485
    450486        if (group && !(pg = purple_find_group(group))) {
     
    453489        }
    454490
    455         pb = purple_buddy_new((PurpleAccount *) ic->proto_data, who, NULL);
     491        pb = purple_buddy_new(pd->account, who, NULL);
    456492        purple_blist_add_buddy(pb, NULL, pg, NULL);
    457         purple_account_add_buddy((PurpleAccount *) ic->proto_data, pb);
    458 
    459         purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc);
     493        purple_account_add_buddy(pd->account, pb);
     494
     495        purple_gg_buddylist_export(pd->account->gc);
    460496}
    461497
     
    463499{
    464500        PurpleBuddy *pb;
    465 
    466         pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who);
     501        struct purple_data *pd = ic->proto_data;
     502
     503        pb = purple_find_buddy(pd->account, who);
    467504        if (pb != NULL) {
    468505                PurpleGroup *group;
    469506
    470507                group = purple_buddy_get_group(pb);
    471                 purple_account_remove_buddy((PurpleAccount *) ic->proto_data, pb, group);
     508                purple_account_remove_buddy(pd->account, pb, group);
    472509
    473510                purple_blist_remove_buddy(pb);
    474511        }
    475512
    476         purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc);
     513        purple_gg_buddylist_export(pd->account->gc);
    477514}
    478515
    479516static void purple_add_permit(struct im_connection *ic, char *who)
    480517{
    481         PurpleAccount *pa = ic->proto_data;
    482 
    483         purple_privacy_permit_add(pa, who, FALSE);
     518        struct purple_data *pd = ic->proto_data;
     519
     520        purple_privacy_permit_add(pd->account, who, FALSE);
    484521}
    485522
    486523static void purple_add_deny(struct im_connection *ic, char *who)
    487524{
    488         PurpleAccount *pa = ic->proto_data;
    489 
    490         purple_privacy_deny_add(pa, who, FALSE);
     525        struct purple_data *pd = ic->proto_data;
     526
     527        purple_privacy_deny_add(pd->account, who, FALSE);
    491528}
    492529
    493530static void purple_rem_permit(struct im_connection *ic, char *who)
    494531{
    495         PurpleAccount *pa = ic->proto_data;
    496 
    497         purple_privacy_permit_remove(pa, who, FALSE);
     532        struct purple_data *pd = ic->proto_data;
     533
     534        purple_privacy_permit_remove(pd->account, who, FALSE);
    498535}
    499536
    500537static void purple_rem_deny(struct im_connection *ic, char *who)
    501538{
    502         PurpleAccount *pa = ic->proto_data;
    503 
    504         purple_privacy_deny_remove(pa, who, FALSE);
     539        struct purple_data *pd = ic->proto_data;
     540
     541        purple_privacy_deny_remove(pd->account, who, FALSE);
    505542}
    506543
    507544static void purple_get_info(struct im_connection *ic, char *who)
    508545{
    509         serv_get_info(purple_account_get_connection(ic->proto_data), who);
     546        struct purple_data *pd = ic->proto_data;
     547
     548        serv_get_info(purple_account_get_connection(pd->account), who);
    510549}
    511550
     
    517556{
    518557        PurpleTypingState state = PURPLE_NOT_TYPING;
    519         PurpleAccount *pa = ic->proto_data;
     558        struct purple_data *pd = ic->proto_data;
    520559
    521560        if (flags & OPT_TYPING) {
     
    525564        }
    526565
    527         serv_send_typing(purple_account_get_connection(pa), who, state);
     566        serv_send_typing(purple_account_get_connection(pd->account), who, state);
    528567
    529568        return 1;
     
    559598        /* There went my nice afternoon. :-( */
    560599
    561         PurpleAccount *pa = ic->proto_data;
    562         PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id);
     600        struct purple_data *pd = ic->proto_data;
     601        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
    563602        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    564         PurpleBuddy *pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who);
     603        PurpleBuddy *pb = purple_find_buddy(pd->account, who);
    565604        PurpleMenuAction *mi;
    566605        GList *menu;
     
    597636        PurpleConversation *pc = gc->data;
    598637        PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc);
    599 
    600         serv_chat_invite(purple_account_get_connection(gc->ic->proto_data),
     638        struct purple_data *pd = gc->ic->proto_data;
     639
     640        serv_chat_invite(purple_account_get_connection(pd->account),
    601641                         purple_conv_chat_get_id(pcc),
    602642                         message && *message ? message : "Please join my chat",
     
    623663                                   set_t **sets)
    624664{
    625         PurpleAccount *pa = ic->proto_data;
    626         PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id);
     665        struct purple_data *pd = ic->proto_data;
     666        PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id);
    627667        PurplePluginProtocolInfo *pi = prpl->info->extra_info;
    628668        GHashTable *chat_hash;
     
    631671
    632672        if (!pi->chat_info || !pi->chat_info_defaults ||
    633             !(info = pi->chat_info(purple_account_get_connection(pa)))) {
     673            !(info = pi->chat_info(purple_account_get_connection(pd->account)))) {
    634674                imcb_error(ic, "Joining chatrooms not supported by this protocol");
    635675                return NULL;
    636676        }
    637677
    638         if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, room, pa))) {
     678        if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
     679                                                          room, pd->account))) {
    639680                purple_conversation_destroy(conv);
    640681        }
    641682
    642         chat_hash = pi->chat_info_defaults(purple_account_get_connection(pa), room);
     683        chat_hash = pi->chat_info_defaults(
     684                purple_account_get_connection(pd->account), room
     685        );
    643686
    644687        for (l = info; l; l = l->next) {
     
    654697        }
    655698
    656         serv_join_chat(purple_account_get_connection(pa), chat_hash);
     699        serv_join_chat(purple_account_get_connection(pd->account), chat_hash);
    657700
    658701        return NULL;
     
    9811024                pqad->yes(pqad->user_data, pqad->yes_i);
    9821025        }
    983         g_free(pqad);
    9841026}
    9851027
     
    9911033                pqad->no(pqad->user_data, pqad->no_i);
    9921034        }
    993         g_free(pqad);
     1035}
     1036
     1037/* q->free() callback from query_del()*/
     1038static void prplcb_request_action_free(void *data)
     1039{
     1040        struct prplcb_request_action_data *pqad = data;
     1041
     1042        pqad->bee_data = NULL;
     1043        purple_request_close(PURPLE_REQUEST_ACTION, pqad);
    9941044}
    9951045
     
    10261076        q = g_strdup_printf("Request: %s\n\n%s\n\n%s", title, primary, secondary);
    10271077        pqad->bee_data = query_add(local_bee->ui_data, purple_ic_by_pa(account), q,
    1028                                    prplcb_request_action_yes, prplcb_request_action_no, g_free, pqad);
     1078                                   prplcb_request_action_yes, prplcb_request_action_no,
     1079                                   prplcb_request_action_free, pqad);
    10291080
    10301081        g_free(q);
     
    10331084}
    10341085
    1035 /*
    1036 static void prplcb_request_test()
    1037 {
    1038         fprintf( stderr, "bla\n" );
    1039 }
    1040 */
     1086/* So it turns out some requests have no account context at all, because
     1087 * libpurple hates us. This means that query_del_by_conn() won't remove those
     1088 * on logout, and will segfault if the user replies. That's why this exists.
     1089 */
     1090static void prplcb_close_request(PurpleRequestType type, void *data)
     1091{
     1092        struct prplcb_request_action_data *pqad;
     1093        struct request_input_data *ri;
     1094        struct purple_data *pd;
     1095
     1096        if (!data) {
     1097                return;
     1098        }
     1099
     1100        switch (type) {
     1101        case PURPLE_REQUEST_ACTION:
     1102                pqad = data;
     1103                /* if this is null, it's because query_del was run already */
     1104                if (pqad->bee_data) {
     1105                        query_del(local_bee->ui_data, pqad->bee_data);
     1106                }
     1107                g_free(pqad);
     1108                break;
     1109        case PURPLE_REQUEST_INPUT:
     1110                ri = data;
     1111                pd = ri->ic->proto_data;
     1112                imcb_remove_buddy(ri->ic, ri->buddy, NULL);
     1113                g_free(ri->buddy);
     1114                g_hash_table_remove(pd->input_requests, GUINT_TO_POINTER(ri->id));
     1115                break;
     1116        default:
     1117                g_free(data);
     1118                break;
     1119        }
     1120
     1121}
     1122
     1123void* prplcb_request_input(const char *title, const char *primary,
     1124        const char *secondary, const char *default_value, gboolean multiline,
     1125        gboolean masked, gchar *hint, const char *ok_text, GCallback ok_cb,
     1126        const char *cancel_text, GCallback cancel_cb, PurpleAccount *account,
     1127        const char *who, PurpleConversation *conv, void *user_data)
     1128{
     1129        struct im_connection *ic = purple_ic_by_pa(account);
     1130        struct purple_data *pd = ic->proto_data;
     1131        struct request_input_data *ri = g_new0(struct request_input_data, 1);
     1132        guint id = pd->next_request_id++;
     1133
     1134        ri->id = id;
     1135        ri->ic = ic;
     1136        ri->buddy = g_strdup_printf("%s_%u", PURPLE_REQUEST_HANDLE, id);
     1137        ri->data_callback = (ri_callback_t) ok_cb;
     1138        ri->user_data = user_data;
     1139        g_hash_table_insert(pd->input_requests, GUINT_TO_POINTER(id), ri);
     1140
     1141        imcb_add_buddy(ic, ri->buddy, NULL);
     1142        imcb_buddy_msg(ic, ri->buddy, secondary, 0, 0);
     1143
     1144        return ri;
     1145}
     1146
     1147void purple_request_input_callback(guint id, struct im_connection *ic,
     1148                                   const char *message, const char *who)
     1149{
     1150        struct purple_data *pd = ic->proto_data;
     1151        struct request_input_data *ri;
     1152
     1153        if (!(ri = g_hash_table_lookup(pd->input_requests, GUINT_TO_POINTER(id)))) {
     1154                return;
     1155        }
     1156
     1157        ri->data_callback(ri->user_data, message);
     1158
     1159        purple_request_close(PURPLE_REQUEST_INPUT, ri);
     1160}
     1161
    10411162
    10421163static PurpleRequestUiOps bee_request_uiops =
    10431164{
    1044         NULL,
     1165        prplcb_request_input,
    10451166        NULL,
    10461167        prplcb_request_action,
    10471168        NULL,
    10481169        NULL,
    1049         NULL,
     1170        prplcb_close_request,
    10501171        NULL,
    10511172};
Note: See TracChangeset for help on using the changeset viewer.