diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-09-01 01:18:21 +0200 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-09-01 01:18:21 +0200 | 
| commit | 0c85c08d210e16bb10dc283b4a1478ce53c0c1b1 (patch) | |
| tree | 4d7fb00a0467ba51337fdc84cacade43b6baab97 | |
| parent | f5c0d8e4dd3ce01945a6334a5d87c89a9f43b16b (diff) | |
Pluginify this thing a little bit. Not so much in the dynamically loadable
sense of the word, more in a way that core files don't have to include otr.h.
| -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;  } | 
