diff options
| -rw-r--r-- | irc.c | 25 | ||||
| -rw-r--r-- | irc.h | 2 | ||||
| -rw-r--r-- | lib/misc.c | 12 | ||||
| -rw-r--r-- | otr.c | 286 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 1 | ||||
| -rw-r--r-- | protocols/msn/msn.c | 1 | ||||
| -rw-r--r-- | protocols/nogaim.c | 17 | ||||
| -rw-r--r-- | protocols/nogaim.h | 4 | ||||
| -rw-r--r-- | protocols/oscar/oscar.c | 1 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo.c | 1 | ||||
| -rw-r--r-- | set.c | 145 | ||||
| -rw-r--r-- | set.h | 5 | ||||
| -rw-r--r-- | user.h | 1 | 
13 files changed, 420 insertions, 81 deletions
| @@ -101,8 +101,7 @@ irc_t *irc_new( int fd )  	irc_write( irc, ":%s NOTICE AUTH :%s", irc->myhost, "BitlBee-IRCd initialized, please go on" );  	irc_connection_list = g_slist_append( irc_connection_list, irc ); -	 -	set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc ); +  	set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );  	set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );  	set_add( &irc->set, "auto_reconnect_delay", "300", set_eval_int, irc ); @@ -114,7 +113,9 @@ irc_t *irc_new( int fd )  	set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );  	set_add( &irc->set, "handle_unknown", "root", NULL, irc );  	set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc ); -	set_add( &irc->set, "ops", "both", set_eval_ops, irc ); +	set_add( &irc->set, "op_buddies", "false", set_eval_op_buddies, irc ); +	set_add( &irc->set, "op_root", "true", set_eval_op_root, irc ); +	set_add( &irc->set, "op_user", "true", set_eval_op_user, irc );  	set_add( &irc->set, "password", NULL, passchange, irc );  	set_add( &irc->set, "private", "true", set_eval_bool, irc );  	set_add( &irc->set, "query_order", "lifo", NULL, irc ); @@ -123,6 +124,7 @@ irc_t *irc_new( int fd )  	set_add( &irc->set, "strip_html", "true", NULL, irc );  	set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );  	set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc ); +	set_add( &irc->set, "voice_buddies", "notaway",  set_eval_voice_buddies, irc );  	conf_loaddefaults( irc ); @@ -642,7 +644,8 @@ void irc_names( irc_t *irc, char *channel )  	user_t *u;  	char namelist[385] = "";  	struct groupchat *c = NULL; -	char *ops = set_getstr( &irc->set, "ops" ); +	char *oo = set_getstr(&irc->set, "op_buddies"); +	char *vo = set_getstr(&irc->set, "voice_buddies");  	/* RFCs say there is no error reply allowed on NAMES, so when the  	   channel is invalid, just give an empty reply. */ @@ -657,10 +660,13 @@ void irc_names( irc_t *irc, char *channel )  				*namelist = 0;  			} -			if( u->ic && !u->away && set_getbool( &irc->set, "away_devoice" ) ) +			if( u->ic && !u->away && !strcmp(vo, "notaway") )  				strcat( namelist, "+" ); -			else if( ( strcmp( u->nick, irc->mynick ) == 0 && ( strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) == 0 ) ) || -			         ( strcmp( u->nick, irc->nick ) == 0 && ( strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) == 0 ) ) ) +			else if( ( strcmp( u->nick, irc->mynick ) == 0 && set_getbool(&irc->set, "op_root") ) || +			         ( strcmp( u->nick, irc->nick ) == 0 && set_getbool(&irc->set, "op_user") ) || +			         ( !u->away && !strcmp(oo, "notaway") ) || +			         ( u->encrypted>1 && !strcmp(oo, "trusted") ) || +			         ( u->encrypted && !strcmp(oo, "encrypted") ) )  				strcat( namelist, "@" );  			strcat( namelist, u->nick ); @@ -673,9 +679,10 @@ void irc_names( irc_t *irc, char *channel )  		/* root and the user aren't in the channel userlist but should  		   show up in /NAMES, so list them first: */ -		sprintf( namelist, "%s%s %s%s ", strcmp( ops, "root" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->mynick, -		                                 strcmp( ops, "user" ) == 0 || strcmp( ops, "both" ) ? "@" : "", irc->nick ); +		sprintf( namelist, "%s%s %s%s ", set_getbool(&irc->set, "op_root") ? "@" : "", irc->mynick, +		                                 set_getbool(&irc->set, "op_user") ? "@" : "", irc->nick ); +		/* TODO: Honor op/voice_buddies in chats?! */  		for( l = c->in_room; l; l = l->next ) if( ( u = user_findhandle( c->ic, l->data ) ) )  		{  			if( strlen( namelist ) + strlen( u->nick ) > sizeof( namelist ) - 4 ) @@ -29,7 +29,7 @@  #include "otr.h"  #define IRC_MAX_LINE 512 -#define IRC_MAX_ARGS 8 +#define IRC_MAX_ARGS 16  #define IRC_LOGIN_TIMEOUT 60  #define IRC_PING_STRING "PinglBee" @@ -142,6 +142,7 @@ void strip_html( char *in )  	char *out = g_malloc( strlen( in ) + 1 );  	char *s = out, *cs;  	int i, matched; +	int taglen;  	memset( out, 0, strlen( in ) + 1 ); @@ -158,9 +159,18 @@ void strip_html( char *in )  			while( *in && *in != '>' )  				in ++; +			taglen = in-cs-1;   /* not <0 because the above loop runs at least once */  			if( *in )  			{ -				if( g_strncasecmp( cs+1, "br", 2) == 0 ) +				if( g_strncasecmp( cs+1, "b", taglen) == 0 ) +					*(s++) = '\x02'; +				else if( g_strncasecmp( cs+1, "/b", taglen) == 0 ) +					*(s++) = '\x02'; +				else if( g_strncasecmp( cs+1, "i", taglen) == 0 ) +					*(s++) = '\x1f'; +				else if( g_strncasecmp( cs+1, "/i", taglen) == 0 ) +					*(s++) = '\x1f'; +				else if( g_strncasecmp( cs+1, "br", 2) == 0 )  					*(s++) = '\n';  				in ++;  			} @@ -34,8 +34,6 @@ void op_write_fingerprints(void *opdata);  void op_gone_secure(void *opdata, ConnContext *context); -void op_gone_secure(void *opdata, ConnContext *context); -  void op_gone_insecure(void *opdata, ConnContext *context);  void op_still_secure(void *opdata, ConnContext *context, int is_reply); @@ -52,7 +50,8 @@ const char *op_account_name(void *opdata, const char *account, const char *proto  /* TODO: void cmd_otr_keygen(irc_t *irc, char **args); */  void cmd_otr_abort(irc_t *irc, char **args); /* TODO: does this cmd even make sense? */  void cmd_otr_request(irc_t *irc, char **args); /* TODO: do we even need this? */ -void cmd_otr_auth(irc_t *irc, char **args); +void cmd_otr_smp(irc_t *irc, char **args); +void cmd_otr_trust(irc_t *irc, char **args);  /* TODO: void cmd_otr_affirm(irc_t *irc, char **args); */  void cmd_otr_fprints(irc_t *irc, char **args);  void cmd_otr_info(irc_t *irc, char **args); @@ -61,7 +60,8 @@ void cmd_otr_policy(irc_t *irc, char **args);  const command_t otr_commands[] = {  	{ "abort",    1, &cmd_otr_abort,    0 },  	{ "request",  1, &cmd_otr_request,  0 }, -	{ "auth",     2, &cmd_otr_auth,     0 }, +	{ "smp",      2, &cmd_otr_smp,      0 }, +	{ "trust",    6, &cmd_otr_trust,    0 },  	{ "fprints",  0, &cmd_otr_fprints,  0 },  	{ "info",     1, &cmd_otr_info,     0 },  	{ "policy",   0, &cmd_otr_policy,   0 }, @@ -96,12 +96,22 @@ void no_keygen(gpointer w, void *data);  struct im_connection *check_imc(void *opdata, const char *accountname,  	const char *protocol); -/* determine the nick for a given handle/protocol pair */ +/* determine the nick for a given handle/protocol pair +   returns "handle/protocol" if not found */  const char *peernick(irc_t *irc, const char *handle, const char *protocol); +/* determine the user_t for a given handle/protocol pair +   returns NULL if not found */ +user_t *peeruser(irc_t *irc, const char *handle, const char *protocol); +  /* handle SMP TLVs from a received message */  void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs); +/* update op/voice flag of given user according to encryption state and settings +   returns 0 if neither op_buddies nor voice_buddies is set to "encrypted", +   i.e. msgstate should be announced seperately */ +int otr_update_modeflags(irc_t *irc, user_t *u); +  /* show the list of fingerprints associated with a given context */  void show_fingerprints(irc_t *irc, ConnContext *ctx); @@ -238,8 +248,15 @@ char *otr_handle_message(struct im_connection *ic, const char *handle, const cha  	char *colormsg;      if(!g_mutex_trylock(ic->irc->otr_mutex)) { -    	/* TODO: queue msgs received during keygen for later */ -		irc_usermsg(ic->irc, "msg from %s during keygen - dropped", +    	user_t *u = user_findhandle(ic, handle); +    	 +    	/* fallback for non-otr clients */ +    	if(u && !u->encrypted) { +    		return g_strdup(msg); +    	} +    	 +    	/* TODO: queue msgs received during keygen for later? */ +		irc_usermsg(ic->irc, "otr msg from %s during keygen - dropped",  			peernick(ic->irc, handle, ic->acc->prpl->name));  		return NULL;  	} @@ -282,14 +299,24 @@ char *otr_handle_message(struct im_connection *ic, const char *handle, const cha  int otr_send_message(struct im_connection *ic, const char *handle, const char *msg, int flags)  {	 -    int st; -    char *otrmsg = NULL; -    ConnContext *ctx = NULL; -     +	int st; +	char *otrmsg = NULL; +	ConnContext *ctx = NULL; +	      if(!g_mutex_trylock(ic->irc->otr_mutex)) { -    	irc_usermsg(ic->irc, "msg to %s during keygen - not sent", -    		peernick(ic->irc, handle, ic->acc->prpl->name)); -    	return 1; +		user_t *u = user_findhandle(ic, handle); +    	 +		/* Fallback for non-otr clients. +		   Yes, we must be very sure this doesn't send stuff in the clear where it +		   shouldn't... */ +		if(u && !u->encrypted) { +			return ic->acc->prpl->buddy_msg(ic, (char *)handle, (char *)msg, flags); +		} +		 +		/* otherwise refuse to send */ +		irc_usermsg(ic->irc, "otr msg to %s not sent during keygen", +			peernick(ic->irc, handle, ic->acc->prpl->name)); +		return 1;      }  	st = otrl_message_sending(ic->irc->otr_us, &global.otr_ops, ic, @@ -413,14 +440,17 @@ void op_inject_message(void *opdata, const char *accountname,  }  int op_display_otr_message(void *opdata, const char *accountname, -	const char *protocol, const char *username, const char *msg) +	const char *protocol, const char *username, const char *message)  {  	struct im_connection *ic = check_imc(opdata, accountname, protocol); +	char *msg = g_strdup(message); -	log_message(LOGLVL_DEBUG, "op_display_otr_message '%s' '%s' '%s' '%s'", accountname, protocol, username, msg); +	log_message(LOGLVL_DEBUG, "op_display_otr_message '%s' '%s' '%s' '%s'", accountname, protocol, username, message); -	irc_usermsg(ic->irc, "%s", msg); +	strip_html(msg); +	irc_usermsg(ic->irc, "otr: %s", msg); +	g_free(msg);  	return 0;  } @@ -451,51 +481,84 @@ void op_gone_secure(void *opdata, ConnContext *context)  {  	struct im_connection *ic =  		check_imc(opdata, context->accountname, context->protocol); +	user_t *u;  	log_message(LOGLVL_DEBUG, "op_gone_secure '%s' '%s' '%s'", context->accountname, context->protocol, context->username); -	irc_usermsg(ic->irc, "conversation with %s is now off the record", -		peernick(ic->irc, context->username, context->protocol)); +	u = peeruser(ic->irc, context->username, context->protocol); +	if(!u) { +		log_message(LOGLVL_ERROR, +			"BUG: otr.c: op_gone_secure: user_t for %s/%s not found!", +			context->username, context->protocol); +		return; +	} +	if(context->active_fingerprint->trust[0]) +		u->encrypted = 2; +	else +		u->encrypted = 1; +	if(!otr_update_modeflags(ic->irc, u)) +		irc_usermsg(ic->irc, "conversation with %s is now off the record", u->nick);  }  void op_gone_insecure(void *opdata, ConnContext *context)  {  	struct im_connection *ic =  		check_imc(opdata, context->accountname, context->protocol); +	user_t *u;  	log_message(LOGLVL_DEBUG, "op_gone_insecure '%s' '%s' '%s'", context->accountname, context->protocol, context->username); -	irc_usermsg(ic->irc, "conversation with %s is now in the clear", -		peernick(ic->irc, context->username, context->protocol)); +	u = peeruser(ic->irc, context->username, context->protocol); +	if(!u) { +		log_message(LOGLVL_ERROR, +			"BUG: otr.c: op_gone_insecure: user_t for %s/%s not found!", +			context->username, context->protocol); +		return; +	} +	u->encrypted = 0; +	if(!otr_update_modeflags(ic->irc, u)) +		irc_usermsg(ic->irc, "conversation with %s is now in the clear", u->nick);  }  void op_still_secure(void *opdata, ConnContext *context, int is_reply)  {  	struct im_connection *ic =  		check_imc(opdata, context->accountname, context->protocol); +	user_t *u;  	log_message(LOGLVL_DEBUG, "op_still_secure '%s' '%s' '%s' is_reply=%d",  		context->accountname, context->protocol, context->username, is_reply); -	irc_usermsg(ic->irc, "otr connection with %s has been refreshed", -		peernick(ic->irc, context->username, context->protocol)); +	u = peeruser(ic->irc, context->username, context->protocol); +	if(!u) { +		log_message(LOGLVL_ERROR, +			"BUG: otr.c: op_still_secure: user_t for %s/%s not found!", +			context->username, context->protocol); +		return; +	} +	if(context->active_fingerprint->trust[0]) +		u->encrypted = 2; +	else +		u->encrypted = 1; +	if(!otr_update_modeflags(ic->irc, u)) +		irc_usermsg(ic->irc, "otr connection with %s has been refreshed", u->nick);  }  void op_log_message(void *opdata, const char *message)  { -	log_message(LOGLVL_INFO, "%s", message); +	char *msg = g_strdup(message); +	 +	strip_html(msg); +	log_message(LOGLVL_INFO, "otr: %s", msg); +	g_free(msg);  }  int op_max_message_size(void *opdata, ConnContext *context)  { -	/* TODO: make max_message_size a property of the prpl. -	         the values here are taken from the libotr UPGRADING file */ -	if(!strcmp(context->protocol, "msn")) -		return 1409; -	if(!strcmp(context->protocol, "yahoo")) -		return 832; -	if(!strcmp(context->protocol, "oscar")) -		return 2343; +	struct im_connection *ic = +		check_imc(opdata, context->accountname, context->protocol); + +	return ic->acc->prpl->mms;  }  const char *op_account_name(void *opdata, const char *account, const char *protocol) @@ -541,7 +604,7 @@ void cmd_otr_request(irc_t *irc, char **args)  	imc_buddy_msg(u->ic, u->handle, "?OTR?", 0);  } -void cmd_otr_auth(irc_t *irc, char **args) +void cmd_otr_smp(irc_t *irc, char **args)  {  	user_t *u;  	ConnContext *ctx; @@ -588,6 +651,80 @@ void cmd_otr_auth(irc_t *irc, char **args)  	}  } +int hexval(char a) +{ +	int x=tolower(a); +	 +	if(x>='a' && x<='f') +		x = x - 'a' + 10; +	else if(x>='0' && x<='9') +		x = x - '0'; +	else +		return -1; +	 +	return x; +} + +void cmd_otr_trust(irc_t *irc, char **args) +{ +	user_t *u; +	ConnContext *ctx; +	unsigned char raw[20]; +	Fingerprint *fp; +	int i,j; +	 +	u = user_find(irc, args[1]); +	if(!u || !u->ic) { +		irc_usermsg(irc, "%s: unknown user", args[1]); +		return; +	} +	 +	ctx = otrl_context_find(irc->otr_us, u->handle, +		u->ic->acc->user, u->ic->acc->prpl->name, 0, NULL, NULL, NULL); +	if(!ctx) { +		irc_usermsg(irc, "%s: no otr context with user", args[1]); +		return; +	} +	 +	/* convert given fingerprint to raw representation */ +	for(i=0; i<5; i++) { +		for(j=0; j<4; j++) { +			char *p = args[2+i]+(2*j); +			char *q = p+1; +			int x, y; +			 +			if(!*p || !*q) { +				irc_usermsg(irc, "failed: truncated fingerprint block %d", i+1); +				return; +			} +			 +			x = hexval(*p); +			y = hexval(*q); +			if(x<0) { +				irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+1, i+1); +				return; +			} +			if(y<0) { +				irc_usermsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+2, i+1); +				return; +			} + +			raw[i*4+j] = x*16 + y; +		} +	} +	fp = otrl_context_find_fingerprint(ctx, raw, 0, NULL); +	if(!fp) { +		irc_usermsg(irc, "failed: no such fingerprint for %s", args[1]); +	} else { +		char *trust = args[7] ? args[7] : "affirmed"; +		otrl_context_set_trust(fp, trust); +		irc_usermsg(irc, "fingerprint match, trust set to \"%s\"", trust); +		if(u->encrypted) +			u->encrypted = 2; +		otr_update_modeflags(irc, u); +	} +} +  void cmd_otr_fprints(irc_t *irc, char **args)  {  	if(args[1]) { @@ -648,7 +785,7 @@ void cmd_otr_info(irc_t *irc, char **args)  	ctx = otrl_context_find(irc->otr_us, u->handle,  		u->ic->acc->user, u->ic->acc->prpl->name, 0, NULL, NULL, NULL);  	if(!ctx) { -		irc_usermsg(irc, "no otr info on %s", args[1]); +		irc_usermsg(irc, "no otr context with %s", args[1]);  		return;  	} @@ -671,18 +808,21 @@ void cmd_otr_info(irc_t *irc, char **args)  		ctx->username, ctx->protocol, ctx->accountname, ctx->protocol);  	irc_usermsg(irc, "  otr offer status: %s", offer_status);  	irc_usermsg(irc, "  connection state: %s", message_state); -	irc_usermsg(irc, "  protocol version: %d", ctx->protocol_version); -	fp = ctx->active_fingerprint; -	if(!fp) { -		irc_usermsg(irc, "  active f'print:   none"); -	} else { -		otrl_privkey_hash_to_human(human, fp->fingerprint); -		if(!fp->trust || fp->trust[0] == '\0') { -			trust="untrusted"; +	 +	if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { +		irc_usermsg(irc, "  protocol version: %d", ctx->protocol_version); +		fp = ctx->active_fingerprint; +		if(!fp) { +			irc_usermsg(irc, "  active f'print:   none?");  		} else { -			trust=fp->trust; +			otrl_privkey_hash_to_human(human, fp->fingerprint); +			if(!fp->trust || fp->trust[0] == '\0') { +				trust="untrusted"; +			} else { +				trust=fp->trust; +			} +			irc_usermsg(irc, "  active f'print:   %s (%s)", human, trust);  		} -		irc_usermsg(irc, "  active f'print:   %s (%s)", human, trust);  	}  } @@ -808,12 +948,10 @@ struct im_connection *check_imc(void *opdata, const char *accountname,  	return ic;  } -const char *peernick(irc_t *irc, const char *handle, const char *protocol) +user_t *peeruser(irc_t *irc, const char *handle, const char *protocol)  {  	user_t *u; -	static char fallback[512]; -	g_snprintf(fallback, 511, "%s/%s", handle, protocol);  	for(u=irc->users; u; u=u->next) {  		struct prpl *prpl;  		if(!u->ic || !u->handle) @@ -821,11 +959,55 @@ const char *peernick(irc_t *irc, const char *handle, const char *protocol)  		prpl = u->ic->acc->prpl;  		if(strcmp(prpl->name, protocol) == 0  			&& prpl->handle_cmp(u->handle, handle) == 0) { -			return u->nick; +			return u;  		}  	} -	return fallback; +	return NULL; +} + +const char *peernick(irc_t *irc, const char *handle, const char *protocol) +{ +	static char fallback[512]; +	 +	user_t *u = peeruser(irc, handle, protocol); +	if(u) { +		return u->nick; +	} else { +		g_snprintf(fallback, 511, "%s/%s", handle, protocol); +		return fallback; +	} +} + +int otr_update_modeflags(irc_t *irc, user_t *u) +{ +	char *vo = set_getstr(&irc->set, "voice_buddies"); +	char *oo = set_getstr(&irc->set, "op_buddies"); +	char eflag=0, tflag=0; +	int e = u->encrypted; +	int t = (u->encrypted > 1); +	 +	if(!strcmp(vo, "encrypted")) +		eflag='v'; +	else if(!strcmp(oo, "encrypted")) +		eflag='o'; +	if(!strcmp(vo, "trusted")) +		tflag='v'; +	else if(!strcmp(oo, "trusted")) +		tflag='o'; +	 +	if(!eflag) +		return 0; +	 +	if(tflag) { +		irc_write( irc, ":%s!%s@%s MODE %s %c%c%c%c %s %s", irc->mynick, irc->mynick, irc->myhost, +			irc->channel, e?'+':'-', eflag, t?'+':'-', tflag, u->nick, u->nick ); +	} else { +		irc_write( irc, ":%s!%s@%s MODE %s %c%c %s", irc->mynick, irc->mynick, irc->myhost, +			irc->channel, e?'+':'-', eflag, u->nick ); +	} +		 +	return 1;  }  void show_fingerprints(irc_t *irc, ConnContext *ctx) @@ -965,9 +1147,13 @@ void no_keygen(gpointer w, void *data)  {  	account_t *acc = (account_t *)data; -	/* TODO: remember that we didn't want a key? */  	irc_usermsg(acc->irc, "proceeding without key, otr inoperable on %s/%s",  		acc->user, acc->prpl->name); +	/* TODO:  +	irc_usermsg(acc->irc, "setting otr policy for %s/%s to \"never\"", +		acc->user, acc->prpl->name); +	set_setstr(acc->set, "otr_policy", "never"); +	*/  } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index 243ed7fd..dac18bae 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -510,6 +510,7 @@ void jabber_initmodule()  	struct prpl *ret = g_new0( struct prpl, 1 );  	ret->name = "jabber"; +    ret->mms = 0;                        /* no limit */  	ret->login = jabber_login;  	ret->init = jabber_init;  	ret->logout = jabber_logout; diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index a2e8519a..335ae894 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -371,6 +371,7 @@ void msn_initmodule()  	struct prpl *ret = g_new0(struct prpl, 1);  	ret->name = "msn"; +    ret->mms = 1409;         /* this guess taken from libotr UPGRADING file */  	ret->login = msn_login;  	ret->init = msn_init;  	ret->logout = msn_logout; diff --git a/protocols/nogaim.c b/protocols/nogaim.c index d8bfad14..138e2ce1 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -602,10 +602,9 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  	/* else waste_any_state_information_for_now(); */  	/* LISPy... */ -	if( ( set_getbool( &ic->irc->set, "away_devoice" ) ) &&		/* Don't do a thing when user doesn't want it */ -	    ( u->online ) &&						/* Don't touch offline people */ -	    ( ( ( u->online != oo ) && !u->away ) ||			/* Voice joining people */ -	      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )		/* (De)voice people changing state */ +	if( ( u->online ) &&						/* Don't touch offline people */ +	    ( ( ( u->online != oo ) && !u->away ) ||			/* Do joining people */ +	      ( ( u->online == oo ) && ( oa == !u->away ) ) ) )		/* Do people changing state */  	{  		char *from; @@ -618,8 +617,14 @@ void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags,  			from = g_strdup_printf( "%s!%s@%s", ic->irc->mynick, ic->irc->mynick,  			                                    ic->irc->myhost );  		} -		irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, -		                                          u->away?'-':'+', u->nick ); +		if(!strcmp(set_getstr(&ic->irc->set, "voice_buddies"), "notaway")) { +			irc_write( ic->irc, ":%s MODE %s %cv %s", from, ic->irc->channel, +		 	                                         u->away?'-':'+', u->nick ); +		} +		if(!strcmp(set_getstr(&ic->irc->set, "op_buddies"), "notaway")) { +			irc_write( ic->irc, ":%s MODE %s %co %s", from, ic->irc->channel, +		 	                                         u->away?'-':'+', u->nick ); +		}  		g_free( from );  	}  } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index 7d391edd..3eb640e2 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -135,6 +135,10 @@ struct prpl {  	/* You should set this to the name of your protocol.  	 * - The user sees this name ie. when imcb_log() is used. */  	const char *name; +    /* Maximum Message Size of this protocol. +     * - Introduced for OTR, in order to fragment large protocol messages. +     * - 0 means "unlimited". */ +    unsigned int mms;  	/* Added this one to be able to add per-account settings, don't think  	 * it should be used for anything else. You are supposed to use the diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 30ad4b68..9167f6a3 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -2602,6 +2602,7 @@ void oscar_initmodule()  {  	struct prpl *ret = g_new0(struct prpl, 1);  	ret->name = "oscar"; +    ret->mms = 2343;       /* this guess taken from libotr UPGRADING file */  	ret->away_states = oscar_away_states;  	ret->init = oscar_init;  	ret->login = oscar_login; diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 9f9ffcf7..52747bb4 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -353,6 +353,7 @@ void byahoo_initmodule( )  {  	struct prpl *ret = g_new0(struct prpl, 1);  	ret->name = "yahoo"; +    ret->mms = 832;           /* this guess taken from libotr UPGRADING file */  	ret->init = byahoo_init;  	ret->login = byahoo_login; @@ -208,28 +208,147 @@ char *set_eval_to_char( set_t *set, char *value )  	return s;  } -char *set_eval_ops( set_t *set, char *value ) +char *set_eval_op_root( set_t *set, char *value )  {  	irc_t *irc = set->data; +	char *ret = set_eval_bool(set, value); +	int b = bool2int(ret); -	if( g_strcasecmp( value, "user" ) == 0 ) -		irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, -		                                              irc->channel, "+o-o", irc->nick, irc->mynick ); -	else if( g_strcasecmp( value, "root" ) == 0 ) -		irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, -		                                              irc->channel, "-o+o", irc->nick, irc->mynick ); -	else if( g_strcasecmp( value, "both" ) == 0 ) -		irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, -		                                              irc->channel, "+oo", irc->nick, irc->mynick ); -	else if( g_strcasecmp( value, "none" ) == 0 ) -		irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost, -		                                              irc->channel, "-oo", irc->nick, irc->mynick ); +	irc_write( irc, ":%s!%s@%s MODE %s %s %s", irc->mynick, irc->mynick, irc->myhost, +	                                           irc->channel, b?"+o":"-o", irc->mynick ); +	return ret; +} + +char *set_eval_op_user( set_t *set, char *value ) +{ +	irc_t *irc = set->data; +	char *ret = set_eval_bool(set, value); +	int b = bool2int(ret); +	 +	irc_write( irc, ":%s!%s@%s MODE %s %s %s", irc->mynick, irc->mynick, irc->myhost, +	                                           irc->channel, b?"+o":"-o", irc->nick ); +	return ret; +} + +/* generalized version of set_eval_op/voice_buddies */ +char *set_eval_mode_buddies( set_t *set, char *value, char modeflag ) +{ +	irc_t *irc = set->data; +	char op[64], deop[64]; +	int nop=0, ndeop=0; +	user_t *u; +	int mode; +	 +	if(!strcmp(value, "false")) +		mode=0; +	else if(!strcmp(value, "encrypted")) +		mode=1; +	else if(!strcmp(value, "trusted")) +		mode=2; +	else if(!strcmp(value, "notaway")) +		mode=3;  	else  		return NULL; +	/* sorry for calling them op/deop - too lazy for search+replace :P */ +	op[0]='\0'; +	deop[0]='\0'; +	for(u=irc->users; u; u=u->next) { +		/* we're only concerned with online buddies */ +		if(!u->ic || !u->online) +			continue; + +		/* just in case... */ +		if(strlen(u->nick) >= 64) +			continue; +		 +		/* dump out ops/deops when the corresponding name list fills up */ +		if(strlen(op)+strlen(u->nick)+2 > 64) { +			char *flags = g_strnfill(nop, modeflag); +			irc_write( irc, ":%s!%s@%s MODE %s +%s%s", irc->mynick, irc->mynick, irc->myhost, +		                                               irc->channel, flags, op ); +		    op[0]='\0'; +		    g_free(flags); +		} +		if(strlen(deop)+strlen(u->nick)+2 > 64) { +			char *flags = g_strnfill(ndeop, modeflag); +			irc_write( irc, ":%s!%s@%s MODE %s -%s%s", irc->mynick, irc->mynick, irc->myhost, +		                                               irc->channel, flags, deop ); +		    deop[0]='\0'; +		    g_free(flags); +		} +		 +		switch(mode) { +		/* "false" */ +		case 0: +			g_strlcat(deop, " ", 64); +			g_strlcat(deop, u->nick, 64); +			ndeop++; +			break; +		/* "encrypted" */ +		case 1: +			if(u->encrypted) { +				g_strlcat(op, " ", 64); +				g_strlcat(op, u->nick, 64); +				nop++; +			} else { +				g_strlcat(deop, " ", 64); +				g_strlcat(deop, u->nick, 64); +				ndeop++; +			} +			break; +		/* "trusted" */ +		case 2: +			if(u->encrypted > 1) { +				g_strlcat(op, " ", 64); +				g_strlcat(op, u->nick, 64); +				nop++; +			} else { +				g_strlcat(deop, " ", 64); +				g_strlcat(deop, u->nick, 64); +				ndeop++; +			} +			break; +		/* "notaway" */ +		case 3: +			if(u->away) { +				g_strlcat(deop, " ", 64); +				g_strlcat(deop, u->nick, 64); +				ndeop++; +			} else { +				g_strlcat(op, " ", 64); +				g_strlcat(op, u->nick, 64); +				nop++; +			} +		} +	} +	/* dump anything left in op/deop lists */ +	if(*op) { +		char *flags = g_strnfill(nop, modeflag); +		irc_write( irc, ":%s!%s@%s MODE %s +%s%s", irc->mynick, irc->mynick, irc->myhost, +		                                               irc->channel, flags, op ); +		g_free(flags); +	} +	if(*deop) { +		char *flags = g_strnfill(ndeop, modeflag); +		irc_write( irc, ":%s!%s@%s MODE %s -%s%s", irc->mynick, irc->mynick, irc->myhost, +	                                               irc->channel, flags, deop ); +		g_free(flags); +	} +	  	return value;  } +char *set_eval_op_buddies( set_t *set, char *value ) +{ +	return set_eval_mode_buddies(set, value, 'o'); +} + +char *set_eval_voice_buddies( set_t *set, char *value ) +{ +	return set_eval_mode_buddies(set, value, 'v'); +} +  char *set_eval_charset( set_t *set, char *value )  {  	GIConv cd; @@ -95,7 +95,10 @@ char *set_eval_bool( set_t *set, char *value );  /* Some not very generic evaluators that really shouldn't be here... */  char *set_eval_to_char( set_t *set, char *value ); -char *set_eval_ops( set_t *set, char *value ); +char *set_eval_op_root( set_t *set, char *value ); +char *set_eval_op_user( set_t *set, char *value ); +char *set_eval_op_buddies( set_t *set, char *value ); +char *set_eval_voice_buddies( set_t *set, char *value );  char *set_eval_charset( set_t *set, char *value );  #endif /* __SET_H__ */ @@ -36,6 +36,7 @@ typedef struct __USER  	char is_private;  	char online; +	char encrypted;  	char *handle;  	char *group; | 
