diff options
author | Sven Moritz Hallberg <sm@khjk.org> | 2008-02-09 18:58:13 +0100 |
---|---|---|
committer | Sven Moritz Hallberg <sm@khjk.org> | 2008-02-09 18:58:13 +0100 |
commit | 5a71d9c5b14aa749b532666b71b25ce2afcdc5bb (patch) | |
tree | 5e6ec25cb526a9940ba6ba4c63dc590a8991679f | |
parent | a13855a57daae6eba05c9600b69f640c2949e944 (diff) |
- add support for setting ops/voice according to OTR msgstate
- add 'otr trust' user command
- support non-otr messages during keygen
- run otr messages through strip_html
- interpret <b> and <i> tags in html messages
- record max message size in prpl
- add 'encrypted' flag to user_t
- cosmetics
-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; |