diff options
-rw-r--r-- | bitlbee.h | 2 | ||||
-rw-r--r-- | irc.c | 23 | ||||
-rw-r--r-- | irc.h | 27 | ||||
-rw-r--r-- | otr.c | 88 | ||||
-rw-r--r-- | otr.h | 6 | ||||
-rw-r--r-- | storage.c | 19 |
6 files changed, 108 insertions, 57 deletions
@@ -141,7 +141,6 @@ #include "sock.h" #include "misc.h" #include "proxy.h" -#include "otr.h" typedef struct global { /* In forked mode, child processes store the fd of the IPC socket here. */ @@ -153,7 +152,6 @@ typedef struct global { GList *storage; /* The first backend in the list will be used for saving */ char *helpfile; int restart; - OtrlMessageAppOps otr_ops; /* collects interface functions required by OTR */ } global_t; int bitlbee_daemon_init( void ); @@ -28,6 +28,7 @@ #include "dcc.h" GSList *irc_connection_list; +GSList *irc_plugins; static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ); static char *set_eval_charset( set_t *set, char *value ); @@ -41,6 +42,7 @@ irc_t *irc_new( int fd ) socklen_t socklen = sizeof( sock ); char *host = NULL, *myhost = NULL; irc_user_t *iu; + GSList *l; set_t *s; bee_t *b; @@ -163,6 +165,13 @@ irc_t *irc_new( int fd ) nogaim_init(); + for( l = irc_plugins; l; l = l->next ) + { + irc_plugin_t *p = l->data; + if( p->irc_new ) + p->irc_new( irc ); + } + return irc; } @@ -206,10 +215,19 @@ static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); void irc_free( irc_t * irc ) { + GSList *l; + irc->status |= USTATUS_SHUTDOWN; log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); + for( l = irc_plugins; l; l = l->next ) + { + irc_plugin_t *p = l->data; + if( p->irc_free ) + p->irc_free( irc ); + } + if( irc->status & USTATUS_IDENTIFIED && set_getbool( &irc->b->set, "save_on_quit" ) ) if( storage_save( irc, NULL, TRUE ) != STORAGE_OK ) log_message( LOGLVL_WARNING, "Error while saving settings for user %s", irc->user->nick ); @@ -931,3 +949,8 @@ static char *set_eval_bw_compat( set_t *set, char *value ) return SET_INVALID; } + +void register_irc_plugin( const struct irc_plugin *p ) +{ + irc_plugins = g_slist_prepend( irc_plugins, (gpointer) p ); +} @@ -26,8 +26,6 @@ #ifndef _IRC_H #define _IRC_H -#include "otr.h" - #define IRC_MAX_LINE 512 #define IRC_MAX_ARGS 16 @@ -87,7 +85,8 @@ typedef struct irc gint ping_source_id; gint login_source_id; /* To slightly delay some events at login time. */ - otr_t *otr; /* OTR state and book keeping */ + struct otr *otr; /* OTR state and book keeping, used by the OTR plugin. + TODO: Some mechanism for plugindata. */ struct bee *b; } irc_t; @@ -220,6 +219,26 @@ typedef enum IRC_CDU_KICK, } irc_channel_del_user_type_t; +/* These are a glued a little bit to the core/bee layer and a little bit to + IRC. The first user is OTR, and I guess at some point we'll get to shape + this a little bit more as other uses come up. */ +typedef struct irc_plugin +{ + /* Called at the end of irc_new(). Can be used to add settings, etc. */ + gboolean (*irc_new)( irc_t *irc ); + /* At the end of irc_free(). */ + void (*irc_free)( irc_t *irc ); + + /* Called by bee_irc_user_privmsg_cb(). Return NULL if you want to + abort sending the msg. */ + char* (*filter_msg_out)( irc_user_t *iu, const char *msg, int flags ); + /* Called by bee_irc_user_msg(). Return NULL if you swallowed the + message and don't want anything to go to the user. */ + char* (*filter_msg_in)( irc_user_t *iu, const char *msg, int flags ); +} irc_plugin_t; + +extern GSList *irc_plugins; /* struct irc_plugin */ + /* irc.c */ extern GSList *irc_connection_list; @@ -245,6 +264,8 @@ int irc_check_login( irc_t *irc ); void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); +void register_irc_plugin( const struct irc_plugin *p ); + /* irc_channel.c */ irc_channel_t *irc_channel_new( irc_t *irc, const char *name ); irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ); @@ -108,6 +108,8 @@ typedef struct { void *snd; } pair_t; +static OtrlMessageAppOps otr_ops; /* collects interface functions required by OTR */ + /** misc. helpers/subroutines: **/ @@ -173,6 +175,9 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args); /* find a private key by fingerprint prefix (given as any number of hex strings) */ OtrlPrivKey *match_privkey(irc_t *irc, const char **args); +/* functions to be called for certain events */ +static const struct irc_plugin otr_plugin; + /*** routines declared in otr.h: ***/ @@ -181,39 +186,52 @@ void otr_init(void) OTRL_INIT; /* fill global OtrlMessageAppOps */ - global.otr_ops.policy = &op_policy; - global.otr_ops.create_privkey = &op_create_privkey; - global.otr_ops.is_logged_in = &op_is_logged_in; - global.otr_ops.inject_message = &op_inject_message; - global.otr_ops.notify = NULL; - global.otr_ops.display_otr_message = &op_display_otr_message; - global.otr_ops.update_context_list = NULL; - global.otr_ops.protocol_name = NULL; - global.otr_ops.protocol_name_free = NULL; - global.otr_ops.new_fingerprint = &op_new_fingerprint; - global.otr_ops.write_fingerprints = &op_write_fingerprints; - global.otr_ops.gone_secure = &op_gone_secure; - global.otr_ops.gone_insecure = &op_gone_insecure; - global.otr_ops.still_secure = &op_still_secure; - global.otr_ops.log_message = &op_log_message; - global.otr_ops.max_message_size = &op_max_message_size; - global.otr_ops.account_name = &op_account_name; - global.otr_ops.account_name_free = NULL; + otr_ops.policy = &op_policy; + otr_ops.create_privkey = &op_create_privkey; + otr_ops.is_logged_in = &op_is_logged_in; + otr_ops.inject_message = &op_inject_message; + otr_ops.notify = NULL; + otr_ops.display_otr_message = &op_display_otr_message; + otr_ops.update_context_list = NULL; + otr_ops.protocol_name = NULL; + otr_ops.protocol_name_free = NULL; + otr_ops.new_fingerprint = &op_new_fingerprint; + otr_ops.write_fingerprints = &op_write_fingerprints; + otr_ops.gone_secure = &op_gone_secure; + otr_ops.gone_insecure = &op_gone_insecure; + otr_ops.still_secure = &op_still_secure; + otr_ops.log_message = &op_log_message; + otr_ops.max_message_size = &op_max_message_size; + otr_ops.account_name = &op_account_name; + otr_ops.account_name_free = NULL; root_command_add( "otr", 1, cmd_otr, 0 ); + register_irc_plugin( &otr_plugin ); } -otr_t *otr_new(void) +gboolean otr_irc_new(irc_t *irc) { - otr_t *otr = g_new0(otr_t, 1); - - otr->us = otrl_userstate_create(); + set_t *s; + GSList *l; + + irc->otr = g_new0(otr_t, 1); + irc->otr->us = otrl_userstate_create(); - return otr; + s = set_add( &irc->b->set, "otr_color_encrypted", "true", set_eval_bool, irc ); + + s = set_add( &irc->b->set, "otr_policy", "oppurtunistic", set_eval_list, irc ); + l = g_slist_prepend( NULL, "never" ); + l = g_slist_prepend( l, "opportunistic" ); + l = g_slist_prepend( l, "manual" ); + l = g_slist_prepend( l, "always" ); + s->eval_data = l; + + return TRUE; } -void otr_free(otr_t *otr) +void otr_irc_free(irc_t *irc) { + otr_t *otr = irc->otr; otrl_userstate_free(otr->us); if(otr->keygen) { kill(otr->keygen, SIGTERM); @@ -338,7 +356,7 @@ char *otr_handle_message(struct im_connection *ic, const char *handle, const cha return (g_strdup(msg)); } - ignore_msg = otrl_message_receiving(irc->otr->us, &global.otr_ops, ic, + ignore_msg = otrl_message_receiving(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, handle, msg, &newmsg, &tlvs, NULL, NULL); @@ -392,7 +410,7 @@ int otr_send_message(struct im_connection *ic, const char *handle, const char *m return (ic->acc->prpl->buddy_msg(ic, (char*) handle, (char*) msg, flags)); } - st = otrl_message_sending(irc->otr->us, &global.otr_ops, ic, + st = otrl_message_sending(irc->otr->us, &otr_ops, ic, ic->acc->user, ic->acc->prpl->name, handle, msg, NULL, &otrmsg, NULL, NULL); if(st) { @@ -408,7 +426,7 @@ int otr_send_message(struct im_connection *ic, const char *handle, const char *m otrl_message_free(otrmsg); return 1; } - st = otrl_message_fragment_and_send(&global.otr_ops, ic, ctx, + st = otrl_message_fragment_and_send(&otr_ops, ic, ctx, otrmsg, OTRL_FRAGMENT_SEND_ALL, NULL); otrl_message_free(otrmsg); } else { @@ -420,6 +438,12 @@ int otr_send_message(struct im_connection *ic, const char *handle, const char *m return st; } +static const struct irc_plugin otr_plugin = +{ + otr_irc_new, + otr_irc_free, +}; + static void cmd_otr(irc_t *irc, char **args) { const command_t *cmd; @@ -662,7 +686,7 @@ void cmd_otr_disconnect(irc_t *irc, char **args) return; } - otrl_message_disconnect(irc->otr->us, &global.otr_ops, + otrl_message_disconnect(irc->otr->us, &otr_ops, u->bu->ic, u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, u->bu->handle); /* for some reason, libotr (3.1.0) doesn't do this itself: */ @@ -720,7 +744,7 @@ void cmd_otr_smp(irc_t *irc, char **args) log_message(LOGLVL_INFO, "SMP already in phase %d, sending abort before reinitiating", ctx->smstate->nextExpected+1); - otrl_message_abort_smp(irc->otr->us, &global.otr_ops, u->bu->ic, ctx); + otrl_message_abort_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx); otrl_sm_state_free(ctx->smstate); } @@ -728,14 +752,14 @@ void cmd_otr_smp(irc_t *irc, char **args) is completed or aborted! */ if(ctx->smstate->secret == NULL) { irc_usermsg(irc, "smp: initiating with %s...", u->nick); - otrl_message_initiate_smp(irc->otr->us, &global.otr_ops, + otrl_message_initiate_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx, (unsigned char *)args[2], strlen(args[2])); /* smp is now in EXPECT2 */ } else { /* if we're still in EXPECT1 but smstate is initialized, we must have received the SMP1, so let's issue a response */ irc_usermsg(irc, "smp: responding to %s...", u->nick); - otrl_message_respond_smp(irc->otr->us, &global.otr_ops, + otrl_message_respond_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx, (unsigned char *)args[2], strlen(args[2])); /* smp is now in EXPECT3 */ } @@ -1049,7 +1073,7 @@ void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) { irc_t *irc = ic->bee->ui_data; OtrlUserState us = irc->otr->us; - OtrlMessageAppOps *ops = &global.otr_ops; + OtrlMessageAppOps *ops = &otr_ops; OtrlTLV *tlv = NULL; ConnContext *context; NextExpectedSMP nextMsg; @@ -71,10 +71,6 @@ typedef struct otr { /* called from main() */ void otr_init(void); -/* called from irc_new()/irc_free() */ -otr_t *otr_new(); -void otr_free(otr_t *otr); - /* called by storage_* functions */ void otr_load(struct irc *irc); void otr_save(struct irc *irc); @@ -97,8 +93,6 @@ int otr_send_message(struct im_connection *ic, const char *handle, const char *m typedef void otr_t; typedef void *OtrlMessageAppOps; -#define otr_init() {} -#define otr_new() (NULL) #define otr_free(otr) {} #define otr_load(irc) {} #define otr_save(irc) {} @@ -27,7 +27,6 @@ #define BITLBEE_CORE #include "bitlbee.h" -#include "otr.h" extern storage_t storage_text; extern storage_t storage_xml; @@ -114,10 +113,9 @@ storage_status_t storage_load (irc_t * irc, const char *password) storage_status_t status; status = st->load(irc, password); - if (status == STORAGE_OK) { - otr_load(irc); + if (status == STORAGE_OK) return status; - } + if (status != STORAGE_NO_SUCH_USER) return status; } @@ -138,8 +136,7 @@ storage_status_t storage_save (irc_t *irc, char *password, int overwrite) } else if ((irc->status & USTATUS_IDENTIFIED) == 0) { return STORAGE_NO_SUCH_USER; } - - otr_save(irc); + st = ((storage_t *)global.storage->data)->save(irc, overwrite); if (password != NULL) { @@ -165,9 +162,6 @@ storage_status_t storage_remove (const char *nick, const char *password) if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) ret = status; } - if (ret == STORAGE_OK) { - otr_remove(nick); - } return ret; } @@ -181,14 +175,12 @@ storage_status_t storage_rename (const char *onick, const char *nnick, const cha GList *gl = global.storage; storage_t *primary_storage = gl->data; irc_t *irc; - + /* First, try to rename in the current write backend, assuming onick * is stored there */ status = primary_storage->rename(onick, nnick, password); - if (status != STORAGE_NO_SUCH_USER) { - otr_rename(onick, nnick); + if (status != STORAGE_NO_SUCH_USER) return status; - } /* Try to load from a migration backend and save to the current backend. * Explicitly remove the account from the migration backend as otherwise @@ -212,7 +204,6 @@ storage_status_t storage_rename (const char *onick, const char *nnick, const cha irc_free(irc); storage_remove(onick, password); - otr_rename(onick, nnick); return STORAGE_OK; } |