diff options
author | Indent <please@skip.me> | 2015-02-19 02:47:20 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2015-02-20 19:50:54 -0300 |
commit | 5ebff60479fc7a9f7f50ac03b124c91d4e6ebe11 (patch) | |
tree | 9fc0d50cb1f4bc9768d9f00de94eafd876bb55b0 | |
parent | af359b4316f9d392c6b752495a1b2ed631576ed8 (diff) |
Reindent everything to K&R style with tabs
Used uncrustify, with the configuration file in ./doc/uncrustify.cfg
Commit author set to "Indent <please@skip.me>" so that it's easier to
skip while doing git blame.
169 files changed, 25901 insertions, 25127 deletions
@@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -33,42 +33,39 @@ #include <stdio.h> #include <errno.h> -static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ); +static gboolean bitlbee_io_new_client(gpointer data, gint fd, b_input_condition condition); -static gboolean try_listen( struct addrinfo *res ) +static gboolean try_listen(struct addrinfo *res) { int i; - - global.listen_socket = socket( res->ai_family, res->ai_socktype, res->ai_protocol ); - if( global.listen_socket < 0 ) - { - log_error( "socket" ); + + global.listen_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (global.listen_socket < 0) { + log_error("socket"); return FALSE; } -#ifdef IPV6_V6ONLY - if( res->ai_family == AF_INET6 ) - { +#ifdef IPV6_V6ONLY + if (res->ai_family == AF_INET6) { i = 0; - setsockopt( global.listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, - (char *) &i, sizeof( i ) ); + setsockopt(global.listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &i, sizeof(i)); } #endif /* TIME_WAIT (?) sucks.. */ i = 1; - setsockopt( global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) ); + setsockopt(global.listen_socket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); - i = bind( global.listen_socket, res->ai_addr, res->ai_addrlen ); - if( i == -1 ) - { - closesocket( global.listen_socket ); + i = bind(global.listen_socket, res->ai_addr, res->ai_addrlen); + if (i == -1) { + closesocket(global.listen_socket); global.listen_socket = -1; - - log_error( "bind" ); + + log_error("bind"); return FALSE; } - + return TRUE; } @@ -77,295 +74,273 @@ int bitlbee_daemon_init() struct addrinfo *res, hints, *addrinfo_bind; int i; FILE *fp; - - log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); - log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); - - memset( &hints, 0, sizeof( hints ) ); + + log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE); + log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE); + + memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE #ifdef AI_ADDRCONFIG - /* Disabled as it may be doing more harm than good: this flag - ignores IPv6 addresses on lo (which seems reasonable), but - the result is that some clients (including irssi) try to - connect to ::1 and fail. - | AI_ADDRCONFIG */ + /* Disabled as it may be doing more harm than good: this flag + ignores IPv6 addresses on lo (which seems reasonable), but + the result is that some clients (including irssi) try to + connect to ::1 and fail. + | AI_ADDRCONFIG */ #endif ; - i = getaddrinfo( global.conf->iface_in, global.conf->port, &hints, &addrinfo_bind ); - if( i ) - { - log_message( LOGLVL_ERROR, "Couldn't parse address `%s': %s", - global.conf->iface_in, gai_strerror(i) ); + i = getaddrinfo(global.conf->iface_in, global.conf->port, &hints, &addrinfo_bind); + if (i) { + log_message(LOGLVL_ERROR, "Couldn't parse address `%s': %s", + global.conf->iface_in, gai_strerror(i)); return -1; } global.listen_socket = -1; - + /* Try IPv6 first (which will become an IPv6+IPv4 socket). */ - for( res = addrinfo_bind; res; res = res->ai_next ) - if( res->ai_family == AF_INET6 && try_listen( res ) ) + for (res = addrinfo_bind; res; res = res->ai_next) { + if (res->ai_family == AF_INET6 && try_listen(res)) { break; - + } + } + /* The rest (so IPv4, I guess). */ - if( res == NULL ) - for( res = addrinfo_bind; res; res = res->ai_next ) - if( res->ai_family != AF_INET6 && try_listen( res ) ) + if (res == NULL) { + for (res = addrinfo_bind; res; res = res->ai_next) { + if (res->ai_family != AF_INET6 && try_listen(res)) { break; - - freeaddrinfo( addrinfo_bind ); - - i = listen( global.listen_socket, 10 ); - if( i == -1 ) - { - log_error( "listen" ); - return( -1 ); + } + } + } + + freeaddrinfo(addrinfo_bind); + + i = listen(global.listen_socket, 10); + if (i == -1) { + log_error("listen"); + return(-1); } - - global.listen_watch_source_id = b_input_add( global.listen_socket, B_EV_IO_READ, bitlbee_io_new_client, NULL ); - - if( !global.conf->nofork ) - { + + global.listen_watch_source_id = b_input_add(global.listen_socket, B_EV_IO_READ, bitlbee_io_new_client, NULL); + + if (!global.conf->nofork) { i = fork(); - if( i == -1 ) - { - log_error( "fork" ); - return( -1 ); + if (i == -1) { + log_error("fork"); + return(-1); + } else if (i != 0) { + exit(0); } - else if( i != 0 ) - exit( 0 ); - + setsid(); - i = chdir( "/" ); + i = chdir("/"); /* Don't use i, just make gcc happy. :-/ */ - - if( getenv( "_BITLBEE_RESTART_STATE" ) == NULL ) - for( i = 0; i < 3; i ++ ) - if( close( i ) == 0 ) - { + + if (getenv("_BITLBEE_RESTART_STATE") == NULL) { + for (i = 0; i < 3; i++) { + if (close(i) == 0) { /* Keep something bogus on those fd's just in case. */ - open( "/dev/null", O_WRONLY ); + open("/dev/null", O_WRONLY); } + } + } + } + + if (global.conf->runmode == RUNMODE_FORKDAEMON) { + ipc_master_load_state(getenv("_BITLBEE_RESTART_STATE")); } - - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - ipc_master_load_state( getenv( "_BITLBEE_RESTART_STATE" ) ); - if( global.conf->runmode == RUNMODE_DAEMON || global.conf->runmode == RUNMODE_FORKDAEMON ) + if (global.conf->runmode == RUNMODE_DAEMON || global.conf->runmode == RUNMODE_FORKDAEMON) { ipc_master_listen_socket(); - - if( ( fp = fopen( global.conf->pidfile, "w" ) ) ) - { - fprintf( fp, "%d\n", (int) getpid() ); - fclose( fp ); } - else - { - log_message( LOGLVL_WARNING, "Warning: Couldn't write PID to `%s'", global.conf->pidfile ); + + if ((fp = fopen(global.conf->pidfile, "w"))) { + fprintf(fp, "%d\n", (int) getpid()); + fclose(fp); + } else { + log_message(LOGLVL_WARNING, "Warning: Couldn't write PID to `%s'", global.conf->pidfile); } - - if( !global.conf->nofork ) - { - log_link( LOGLVL_ERROR, LOGOUTPUT_SYSLOG ); - log_link( LOGLVL_WARNING, LOGOUTPUT_SYSLOG ); + + if (!global.conf->nofork) { + log_link(LOGLVL_ERROR, LOGOUTPUT_SYSLOG); + log_link(LOGLVL_WARNING, LOGOUTPUT_SYSLOG); } - - return( 0 ); + + return(0); } - + int bitlbee_inetd_init() { - if( !irc_new( 0 ) ) - return( 1 ); - - return( 0 ); + if (!irc_new(0)) { + return(1); + } + + return(0); } -gboolean bitlbee_io_current_client_read( gpointer data, gint fd, b_input_condition cond ) +gboolean bitlbee_io_current_client_read(gpointer data, gint fd, b_input_condition cond) { irc_t *irc = data; char line[513]; int st; - - st = read( irc->fd, line, sizeof( line ) - 1 ); - if( st == 0 ) - { - irc_abort( irc, 1, "Connection reset by peer" ); + + st = read(irc->fd, line, sizeof(line) - 1); + if (st == 0) { + irc_abort(irc, 1, "Connection reset by peer"); return FALSE; - } - else if( st < 0 ) - { - if( sockerr_again() ) - { + } else if (st < 0) { + if (sockerr_again()) { return TRUE; - } - else - { - irc_abort( irc, 1, "Read error: %s", strerror( errno ) ); + } else { + irc_abort(irc, 1, "Read error: %s", strerror(errno)); return FALSE; } } - + line[st] = '\0'; - if( irc->readbuffer == NULL ) - { - irc->readbuffer = g_strdup( line ); - } - else - { - irc->readbuffer = g_renew( char, irc->readbuffer, strlen( irc->readbuffer ) + strlen ( line ) + 1 ); - strcpy( ( irc->readbuffer + strlen( irc->readbuffer ) ), line ); + if (irc->readbuffer == NULL) { + irc->readbuffer = g_strdup(line); + } else { + irc->readbuffer = g_renew(char, irc->readbuffer, strlen(irc->readbuffer) + strlen(line) + 1); + strcpy((irc->readbuffer + strlen(irc->readbuffer)), line); } - - irc_process( irc ); - + + irc_process(irc); + /* Normally, irc_process() shouldn't call irc_free() but irc_abort(). Just in case: */ - if( !g_slist_find( irc_connection_list, irc ) ) - { - log_message( LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", fd ); + if (!g_slist_find(irc_connection_list, irc)) { + log_message(LOGLVL_WARNING, "Abnormal termination of connection with fd %d.", fd); return FALSE; - } - + } + /* Very naughty, go read the RFCs! >:) */ - if( irc->readbuffer && ( strlen( irc->readbuffer ) > 1024 ) ) - { - irc_abort( irc, 0, "Maximum line length exceeded" ); + if (irc->readbuffer && (strlen(irc->readbuffer) > 1024)) { + irc_abort(irc, 0, "Maximum line length exceeded"); return FALSE; } - + return TRUE; } -gboolean bitlbee_io_current_client_write( gpointer data, gint fd, b_input_condition cond ) +gboolean bitlbee_io_current_client_write(gpointer data, gint fd, b_input_condition cond) { irc_t *irc = data; int st, size; char *temp; - if( irc->sendbuffer == NULL ) - return FALSE; - - size = strlen( irc->sendbuffer ); - st = write( irc->fd, irc->sendbuffer, size ); - - if( st == 0 || ( st < 0 && !sockerr_again() ) ) - { - irc_abort( irc, 1, "Write error: %s", strerror( errno ) ); + if (irc->sendbuffer == NULL) { return FALSE; } - else if( st < 0 ) /* && sockerr_again() */ - { + + size = strlen(irc->sendbuffer); + st = write(irc->fd, irc->sendbuffer, size); + + if (st == 0 || (st < 0 && !sockerr_again())) { + irc_abort(irc, 1, "Write error: %s", strerror(errno)); + return FALSE; + } else if (st < 0) { /* && sockerr_again() */ return TRUE; } - - if( st == size ) - { - g_free( irc->sendbuffer ); + + if (st == size) { + g_free(irc->sendbuffer); irc->sendbuffer = NULL; irc->w_watch_source_id = 0; - + return FALSE; - } - else - { - temp = g_strdup( irc->sendbuffer + st ); - g_free( irc->sendbuffer ); + } else { + temp = g_strdup(irc->sendbuffer + st); + g_free(irc->sendbuffer); irc->sendbuffer = temp; - + return TRUE; } } -static gboolean bitlbee_io_new_client( gpointer data, gint fd, b_input_condition condition ) +static gboolean bitlbee_io_new_client(gpointer data, gint fd, b_input_condition condition) { - socklen_t size = sizeof( struct sockaddr_in ); + socklen_t size = sizeof(struct sockaddr_in); struct sockaddr_in conn_info; - int new_socket = accept( global.listen_socket, (struct sockaddr *) &conn_info, &size ); - - if( new_socket == -1 ) - { - log_message( LOGLVL_WARNING, "Could not accept new connection: %s", strerror( errno ) ); + int new_socket = accept(global.listen_socket, (struct sockaddr *) &conn_info, &size); + + if (new_socket == -1) { + log_message(LOGLVL_WARNING, "Could not accept new connection: %s", strerror(errno)); return TRUE; } - - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { + + if (global.conf->runmode == RUNMODE_FORKDAEMON) { pid_t client_pid = 0; int fds[2]; - - if( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 ) - { - log_message( LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror( errno ) ); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) { + log_message(LOGLVL_WARNING, "Could not create IPC socket for client: %s", strerror(errno)); fds[0] = fds[1] = -1; } - - sock_make_nonblocking( fds[0] ); - sock_make_nonblocking( fds[1] ); - + + sock_make_nonblocking(fds[0]); + sock_make_nonblocking(fds[1]); + client_pid = fork(); - - if( client_pid > 0 && fds[0] != -1 ) - { + + if (client_pid > 0 && fds[0] != -1) { struct bitlbee_child *child; - + /* TODO: Stuff like this belongs in ipc.c. */ - child = g_new0( struct bitlbee_child, 1 ); + child = g_new0(struct bitlbee_child, 1); child->pid = client_pid; child->ipc_fd = fds[0]; - child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); + child->ipc_inpa = b_input_add(child->ipc_fd, B_EV_IO_READ, ipc_master_read, child); child->to_fd = -1; - child_list = g_slist_append( child_list, child ); - - log_message( LOGLVL_INFO, "Creating new subprocess with pid %d.", (int) client_pid ); - + child_list = g_slist_append(child_list, child); + + log_message(LOGLVL_INFO, "Creating new subprocess with pid %d.", (int) client_pid); + /* Close some things we don't need in the parent process. */ - close( new_socket ); - close( fds[1] ); - } - else if( client_pid == 0 ) - { + close(new_socket); + close(fds[1]); + } else if (client_pid == 0) { irc_t *irc; - + b_main_init(); - + /* Close the listening socket, we're a client. */ - close( global.listen_socket ); - b_event_remove( global.listen_watch_source_id ); - + close(global.listen_socket); + b_event_remove(global.listen_watch_source_id); + /* Make the connection. */ - irc = irc_new( new_socket ); - + irc = irc_new(new_socket); + /* We can store the IPC fd there now. */ global.listen_socket = fds[1]; - global.listen_watch_source_id = b_input_add( fds[1], B_EV_IO_READ, ipc_child_read, irc ); - - close( fds[0] ); - + global.listen_watch_source_id = b_input_add(fds[1], B_EV_IO_READ, ipc_child_read, irc); + + close(fds[0]); + ipc_master_free_all(); } + } else { + log_message(LOGLVL_INFO, "Creating new connection with fd %d.", new_socket); + irc_new(new_socket); } - else - { - log_message( LOGLVL_INFO, "Creating new connection with fd %d.", new_socket ); - irc_new( new_socket ); - } - + return TRUE; } -gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ) +gboolean bitlbee_shutdown(gpointer data, gint fd, b_input_condition cond) { /* Send the message here with now=TRUE to ensure it arrives */ - irc_write_all( TRUE, "ERROR :Closing link: BitlBee server shutting down" ); + irc_write_all(TRUE, "ERROR :Closing link: BitlBee server shutting down"); /* Try to save data for all active connections (if desired). */ - while( irc_connection_list != NULL ) - irc_abort( irc_connection_list->data, TRUE, NULL ); - + while (irc_connection_list != NULL) { + irc_abort(irc_connection_list->data, TRUE, NULL); + } + /* We'll only reach this point when not running in inetd mode: */ b_main_quit(); - + return FALSE; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -37,7 +37,7 @@ extern "C" { #define PACKAGE "BitlBee" #define BITLBEE_VERSION "3.2.2" #define VERSION BITLBEE_VERSION -#define BITLBEE_VER(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define BITLBEE_VER(a, b, c) (((a) << 16) + ((b) << 8) + (c)) #define BITLBEE_VERSION_CODE BITLBEE_VER(3, 2, 2) #define MAX_STRING 511 @@ -62,42 +62,42 @@ extern "C" { /* The following functions should not be used if we want to maintain Windows compatibility... */ #undef free -#define free __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ +#define free __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef malloc -#define malloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ +#define malloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef calloc -#define calloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ +#define calloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef realloc -#define realloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ +#define realloc __PLEASE_USE_THE_GLIB_MEMORY_ALLOCATION_SYSTEM__ #undef strdup -#define strdup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ +#define strdup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ #undef strndup -#define strndup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ +#define strndup __PLEASE_USE_THE_GLIB_STRDUP_FUNCTIONS_SYSTEM__ #undef snprintf -#define snprintf __PLEASE_USE_G_SNPRINTF__ +#define snprintf __PLEASE_USE_G_SNPRINTF__ #undef strcasecmp -#define strcasecmp __PLEASE_USE_G_STRCASECMP__ +#define strcasecmp __PLEASE_USE_G_STRCASECMP__ #undef strncasecmp -#define strncasecmp __PLEASE_USE_G_STRNCASECMP__ +#define strncasecmp __PLEASE_USE_G_STRNCASECMP__ /* And the following functions shouldn't be used anymore to keep compatibility with other event handling libs than GLib. */ #undef g_timeout_add -#define g_timeout_add __PLEASE_USE_B_TIMEOUT_ADD__ +#define g_timeout_add __PLEASE_USE_B_TIMEOUT_ADD__ #undef g_timeout_add_full -#define g_timeout_add_full __PLEASE_USE_B_TIMEOUT_ADD__ +#define g_timeout_add_full __PLEASE_USE_B_TIMEOUT_ADD__ #undef g_io_add_watch -#define g_io_add_watch __PLEASE_USE_B_INPUT_ADD__ +#define g_io_add_watch __PLEASE_USE_B_INPUT_ADD__ #undef g_io_add_watch_full -#define g_io_add_watch_full __PLEASE_USE_B_INPUT_ADD__ +#define g_io_add_watch_full __PLEASE_USE_B_INPUT_ADD__ #undef g_source_remove -#define g_source_remove __PLEASE_USE_B_EVENT_REMOVE__ +#define g_source_remove __PLEASE_USE_B_EVENT_REMOVE__ #undef g_source_remove_by_user_data -#define g_source_remove_by_user_data __PLEASE_USE_B_SOURCE_REMOVE_BY_USER_DATA__ +#define g_source_remove_by_user_data __PLEASE_USE_B_SOURCE_REMOVE_BY_USER_DATA__ #undef g_main_run -#define g_main_run __PLEASE_USE_B_MAIN_RUN__ +#define g_main_run __PLEASE_USE_B_MAIN_RUN__ #undef g_main_quit -#define g_main_quit __PLEASE_USE_B_MAIN_QUIT__ +#define g_main_quit __PLEASE_USE_B_MAIN_QUIT__ /* And now, because GLib folks think everyone loves typing ridiculously long function names ... no I don't or I'd write BitlBee in Java, ffs. */ @@ -110,7 +110,7 @@ extern "C" { #define G_GNUC_MALLOC #endif -#define _( x ) x +#define _(x) x #define ROOT_NICK "root" #define ROOT_CHAN "&bitlbee" @@ -159,20 +159,20 @@ typedef struct global { int restart; } global_t; -int bitlbee_daemon_init( void ); -int bitlbee_inetd_init( void ); +int bitlbee_daemon_init(void); +int bitlbee_inetd_init(void); -gboolean bitlbee_io_current_client_read( gpointer data, gint source, b_input_condition cond ); -gboolean bitlbee_io_current_client_write( gpointer data, gint source, b_input_condition cond ); +gboolean bitlbee_io_current_client_read(gpointer data, gint source, b_input_condition cond); +gboolean bitlbee_io_current_client_write(gpointer data, gint source, b_input_condition cond); -void root_command_string( irc_t *irc, char *command ); -void root_command( irc_t *irc, char *command[] ); -gboolean root_command_add( const char *command, int params, void (*func)(irc_t *, char **args), int flags ); -gboolean cmd_identify_finish( gpointer data, gint fd, b_input_condition cond ); -gboolean bitlbee_shutdown( gpointer data, gint fd, b_input_condition cond ); +void root_command_string(irc_t *irc, char *command); +void root_command(irc_t *irc, char *command[]); +gboolean root_command_add(const char *command, int params, void (*func)(irc_t *, char **args), int flags); +gboolean cmd_identify_finish(gpointer data, gint fd, b_input_condition cond); +gboolean bitlbee_shutdown(gpointer data, gint fd, b_input_condition cond); -char *set_eval_root_nick( set_t *set, char *new_nick ); -char *set_eval_control_channel( set_t *set, char *new_name ); +char *set_eval_root_nick(set_t *set, char *new_nick); +char *set_eval_control_channel(set_t *set, char *new_name); extern global_t global; @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -28,8 +28,7 @@ #include "bitlbee.h" -typedef struct command -{ +typedef struct command { char *command; int required_parameters; void (*execute)(irc_t *, char **args); @@ -38,11 +37,11 @@ typedef struct command extern command_t root_commands[]; -#define IRC_CMD_PRE_LOGIN 1 -#define IRC_CMD_LOGGED_IN 2 -#define IRC_CMD_OPER_ONLY 4 -#define IRC_CMD_TO_MASTER 8 +#define IRC_CMD_PRE_LOGIN 1 +#define IRC_CMD_LOGGED_IN 2 +#define IRC_CMD_OPER_ONLY 4 +#define IRC_CMD_TO_MASTER 8 -#define IPC_CMD_TO_CHILDREN 1 +#define IPC_CMD_TO_CHILDREN 1 #endif @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2005 Wilmer van der Gaast and others * @@ -35,30 +35,30 @@ #include "proxy.h" -static int conf_loadini( conf_t *conf, char *file ); +static int conf_loadini(conf_t *conf, char *file); -conf_t *conf_load( int argc, char *argv[] ) +conf_t *conf_load(int argc, char *argv[]) { conf_t *conf; int opt, i, config_missing = 0; - - conf = g_new0( conf_t, 1 ); - + + conf = g_new0(conf_t, 1); + conf->iface_in = NULL; conf->iface_out = NULL; - conf->port = g_strdup( "6667" ); + conf->port = g_strdup("6667"); conf->nofork = 0; conf->verbose = 0; - conf->primary_storage = g_strdup( "xml" ); - conf->migrate_storage = g_strsplit( "text", ",", -1 ); + conf->primary_storage = g_strdup("xml"); + conf->migrate_storage = g_strsplit("text", ",", -1); conf->runmode = RUNMODE_INETD; conf->authmode = AUTHMODE_OPEN; conf->auth_pass = NULL; conf->oper_pass = NULL; - conf->configdir = g_strdup( CONFIG ); - conf->plugindir = g_strdup( PLUGINDIR ); - conf->pidfile = g_strdup( PIDFILE ); - conf->motdfile = g_strdup( ETCDIR "/motd.txt" ); + conf->configdir = g_strdup(CONFIG); + conf->plugindir = g_strdup(PLUGINDIR); + conf->pidfile = g_strdup(PIDFILE); + conf->motdfile = g_strdup(ETCDIR "/motd.txt"); conf->ping_interval = 180; conf->ping_timeout = 300; conf->user = NULL; @@ -68,328 +68,261 @@ conf_t *conf_load( int argc, char *argv[] ) conf->protocols = NULL; conf->cafile = NULL; proxytype = 0; - - i = conf_loadini( conf, global.conf_file ); - if( i == 0 ) - { - fprintf( stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file ); + + i = conf_loadini(conf, global.conf_file); + if (i == 0) { + fprintf(stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file); return NULL; - } - else if( i == -1 ) - { - config_missing ++; + } else if (i == -1) { + config_missing++; /* Whine after parsing the options if there was no -c pointing at a *valid* configuration file. */ } - - while( argc > 0 && ( opt = getopt( argc, argv, "i:p:P:nvIDFc:d:hu:V" ) ) >= 0 ) - /* ^^^^ Just to make sure we skip this step from the REHASH handler. */ - { - if( opt == 'i' ) - { - conf->iface_in = g_strdup( optarg ); - } - else if( opt == 'p' ) - { - g_free( conf->port ); - conf->port = g_strdup( optarg ); - } - else if( opt == 'P' ) - { - g_free( conf->pidfile ); - conf->pidfile = g_strdup( optarg ); - } - else if( opt == 'n' ) + + while (argc > 0 && (opt = getopt(argc, argv, "i:p:P:nvIDFc:d:hu:V")) >= 0) { + /* ^^^^ Just to make sure we skip this step from the REHASH handler. */ + if (opt == 'i') { + conf->iface_in = g_strdup(optarg); + } else if (opt == 'p') { + g_free(conf->port); + conf->port = g_strdup(optarg); + } else if (opt == 'P') { + g_free(conf->pidfile); + conf->pidfile = g_strdup(optarg); + } else if (opt == 'n') { conf->nofork = 1; - else if( opt == 'v' ) + } else if (opt == 'v') { conf->verbose = 1; - else if( opt == 'I' ) + } else if (opt == 'I') { conf->runmode = RUNMODE_INETD; - else if( opt == 'D' ) + } else if (opt == 'D') { conf->runmode = RUNMODE_DAEMON; - else if( opt == 'F' ) + } else if (opt == 'F') { conf->runmode = RUNMODE_FORKDAEMON; - else if( opt == 'c' ) - { - if( strcmp( global.conf_file, optarg ) != 0 ) - { - g_free( global.conf_file ); - global.conf_file = g_strdup( optarg ); - g_free( conf ); - /* Re-evaluate arguments. Don't use this option twice, + } else if (opt == 'c') { + if (strcmp(global.conf_file, optarg) != 0) { + g_free(global.conf_file); + global.conf_file = g_strdup(optarg); + g_free(conf); + /* Re-evaluate arguments. Don't use this option twice, you'll end up in an infinite loop! Hope this trick works with all libcs BTW.. */ optind = 1; - return conf_load( argc, argv ); + return conf_load(argc, argv); } - } - else if( opt == 'd' ) - { - g_free( conf->configdir ); - conf->configdir = g_strdup( optarg ); - } - else if( opt == 'h' ) - { - printf( "Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n" - " [-c <file>] [-d <dir>] [-x] [-h]\n" - "\n" - "An IRC-to-other-chat-networks gateway\n" - "\n" - " -I Classic/InetD mode. (Default)\n" - " -D Daemon mode. (one process serves all)\n" - " -F Forking daemon. (one process per client)\n" - " -u Run daemon as specified user.\n" - " -P Specify PID-file (not for inetd mode)\n" - " -i Specify the interface (by IP address) to listen on.\n" - " (Default: 0.0.0.0 (any interface))\n" - " -p Port number to listen on. (Default: 6667)\n" - " -n Don't fork.\n" - " -v Be verbose (only works in combination with -n)\n" - " -c Load alternative configuration file\n" - " -d Specify alternative user configuration directory\n" - " -x Command-line interface to password encryption/hashing\n" - " -h Show this help page.\n" - " -V Show version info.\n" ); + } else if (opt == 'd') { + g_free(conf->configdir); + conf->configdir = g_strdup(optarg); + } else if (opt == 'h') { + printf("Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n" + " [-c <file>] [-d <dir>] [-x] [-h]\n" + "\n" + "An IRC-to-other-chat-networks gateway\n" + "\n" + " -I Classic/InetD mode. (Default)\n" + " -D Daemon mode. (one process serves all)\n" + " -F Forking daemon. (one process per client)\n" + " -u Run daemon as specified user.\n" + " -P Specify PID-file (not for inetd mode)\n" + " -i Specify the interface (by IP address) to listen on.\n" + " (Default: 0.0.0.0 (any interface))\n" + " -p Port number to listen on. (Default: 6667)\n" + " -n Don't fork.\n" + " -v Be verbose (only works in combination with -n)\n" + " -c Load alternative configuration file\n" + " -d Specify alternative user configuration directory\n" + " -x Command-line interface to password encryption/hashing\n" + " -h Show this help page.\n" + " -V Show version info.\n"); return NULL; - } - else if( opt == 'V' ) - { - printf( "BitlBee %s\nAPI version %06x\n", - BITLBEE_VERSION, BITLBEE_VERSION_CODE ); + } else if (opt == 'V') { + printf("BitlBee %s\nAPI version %06x\n", + BITLBEE_VERSION, BITLBEE_VERSION_CODE); return NULL; - } - else if( opt == 'u' ) - { - g_free( conf->user ); - conf->user = g_strdup( optarg ); + } else if (opt == 'u') { + g_free(conf->user); + conf->user = g_strdup(optarg); } } - - if( conf->configdir[strlen(conf->configdir)-1] != '/' ) - { - char *s = g_new( char, strlen( conf->configdir ) + 2 ); - - sprintf( s, "%s/", conf->configdir ); - g_free( conf->configdir ); + + if (conf->configdir[strlen(conf->configdir) - 1] != '/') { + char *s = g_new(char, strlen(conf->configdir) + 2); + + sprintf(s, "%s/", conf->configdir); + g_free(conf->configdir); conf->configdir = s; } - - if( config_missing ) - fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file ); - - if( conf->cafile && access( conf->cafile, R_OK ) != 0 ) - { + + if (config_missing) { + fprintf(stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file); + } + + if (conf->cafile && access(conf->cafile, R_OK) != 0) { /* Let's treat this as a serious problem so people won't think they're secure when in fact they're not. */ - fprintf( stderr, "Error: Could not read CA file %s: %s\n", conf->cafile, strerror( errno ) ); + fprintf(stderr, "Error: Could not read CA file %s: %s\n", conf->cafile, strerror(errno)); return NULL; } - + return conf; } -static int conf_loadini( conf_t *conf, char *file ) +static int conf_loadini(conf_t *conf, char *file) { ini_t *ini; int i; - - ini = ini_open( file ); - if( ini == NULL ) return -1; - while( ini_read( ini ) ) - { - if( g_strcasecmp( ini->section, "settings" ) == 0 ) - { - if( g_strcasecmp( ini->key, "runmode" ) == 0 ) - { - if( g_strcasecmp( ini->value, "daemon" ) == 0 ) + + ini = ini_open(file); + if (ini == NULL) { + return -1; + } + while (ini_read(ini)) { + if (g_strcasecmp(ini->section, "settings") == 0) { + if (g_strcasecmp(ini->key, "runmode") == 0) { + if (g_strcasecmp(ini->value, "daemon") == 0) { conf->runmode = RUNMODE_DAEMON; - else if( g_strcasecmp( ini->value, "forkdaemon" ) == 0 ) + } else if (g_strcasecmp(ini->value, "forkdaemon") == 0) { conf->runmode = RUNMODE_FORKDAEMON; - else + } else { conf->runmode = RUNMODE_INETD; - } - else if( g_strcasecmp( ini->key, "pidfile" ) == 0 ) - { - g_free( conf->pidfile ); - conf->pidfile = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "daemoninterface" ) == 0 ) - { - g_free( conf->iface_in ); - conf->iface_in = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "daemonport" ) == 0 ) - { - g_free( conf->port ); - conf->port = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "clientinterface" ) == 0 ) - { - g_free( conf->iface_out ); - conf->iface_out = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "authmode" ) == 0 ) - { - if( g_strcasecmp( ini->value, "registered" ) == 0 ) + } + } else if (g_strcasecmp(ini->key, "pidfile") == 0) { + g_free(conf->pidfile); + conf->pidfile = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "daemoninterface") == 0) { + g_free(conf->iface_in); + conf->iface_in = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "daemonport") == 0) { + g_free(conf->port); + conf->port = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "clientinterface") == 0) { + g_free(conf->iface_out); + conf->iface_out = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "authmode") == 0) { + if (g_strcasecmp(ini->value, "registered") == 0) { conf->authmode = AUTHMODE_REGISTERED; - else if( g_strcasecmp( ini->value, "closed" ) == 0 ) + } else if (g_strcasecmp(ini->value, "closed") == 0) { conf->authmode = AUTHMODE_CLOSED; - else + } else { conf->authmode = AUTHMODE_OPEN; - } - else if( g_strcasecmp( ini->key, "authpassword" ) == 0 ) - { - g_free( conf->auth_pass ); - conf->auth_pass = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "operpassword" ) == 0 ) - { - g_free( conf->oper_pass ); - conf->oper_pass = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "hostname" ) == 0 ) - { - g_free( conf->hostname ); - conf->hostname = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "configdir" ) == 0 ) - { - g_free( conf->configdir ); - conf->configdir = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "motdfile" ) == 0 ) - { - g_free( conf->motdfile ); - conf->motdfile = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "account_storage" ) == 0 ) - { - g_free( conf->primary_storage ); - conf->primary_storage = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "account_storage_migrate" ) == 0 ) - { - g_strfreev( conf->migrate_storage ); - conf->migrate_storage = g_strsplit_set( ini->value, " \t,;", -1 ); - } - else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 ) - { - if( sscanf( ini->value, "%d", &i ) != 1 ) - { - fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); + } + } else if (g_strcasecmp(ini->key, "authpassword") == 0) { + g_free(conf->auth_pass); + conf->auth_pass = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "operpassword") == 0) { + g_free(conf->oper_pass); + conf->oper_pass = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "hostname") == 0) { + g_free(conf->hostname); + conf->hostname = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "configdir") == 0) { + g_free(conf->configdir); + conf->configdir = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "motdfile") == 0) { + g_free(conf->motdfile); + conf->motdfile = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "account_storage") == 0) { + g_free(conf->primary_storage); + conf->primary_storage = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "account_storage_migrate") == 0) { + g_strfreev(conf->migrate_storage); + conf->migrate_storage = g_strsplit_set(ini->value, " \t,;", -1); + } else if (g_strcasecmp(ini->key, "pinginterval") == 0) { + if (sscanf(ini->value, "%d", &i) != 1) { + fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); return 0; } conf->ping_interval = i; - } - else if( g_strcasecmp( ini->key, "pingtimeout" ) == 0 ) - { - if( sscanf( ini->value, "%d", &i ) != 1 ) - { - fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); + } else if (g_strcasecmp(ini->key, "pingtimeout") == 0) { + if (sscanf(ini->value, "%d", &i) != 1) { + fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); return 0; } conf->ping_timeout = i; - } - else if( g_strcasecmp( ini->key, "proxy" ) == 0 ) - { - url_t *url = g_new0( url_t, 1 ); - - if( !url_set( url, ini->value ) ) - { - fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); - g_free( url ); + } else if (g_strcasecmp(ini->key, "proxy") == 0) { + url_t *url = g_new0(url_t, 1); + + if (!url_set(url, ini->value)) { + fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); + g_free(url); return 0; } - - strncpy( proxyhost, url->host, sizeof( proxyhost ) ); - strncpy( proxyuser, url->user, sizeof( proxyuser ) ); - strncpy( proxypass, url->pass, sizeof( proxypass ) ); + + strncpy(proxyhost, url->host, sizeof(proxyhost)); + strncpy(proxyuser, url->user, sizeof(proxyuser)); + strncpy(proxypass, url->pass, sizeof(proxypass)); proxyport = url->port; - if( url->proto == PROTO_HTTP ) + if (url->proto == PROTO_HTTP) { proxytype = PROXY_HTTP; - else if( url->proto == PROTO_SOCKS4 ) + } else if (url->proto == PROTO_SOCKS4) { proxytype = PROXY_SOCKS4; - else if( url->proto == PROTO_SOCKS5 ) + } else if (url->proto == PROTO_SOCKS5) { proxytype = PROXY_SOCKS5; - - g_free( url ); - } - else if( g_strcasecmp( ini->key, "user" ) == 0 ) - { - g_free( conf->user ); - conf->user = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "ft_max_size" ) == 0 ) - { + } + + g_free(url); + } else if (g_strcasecmp(ini->key, "user") == 0) { + g_free(conf->user); + conf->user = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "ft_max_size") == 0) { size_t ft_max_size; - if( sscanf( ini->value, "%zu", &ft_max_size ) != 1 ) - { - fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); + if (sscanf(ini->value, "%zu", &ft_max_size) != 1) { + fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); return 0; } conf->ft_max_size = ft_max_size; - } - else if( g_strcasecmp( ini->key, "ft_max_kbps" ) == 0 ) - { - if( sscanf( ini->value, "%d", &i ) != 1 ) - { - fprintf( stderr, "Invalid %s value: %s\n", ini->key, ini->value ); + } else if (g_strcasecmp(ini->key, "ft_max_kbps") == 0) { + if (sscanf(ini->value, "%d", &i) != 1) { + fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value); return 0; } conf->ft_max_kbps = i; - } - else if( g_strcasecmp( ini->key, "ft_listen" ) == 0 ) - { - g_free( conf->ft_listen ); - conf->ft_listen = g_strdup( ini->value ); - } - else if( g_strcasecmp( ini->key, "protocols" ) == 0 ) - { - g_strfreev( conf->protocols ); - conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 ); - } - else if( g_strcasecmp( ini->key, "cafile" ) == 0 ) - { - g_free( conf->cafile ); - conf->cafile = g_strdup( ini->value ); - } - else - { - fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line ); + } else if (g_strcasecmp(ini->key, "ft_listen") == 0) { + g_free(conf->ft_listen); + conf->ft_listen = g_strdup(ini->value); + } else if (g_strcasecmp(ini->key, "protocols") == 0) { + g_strfreev(conf->protocols); + conf->protocols = g_strsplit_set(ini->value, " \t,;", -1); + } else if (g_strcasecmp(ini->key, "cafile") == 0) { + g_free(conf->cafile); + conf->cafile = g_strdup(ini->value); + } else { + fprintf(stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", + ini->key, ini->line); return 0; /* For now just ignore unknown keys... */ } - } - else if( g_strcasecmp( ini->section, "defaults" ) != 0 ) - { - fprintf( stderr, "Error: Unknown section [%s] in configuration file (line %d). " - "BitlBee configuration must be put in a [settings] section!\n", ini->section, ini->line ); + } else if (g_strcasecmp(ini->section, "defaults") != 0) { + fprintf(stderr, "Error: Unknown section [%s] in configuration file (line %d). " + "BitlBee configuration must be put in a [settings] section!\n", ini->section, + ini->line); return 0; } } - ini_close( ini ); - + ini_close(ini); + return 1; } -void conf_loaddefaults( irc_t *irc ) +void conf_loaddefaults(irc_t *irc) { ini_t *ini; - - ini = ini_open( global.conf_file ); - if( ini == NULL ) return; - while( ini_read( ini ) ) - { - if( g_strcasecmp( ini->section, "defaults" ) == 0 ) - { - set_t *s = set_find( &irc->b->set, ini->key ); - - if( s ) - { - if( s->def ) g_free( s->def ); - s->def = g_strdup( ini->value ); + + ini = ini_open(global.conf_file); + if (ini == NULL) { + return; + } + while (ini_read(ini)) { + if (g_strcasecmp(ini->section, "defaults") == 0) { + set_t *s = set_find(&irc->b->set, ini->key); + + if (s) { + if (s->def) { + g_free(s->def); + } + s->def = g_strdup(ini->value); } } } - ini_close( ini ); + ini_close(ini); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -29,8 +29,7 @@ typedef enum runmode { RUNMODE_DAEMON, RUNMODE_FORKDAEMON, RUNMODE_INETD } runmode_t; typedef enum authmode { AUTHMODE_OPEN, AUTHMODE_CLOSED, AUTHMODE_REGISTERED } authmode_t; -typedef struct conf -{ +typedef struct conf { char *iface_in, *iface_out; char *port; int nofork; @@ -56,7 +55,7 @@ typedef struct conf char *cafile; } conf_t; -G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] ); -void conf_loaddefaults( irc_t *irc ); +G_GNUC_MALLOC conf_t *conf_load(int argc, char *argv[]); +void conf_loaddefaults(irc_t *irc); #endif @@ -29,62 +29,62 @@ #include <regex.h> #include "lib/ftutil.h" -/* +/* * Since that might be confusing a note on naming: * - * Generic dcc functions start with + * Generic dcc functions start with * - * dcc_ + * dcc_ * * ,methods specific to DCC SEND start with * - * dccs_ + * dccs_ * * . Since we can be on both ends of a DCC SEND, * functions specific to one end are called * - * dccs_send and dccs_recv + * dccs_send and dccs_recv * * ,respectively. */ -/* +/* * used to generate a unique local transfer id the user * can use to reject/cancel transfers */ -unsigned int local_transfer_id=1; +unsigned int local_transfer_id = 1; -/* +/* * just for debugging the nr. of chunks we received from im-protocols and the total data */ -unsigned int receivedchunks=0, receiveddata=0; - -void dcc_finish( file_transfer_t *file ); -void dcc_close( file_transfer_t *file ); -gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond ); -int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr ); -gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond); -gboolean dccs_recv_write_request( file_transfer_t *ft ); -gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond ); -gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ); - -dcc_file_transfer_t *dcc_alloc_transfer( const char *file_name, size_t file_size, struct im_connection *ic ) +unsigned int receivedchunks = 0, receiveddata = 0; + +void dcc_finish(file_transfer_t *file); +void dcc_close(file_transfer_t *file); +gboolean dccs_send_proto(gpointer data, gint fd, b_input_condition cond); +int dccs_send_request(struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr); +gboolean dccs_recv_proto(gpointer data, gint fd, b_input_condition cond); +gboolean dccs_recv_write_request(file_transfer_t *ft); +gboolean dcc_progress(gpointer data, gint fd, b_input_condition cond); +gboolean dcc_abort(dcc_file_transfer_t *df, char *reason, ...); + +dcc_file_transfer_t *dcc_alloc_transfer(const char *file_name, size_t file_size, struct im_connection *ic) { - file_transfer_t *file = g_new0( file_transfer_t, 1 ); - dcc_file_transfer_t *df = file->priv = g_new0( dcc_file_transfer_t, 1 ); - + file_transfer_t *file = g_new0(file_transfer_t, 1); + dcc_file_transfer_t *df = file->priv = g_new0(dcc_file_transfer_t, 1); + file->file_size = file_size; - file->file_name = g_strdup( file_name ); + file->file_name = g_strdup(file_name); file->local_id = local_transfer_id++; file->ic = df->ic = ic; df->ft = file; - + return df; } /* This is where the sending magic starts... */ -file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size ) +file_transfer_t *dccs_send_start(struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size) { file_transfer_t *file; dcc_file_transfer_t *df; @@ -94,75 +94,79 @@ file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, cons char host[HOST_NAME_MAX]; char port[6]; - if( file_size > global.conf->ft_max_size ) + if (file_size > global.conf->ft_max_size) { return NULL; - - df = dcc_alloc_transfer( file_name, file_size, ic ); + } + + df = dcc_alloc_transfer(file_name, file_size, ic); file = df->ft; file->write = dccs_send_write; /* listen and request */ - if( ( df->fd = ft_listen( &saddr, host, port, irc->fd, TRUE, &errmsg ) ) == -1 ) - { - dcc_abort( df, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", errmsg ); + if ((df->fd = ft_listen(&saddr, host, port, irc->fd, TRUE, &errmsg)) == -1) { + dcc_abort(df, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", errmsg); return NULL; } file->status = FT_STATUS_LISTENING; - if( !dccs_send_request( df, iu, &saddr ) ) + if (!dccs_send_request(df, iu, &saddr)) { return NULL; + } /* watch */ - df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_send_proto, df ); + df->watch_in = b_input_add(df->fd, B_EV_IO_READ, dccs_send_proto, df); - irc->file_transfers = g_slist_prepend( irc->file_transfers, file ); + irc->file_transfers = g_slist_prepend(irc->file_transfers, file); - df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); + df->progress_timeout = b_timeout_add(DCC_MAX_STALL * 1000, dcc_progress, df); - imcb_log( ic, "File transfer request from %s for %s (%zd kb).\n" - "Accept the file transfer if you'd like the file. If you don't, " - "issue the 'transfer reject' command.", - iu->nick, file_name, file_size / 1024 ); + imcb_log(ic, "File transfer request from %s for %s (%zd kb).\n" + "Accept the file transfer if you'd like the file. If you don't, " + "issue the 'transfer reject' command.", + iu->nick, file_name, file_size / 1024); return file; } /* Used pretty much everywhere in the code to abort a transfer */ -gboolean dcc_abort( dcc_file_transfer_t *df, char *reason, ... ) +gboolean dcc_abort(dcc_file_transfer_t *df, char *reason, ...) { file_transfer_t *file = df->ft; va_list params; - va_start( params, reason ); - char *msg = g_strdup_vprintf( reason, params ); - va_end( params ); - + + va_start(params, reason); + char *msg = g_strdup_vprintf(reason, params); + va_end(params); + file->status |= FT_STATUS_CANCELED; - - if( file->canceled ) - file->canceled( file, msg ); - imcb_log( df->ic, "File %s: DCC transfer aborted: %s", file->file_name, msg ); + if (file->canceled) { + file->canceled(file, msg); + } + + imcb_log(df->ic, "File %s: DCC transfer aborted: %s", file->file_name, msg); - g_free( msg ); + g_free(msg); - dcc_close( df->ft ); + dcc_close(df->ft); return FALSE; } -gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond ) +gboolean dcc_progress(gpointer data, gint fd, b_input_condition cond) { struct dcc_file_transfer *df = data; - if( df->bytes_sent == df->progress_bytes_last ) - { + if (df->bytes_sent == df->progress_bytes_last) { /* no progress. cancel */ - if( df->bytes_sent == 0 ) - return dcc_abort( df, "Couldn't establish transfer within %d seconds", DCC_MAX_STALL ); - else - return dcc_abort( df, "Transfer stalled for %d seconds at %d kb", DCC_MAX_STALL, df->bytes_sent / 1024 ); + if (df->bytes_sent == 0) { + return dcc_abort(df, "Couldn't establish transfer within %d seconds", DCC_MAX_STALL); + } else { + return dcc_abort(df, "Transfer stalled for %d seconds at %d kb", DCC_MAX_STALL, + df->bytes_sent / 1024); + } } @@ -173,47 +177,45 @@ gboolean dcc_progress( gpointer data, gint fd, b_input_condition cond ) /* used extensively for socket operations */ #define ASSERTSOCKOP(op, msg) \ - if( (op) == -1 ) \ - return dcc_abort( df , msg ": %s", strerror( errno ) ); + if ((op) == -1) { \ + return dcc_abort(df, msg ": %s", strerror(errno)); } /* Creates the "DCC SEND" line and sends it to the server */ -int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr ) +int dccs_send_request(struct dcc_file_transfer *df, irc_user_t *iu, struct sockaddr_storage *saddr) { - char ipaddr[INET6_ADDRSTRLEN]; + char ipaddr[INET6_ADDRSTRLEN]; const void *netaddr; int port; char *cmd; - if( saddr->ss_family == AF_INET ) - { + if (saddr->ss_family == AF_INET) { struct sockaddr_in *saddr_ipv4 = ( struct sockaddr_in *) saddr; - sprintf( ipaddr, "%d", - ntohl( saddr_ipv4->sin_addr.s_addr ) ); + sprintf(ipaddr, "%d", + ntohl(saddr_ipv4->sin_addr.s_addr)); port = saddr_ipv4->sin_port; - } - else - { + } else { struct sockaddr_in6 *saddr_ipv6 = ( struct sockaddr_in6 *) saddr; netaddr = &saddr_ipv6->sin6_addr.s6_addr; port = saddr_ipv6->sin6_port; - /* + /* * Didn't find docs about this, but it seems that's the way irssi does it */ - if( !inet_ntop( saddr->ss_family, netaddr, ipaddr, sizeof( ipaddr ) ) ) - return dcc_abort( df, "inet_ntop failed: %s", strerror( errno ) ); + if (!inet_ntop(saddr->ss_family, netaddr, ipaddr, sizeof(ipaddr))) { + return dcc_abort(df, "inet_ntop failed: %s", strerror(errno)); + } } - port = ntohs( port ); + port = ntohs(port); + + cmd = g_strdup_printf("\001DCC SEND %s %s %u %zu\001", + df->ft->file_name, ipaddr, port, df->ft->file_size); - cmd = g_strdup_printf( "\001DCC SEND %s %s %u %zu\001", - df->ft->file_name, ipaddr, port, df->ft->file_size ); - - irc_send_msg_raw( iu, "PRIVMSG", iu->irc->user->nick, cmd ); + irc_send_msg_raw(iu, "PRIVMSG", iu->irc->user->nick, cmd); - g_free( cmd ); + g_free(cmd); return TRUE; } @@ -222,124 +224,132 @@ int dccs_send_request( struct dcc_file_transfer *df, irc_user_t *iu, struct sock * After setup, the transfer itself is handled entirely by this function. * There are basically four things to handle: connect, receive, send, and error. */ -gboolean dccs_send_proto( gpointer data, gint fd, b_input_condition cond ) +gboolean dccs_send_proto(gpointer data, gint fd, b_input_condition cond) { dcc_file_transfer_t *df = data; file_transfer_t *file = df->ft; - - if( ( cond & B_EV_IO_READ ) && - ( file->status & FT_STATUS_LISTENING ) ) - { + + if ((cond & B_EV_IO_READ) && + (file->status & FT_STATUS_LISTENING)) { struct sockaddr *clt_addr; - socklen_t ssize = sizeof( clt_addr ); + socklen_t ssize = sizeof(clt_addr); /* Connect */ - ASSERTSOCKOP( df->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" ); + ASSERTSOCKOP(df->fd = accept(fd, (struct sockaddr *) &clt_addr, &ssize), "Accepting connection"); - closesocket( fd ); + closesocket(fd); fd = df->fd; file->status = FT_STATUS_TRANSFERRING; - sock_make_nonblocking( fd ); + sock_make_nonblocking(fd); /* IM protocol callback */ - if( file->accept ) - file->accept( file ); + if (file->accept) { + file->accept(file); + } /* reschedule for reading on new fd */ - df->watch_in = b_input_add( fd, B_EV_IO_READ, dccs_send_proto, df ); + df->watch_in = b_input_add(fd, B_EV_IO_READ, dccs_send_proto, df); return FALSE; } - if( cond & B_EV_IO_READ ) - { + if (cond & B_EV_IO_READ) { int ret; - - ASSERTSOCKOP( ret = recv( fd, ( (char*) &df->acked ) + df->acked_len, - sizeof( df->acked ) - df->acked_len, 0 ), "Receiving" ); - if( ret == 0 ) - return dcc_abort( df, "Remote end closed connection" ); - + ASSERTSOCKOP(ret = recv(fd, ((char *) &df->acked) + df->acked_len, + sizeof(df->acked) - df->acked_len, 0), "Receiving"); + + if (ret == 0) { + return dcc_abort(df, "Remote end closed connection"); + } + /* How likely is it that a 32-bit integer gets split accross packet boundaries? Chances are rarely 0 so let's be sure. */ - if( ( df->acked_len = ( df->acked_len + ret ) % 4 ) > 0 ) + if ((df->acked_len = (df->acked_len + ret) % 4) > 0) { return TRUE; + } - df->acked = ntohl( df->acked ); + df->acked = ntohl(df->acked); /* If any of this is actually happening, the receiver should buy a new IRC client */ - if ( df->acked > df->bytes_sent ) - return dcc_abort( df, "Receiver magically received more bytes than sent ( %d > %d ) (BUG at receiver?)", df->acked, df->bytes_sent ); + if (df->acked > df->bytes_sent) { + return dcc_abort(df, + "Receiver magically received more bytes than sent ( %d > %d ) (BUG at receiver?)", df->acked, + df->bytes_sent); + } + + if (df->acked < file->bytes_transferred) { + return dcc_abort(df, "Receiver lost bytes? ( has %d, had %d ) (BUG at receiver?)", df->acked, + file->bytes_transferred); + } - if ( df->acked < file->bytes_transferred ) - return dcc_abort( df, "Receiver lost bytes? ( has %d, had %d ) (BUG at receiver?)", df->acked, file->bytes_transferred ); - file->bytes_transferred = df->acked; - - if( file->bytes_transferred >= file->file_size ) { - if( df->proto_finished ) - dcc_finish( file ); + + if (file->bytes_transferred >= file->file_size) { + if (df->proto_finished) { + dcc_finish(file); + } return FALSE; } - + return TRUE; } return TRUE; } -gboolean dccs_recv_start( file_transfer_t *ft ) +gboolean dccs_recv_start(file_transfer_t *ft) { dcc_file_transfer_t *df = ft->priv; struct sockaddr_storage *saddr = &df->saddr; int fd; - char ipaddr[INET6_ADDRSTRLEN]; - socklen_t sa_len = saddr->ss_family == AF_INET ? - sizeof( struct sockaddr_in ) : sizeof( struct sockaddr_in6 ); - - if( !ft->write ) - return dcc_abort( df, "BUG: protocol didn't register write()" ); - - ASSERTSOCKOP( fd = df->fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening Socket" ); - - sock_make_nonblocking( fd ); - - if( ( connect( fd, (struct sockaddr *)saddr, sa_len ) == -1 ) && - ( errno != EINPROGRESS ) ) - return dcc_abort( df, "Connecting to %s:%d : %s", - inet_ntop( saddr->ss_family, - saddr->ss_family == AF_INET ? - ( void* ) &( ( struct sockaddr_in *) saddr )->sin_addr.s_addr : - ( void* ) &( ( struct sockaddr_in6 *) saddr )->sin6_addr.s6_addr, - ipaddr, - sizeof( ipaddr ) ), - ntohs( saddr->ss_family == AF_INET ? - ( ( struct sockaddr_in *) saddr )->sin_port : - ( ( struct sockaddr_in6 *) saddr )->sin6_port ), - strerror( errno ) ); + char ipaddr[INET6_ADDRSTRLEN]; + socklen_t sa_len = saddr->ss_family == AF_INET ? + sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); + + if (!ft->write) { + return dcc_abort(df, "BUG: protocol didn't register write()"); + } + + ASSERTSOCKOP(fd = df->fd = socket(saddr->ss_family, SOCK_STREAM, 0), "Opening Socket"); + + sock_make_nonblocking(fd); + + if ((connect(fd, (struct sockaddr *) saddr, sa_len) == -1) && + (errno != EINPROGRESS)) { + return dcc_abort(df, "Connecting to %s:%d : %s", + inet_ntop(saddr->ss_family, + saddr->ss_family == AF_INET ? + ( void * ) &(( struct sockaddr_in *) saddr)->sin_addr.s_addr : + ( void * ) &(( struct sockaddr_in6 *) saddr)->sin6_addr.s6_addr, + ipaddr, + sizeof(ipaddr)), + ntohs(saddr->ss_family == AF_INET ? + (( struct sockaddr_in *) saddr)->sin_port : + (( struct sockaddr_in6 *) saddr)->sin6_port), + strerror(errno)); + } ft->status = FT_STATUS_CONNECTING; /* watch */ - df->watch_out = b_input_add( df->fd, B_EV_IO_WRITE, dccs_recv_proto, df ); + df->watch_out = b_input_add(df->fd, B_EV_IO_WRITE, dccs_recv_proto, df); ft->write_request = dccs_recv_write_request; - df->progress_timeout = b_timeout_add( DCC_MAX_STALL * 1000, dcc_progress, df ); + df->progress_timeout = b_timeout_add(DCC_MAX_STALL * 1000, dcc_progress, df); return TRUE; } -gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond ) +gboolean dccs_recv_proto(gpointer data, gint fd, b_input_condition cond) { dcc_file_transfer_t *df = data; file_transfer_t *ft = df->ft; - if( ( cond & B_EV_IO_WRITE ) && - ( ft->status & FT_STATUS_CONNECTING ) ) - { + if ((cond & B_EV_IO_WRITE) && + (ft->status & FT_STATUS_CONNECTING)) { ft->status = FT_STATUS_TRANSFERRING; //df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_recv_proto, df ); @@ -348,46 +358,49 @@ gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond ) return FALSE; } - if( cond & B_EV_IO_READ ) - { + if (cond & B_EV_IO_READ) { int ret, done; - ASSERTSOCKOP( ret = recv( fd, ft->buffer, sizeof( ft->buffer ), 0 ), "Receiving" ); + ASSERTSOCKOP(ret = recv(fd, ft->buffer, sizeof(ft->buffer), 0), "Receiving"); - if( ret == 0 ) - return dcc_abort( df, "Remote end closed connection" ); + if (ret == 0) { + return dcc_abort(df, "Remote end closed connection"); + } - if( !ft->write( df->ft, ft->buffer, ret ) ) + if (!ft->write(df->ft, ft->buffer, ret)) { return FALSE; + } df->bytes_sent += ret; done = df->bytes_sent >= ft->file_size; - if( ( ( df->bytes_sent - ft->bytes_transferred ) > DCC_PACKET_SIZE ) || - done ) - { - guint32 ack = htonl( ft->bytes_transferred = df->bytes_sent ); + if (((df->bytes_sent - ft->bytes_transferred) > DCC_PACKET_SIZE) || + done) { + guint32 ack = htonl(ft->bytes_transferred = df->bytes_sent); int ackret; - ASSERTSOCKOP( ackret = send( fd, &ack, 4, 0 ), "Sending DCC ACK" ); - - if ( ackret != 4 ) - return dcc_abort( df, "Error sending DCC ACK, sent %d instead of 4 bytes", ackret ); + ASSERTSOCKOP(ackret = send(fd, &ack, 4, 0), "Sending DCC ACK"); + + if (ackret != 4) { + return dcc_abort(df, "Error sending DCC ACK, sent %d instead of 4 bytes", ackret); + } + } + + if (df->bytes_sent == ret) { + ft->started = time(NULL); } - - if( df->bytes_sent == ret ) - ft->started = time( NULL ); - if( done ) - { - if( df->watch_out ) - b_event_remove( df->watch_out ); + if (done) { + if (df->watch_out) { + b_event_remove(df->watch_out); + } df->watch_in = 0; - if( df->proto_finished ) - dcc_finish( ft ); + if (df->proto_finished) { + dcc_finish(ft); + } return FALSE; } @@ -399,57 +412,64 @@ gboolean dccs_recv_proto( gpointer data, gint fd, b_input_condition cond ) return TRUE; } -gboolean dccs_recv_write_request( file_transfer_t *ft ) +gboolean dccs_recv_write_request(file_transfer_t *ft) { dcc_file_transfer_t *df = ft->priv; - if( df->watch_in ) - return dcc_abort( df, "BUG: write_request() called while watching" ); + if (df->watch_in) { + return dcc_abort(df, "BUG: write_request() called while watching"); + } - df->watch_in = b_input_add( df->fd, B_EV_IO_READ, dccs_recv_proto, df ); + df->watch_in = b_input_add(df->fd, B_EV_IO_READ, dccs_recv_proto, df); return TRUE; } -gboolean dccs_send_can_write( gpointer data, gint fd, b_input_condition cond ) +gboolean dccs_send_can_write(gpointer data, gint fd, b_input_condition cond) { struct dcc_file_transfer *df = data; + df->watch_out = 0; - df->ft->write_request( df->ft ); + df->ft->write_request(df->ft); return FALSE; } -/* +/* * Incoming data. - * + * */ -gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_len ) +gboolean dccs_send_write(file_transfer_t *file, char *data, unsigned int data_len) { dcc_file_transfer_t *df = file->priv; int ret; receivedchunks++; receiveddata += data_len; - if( df->watch_out ) - return dcc_abort( df, "BUG: write() called while watching" ); + if (df->watch_out) { + return dcc_abort(df, "BUG: write() called while watching"); + } - ASSERTSOCKOP( ret = send( df->fd, data, data_len, 0 ), "Sending data" ); + ASSERTSOCKOP(ret = send(df->fd, data, data_len, 0), "Sending data"); - if( ret == 0 ) - return dcc_abort( df, "Remote end closed connection" ); + if (ret == 0) { + return dcc_abort(df, "Remote end closed connection"); + } /* TODO: this should really not be fatal */ - if( ret < data_len ) - return dcc_abort( df, "send() sent %d instead of %d", ret, data_len ); + if (ret < data_len) { + return dcc_abort(df, "send() sent %d instead of %d", ret, data_len); + } - if( df->bytes_sent == 0 ) - file->started = time( NULL ); + if (df->bytes_sent == 0) { + file->started = time(NULL); + } df->bytes_sent += ret; - if( df->bytes_sent < df->ft->file_size ) - df->watch_out = b_input_add( df->fd, B_EV_IO_WRITE, dccs_send_can_write, df ); + if (df->bytes_sent < df->ft->file_size) { + df->watch_out = b_input_add(df->fd, B_EV_IO_WRITE, dccs_send_can_write, df); + } return TRUE; } @@ -457,111 +477,115 @@ gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_l /* * Cleans up after a transfer. */ -void dcc_close( file_transfer_t *file ) +void dcc_close(file_transfer_t *file) { dcc_file_transfer_t *df = file->priv; irc_t *irc = (irc_t *) df->ic->bee->ui_data; - if( file->free ) - file->free( file ); - - closesocket( df->fd ); - - if( df->watch_in ) - b_event_remove( df->watch_in ); - - if( df->watch_out ) - b_event_remove( df->watch_out ); - - if( df->progress_timeout ) - b_event_remove( df->progress_timeout ); - - irc->file_transfers = g_slist_remove( irc->file_transfers, file ); - - g_free( df ); - g_free( file->file_name ); - g_free( file ); + if (file->free) { + file->free(file); + } + + closesocket(df->fd); + + if (df->watch_in) { + b_event_remove(df->watch_in); + } + + if (df->watch_out) { + b_event_remove(df->watch_out); + } + + if (df->progress_timeout) { + b_event_remove(df->progress_timeout); + } + + irc->file_transfers = g_slist_remove(irc->file_transfers, file); + + g_free(df); + g_free(file->file_name); + g_free(file); } -void dcc_finish( file_transfer_t *file ) +void dcc_finish(file_transfer_t *file) { dcc_file_transfer_t *df = file->priv; - time_t diff = time( NULL ) - file->started ? : 1; + time_t diff = time(NULL) - file->started ? : 1; file->status |= FT_STATUS_FINISHED; - - if( file->finished ) - file->finished( file ); - imcb_log( df->ic, "File %s transferred successfully at %d kb/s!" , file->file_name, (int) ( file->bytes_transferred / 1024 / diff ) ); - dcc_close( file ); + if (file->finished) { + file->finished(file); + } + + imcb_log(df->ic, "File %s transferred successfully at %d kb/s!", file->file_name, + (int) (file->bytes_transferred / 1024 / diff)); + dcc_close(file); } -/* +/* * DCC SEND <filename> <IP> <port> <filesize> * * filename can be in "" or not. If it is, " can probably be escaped... * IP can be an unsigned int (IPV4) or something else (IPV6) - * + * */ -file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp ) +file_transfer_t *dcc_request(struct im_connection *ic, char* const* ctcp) { irc_t *irc = (irc_t *) ic->bee->ui_data; file_transfer_t *ft; dcc_file_transfer_t *df; int gret; size_t filesize; - - if( ctcp[5] != NULL && - sscanf( ctcp[4], "%zd", &filesize ) == 1 && /* Just int. validation. */ - sscanf( ctcp[5], "%zd", &filesize ) == 1 ) - { + + if (ctcp[5] != NULL && + sscanf(ctcp[4], "%zd", &filesize) == 1 && /* Just int. validation. */ + sscanf(ctcp[5], "%zd", &filesize) == 1) { char *filename, *host, *port; struct addrinfo hints, *rp; - + filename = ctcp[2]; - + host = ctcp[3]; - while( *host && g_ascii_isdigit( *host ) ) host++; /* Just digits? */ - if( *host == '\0' ) - { - struct in_addr ipaddr = { .s_addr = htonl( atoll( ctcp[3] ) ) }; - host = inet_ntoa( ipaddr ); - } else - { + while (*host && g_ascii_isdigit(*host)) { + host++; /* Just digits? */ + } + if (*host == '\0') { + struct in_addr ipaddr = { .s_addr = htonl(atoll(ctcp[3])) }; + host = inet_ntoa(ipaddr); + } else { /* Contains non-numbers, hopefully an IPV6 address */ host = ctcp[3]; } port = ctcp[4]; - filesize = atoll( ctcp[5] ); + filesize = atoll(ctcp[5]); - memset( &hints, 0, sizeof ( struct addrinfo ) ); + memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICSERV; - if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) ) - { - imcb_log( ic, "DCC: getaddrinfo() failed with %s " - "when parsing incoming 'DCC SEND': " - "host %s, port %s", - gai_strerror( gret ), host, port ); + if ((gret = getaddrinfo(host, port, &hints, &rp))) { + imcb_log(ic, "DCC: getaddrinfo() failed with %s " + "when parsing incoming 'DCC SEND': " + "host %s, port %s", + gai_strerror(gret), host, port); return NULL; } - df = dcc_alloc_transfer( filename, filesize, ic ); + df = dcc_alloc_transfer(filename, filesize, ic); ft = df->ft; ft->sending = TRUE; - memcpy( &df->saddr, rp->ai_addr, rp->ai_addrlen ); + memcpy(&df->saddr, rp->ai_addr, rp->ai_addrlen); - freeaddrinfo( rp ); + freeaddrinfo(rp); - irc->file_transfers = g_slist_prepend( irc->file_transfers, ft ); + irc->file_transfers = g_slist_prepend(irc->file_transfers, ft); return ft; + } else { + imcb_log(ic, "DCC: couldnt parse `DCC SEND' line"); } - else - imcb_log( ic, "DCC: couldnt parse `DCC SEND' line" ); return NULL; } @@ -22,7 +22,7 @@ Fifth Floor, Boston, MA 02110-1301 USA */ -/* +/* * DCC SEND * * Historically, DCC means send 1024 Bytes and wait for a 4 byte reply @@ -38,7 +38,7 @@ * about those DCC ACKs and just send data as you please. This behaviour is * enabled by default. Note that this also means that packets may be as large * as the maximum segment size. - */ + */ #ifndef _DCC_H #define _DCC_H @@ -60,13 +60,13 @@ typedef struct dcc_file_transfer { * taking place. */ int fd; - + /* * IDs returned by b_input_add for watch_ing over the above socket. */ gint watch_in; /* readable */ gint watch_out; /* writable */ - + /* the progress watcher cancels any file transfer if nothing happens within DCC_MAX_STALL */ gint progress_timeout; size_t progress_bytes_last; @@ -75,31 +75,31 @@ typedef struct dcc_file_transfer { * The total amount of bytes that have been sent to the irc client. */ size_t bytes_sent; - + /* * Handle the wonderful sadly-not-deprecated ACKs. */ guint32 acked; int acked_len; - + /* imc's handle */ file_transfer_t *ft; /* if we're receiving, this is the sender's socket address */ struct sockaddr_storage saddr; - /* set to true if the protocol has finished + /* set to true if the protocol has finished * (i.e. called imcb_file_finished) */ int proto_finished; } dcc_file_transfer_t; -file_transfer_t *dccs_send_start( struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size ); -void dcc_canceled( file_transfer_t *file, char *reason ); -gboolean dccs_send_write( file_transfer_t *file, char *data, unsigned int data_size ); -file_transfer_t *dcc_request( struct im_connection *ic, char* const* ctcp ); -void dcc_finish( file_transfer_t *file ); -void dcc_close( file_transfer_t *file ); -gboolean dccs_recv_start( file_transfer_t *ft ); +file_transfer_t *dccs_send_start(struct im_connection *ic, irc_user_t *iu, const char *file_name, size_t file_size); +void dcc_canceled(file_transfer_t *file, char *reason); +gboolean dccs_send_write(file_transfer_t *file, char *data, unsigned int data_size); +file_transfer_t *dcc_request(struct im_connection *ic, char* const* ctcp); +void dcc_finish(file_transfer_t *file); +void dcc_close(file_transfer_t *file); +gboolean dccs_recv_start(file_transfer_t *ft); #endif diff --git a/doc/example_plugin.c b/doc/example_plugin.c index a33907a8..2fc320a7 100644 --- a/doc/example_plugin.c +++ b/doc/example_plugin.c @@ -1,6 +1,6 @@ -/* - * This is the most simple possible BitlBee plugin. To use, compile it as - * a shared library and place it in the plugin directory: +/* + * This is the most simple possible BitlBee plugin. To use, compile it as + * a shared library and place it in the plugin directory: * * gcc -o example.so -shared example.c `pkg-config --cflags bitlbee` * cp example.so /usr/local/lib/bitlbee @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -26,188 +26,179 @@ #define BITLBEE_CORE #include "bitlbee.h" #include "help.h" -#undef read +#undef read #undef write #define BUFSIZE 1100 -help_t *help_init( help_t **help, const char *helpfile ) +help_t *help_init(help_t **help, const char *helpfile) { int i, buflen = 0; help_t *h; char *s, *t; time_t mtime; struct stat stat[1]; - - *help = h = g_new0 ( help_t, 1 ); - - h->fd = open( helpfile, O_RDONLY ); - - if( h->fd == -1 ) - { - g_free( h ); - return( *help = NULL ); + + *help = h = g_new0(help_t, 1); + + h->fd = open(helpfile, O_RDONLY); + + if (h->fd == -1) { + g_free(h); + return(*help = NULL); } - - if( fstat( h->fd, stat ) != 0 ) - { - g_free( h ); - return( *help = NULL ); + + if (fstat(h->fd, stat) != 0) { + g_free(h); + return(*help = NULL); } mtime = stat->st_mtime; - - s = g_new (char, BUFSIZE + 1 ); + + s = g_new(char, BUFSIZE + 1); s[BUFSIZE] = 0; - - while( ( ( i = read( h->fd, s + buflen, BUFSIZE - buflen ) ) > 0 ) || - ( i == 0 && strstr( s, "\n%\n" ) ) ) - { + + while (((i = read(h->fd, s + buflen, BUFSIZE - buflen)) > 0) || + (i == 0 && strstr(s, "\n%\n"))) { buflen += i; - memset( s + buflen, 0, BUFSIZE - buflen ); - if( !( t = strstr( s, "\n%\n" ) ) || s[0] != '?' ) - { + memset(s + buflen, 0, BUFSIZE - buflen); + if (!(t = strstr(s, "\n%\n")) || s[0] != '?') { /* FIXME: Clean up */ - help_free( help ); - g_free( s ); + help_free(help); + g_free(s); return NULL; } - i = strchr( s, '\n' ) - s; - - if( h->title ) - { - h = h->next = g_new0( help_t, 1 ); + i = strchr(s, '\n') - s; + + if (h->title) { + h = h->next = g_new0(help_t, 1); } - h->title = g_new ( char, i ); - - strncpy( h->title, s + 1, i - 1 ); - h->title[i-1] = 0; + h->title = g_new(char, i); + + strncpy(h->title, s + 1, i - 1); + h->title[i - 1] = 0; h->fd = (*help)->fd; - h->offset.file_offset = lseek( h->fd, 0, SEEK_CUR ) - buflen + i + 1; + h->offset.file_offset = lseek(h->fd, 0, SEEK_CUR) - buflen + i + 1; h->length = t - s - i - 1; h->mtime = mtime; - - buflen -= ( t + 3 - s ); - t = g_strdup( t + 3 ); - g_free( s ); - s = g_renew( char, t, BUFSIZE + 1 ); + + buflen -= (t + 3 - s); + t = g_strdup(t + 3); + g_free(s); + s = g_renew(char, t, BUFSIZE + 1); s[BUFSIZE] = 0; } - - g_free( s ); - - return( *help ); + + g_free(s); + + return(*help); } -void help_free( help_t **help ) +void help_free(help_t **help) { help_t *h, *oh; int last_fd = -1; /* Weak de-dupe */ - - if( help == NULL || *help == NULL ) + + if (help == NULL || *help == NULL) { return; - + } + h = *help; - while( h ) - { - if( h->fd != last_fd ) - { - close( h->fd ); + while (h) { + if (h->fd != last_fd) { + close(h->fd); last_fd = h->fd; } - g_free( h->title ); - h = (oh=h)->next; - g_free( oh ); + g_free(h->title); + h = (oh = h)->next; + g_free(oh); } - + *help = NULL; } -char *help_get( help_t **help, char *title ) +char *help_get(help_t **help, char *title) { time_t mtime; struct stat stat[1]; help_t *h; - for( h = *help; h; h = h->next ) - { - if( h->title != NULL && g_strcasecmp( h->title, title ) == 0 ) + for (h = *help; h; h = h->next) { + if (h->title != NULL && g_strcasecmp(h->title, title) == 0) { break; + } } - if( h && h->length > 0 ) - { - char *s = g_new( char, h->length + 1 ); - + if (h && h->length > 0) { + char *s = g_new(char, h->length + 1); + s[h->length] = 0; - if( h->fd >= 0 ) - { - if( fstat( h->fd, stat ) != 0 ) - { - g_free( s ); + if (h->fd >= 0) { + if (fstat(h->fd, stat) != 0) { + g_free(s); return NULL; } mtime = stat->st_mtime; - - if( mtime > h->mtime ) - { - g_free( s ); + + if (mtime > h->mtime) { + g_free(s); return NULL; } - - if( lseek( h->fd, h->offset.file_offset, SEEK_SET ) == -1 || - read( h->fd, s, h->length ) != h->length ) + + if (lseek(h->fd, h->offset.file_offset, SEEK_SET) == -1 || + read(h->fd, s, h->length) != h->length) { return NULL; - } - else - { - strncpy( s, h->offset.mem_offset, h->length ); + } + } else { + strncpy(s, h->offset.mem_offset, h->length); } return s; } - + return NULL; } -int help_add_mem( help_t **help, const char *title, const char *content ) +int help_add_mem(help_t **help, const char *title, const char *content) { help_t *h, *l = NULL; - - for( h = *help; h; h = h->next ) - { - if( g_strcasecmp( h->title, title ) == 0 ) + + for (h = *help; h; h = h->next) { + if (g_strcasecmp(h->title, title) == 0) { return 0; - + } + l = h; } - - if( l ) - h = l->next = g_new0( struct help, 1 ); - else - *help = h = g_new0( struct help, 1 ); + + if (l) { + h = l->next = g_new0(struct help, 1); + } else { + *help = h = g_new0(struct help, 1); + } h->fd = -1; - h->title = g_strdup( title ); - h->length = strlen( content ); - h->offset.mem_offset = g_strdup( content ); - + h->title = g_strdup(title); + h->length = strlen(content); + h->offset.mem_offset = g_strdup(content); + return 1; } -char *help_get_whatsnew( help_t **help, int old ) +char *help_get_whatsnew(help_t **help, int old) { GString *ret = NULL; help_t *h; int v; - - for( h = *help; h; h = h->next ) - if( h->title != NULL && strncmp( h->title, "whatsnew", 8 ) == 0 && - sscanf( h->title + 8, "%x", &v ) == 1 && v > old ) - { - char *s = help_get( &h, h->title ); - if( ret == NULL ) - ret = g_string_new( s ); - else - g_string_append_printf( ret, "\n\n%s", s ); - g_free( s ); + + for (h = *help; h; h = h->next) { + if (h->title != NULL && strncmp(h->title, "whatsnew", 8) == 0 && + sscanf(h->title + 8, "%x", &v) == 1 && v > old) { + char *s = help_get(&h, h->title); + if (ret == NULL) { + ret = g_string_new(s); + } else { + g_string_append_printf(ret, "\n\n%s", s); + } + g_free(s); } - - return ret ? g_string_free( ret, FALSE ) : NULL; + } + + return ret ? g_string_free(ret, FALSE) : NULL; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -26,14 +26,12 @@ #ifndef _HELP_H #define _HELP_H -typedef union -{ +typedef union { off_t file_offset; char *mem_offset; } help_off_t; -typedef struct help -{ +typedef struct help { int fd; time_t mtime; char *title; @@ -42,10 +40,10 @@ typedef struct help struct help *next; } help_t; -G_GNUC_MALLOC help_t *help_init( help_t **help, const char *helpfile ); -void help_free( help_t **help ); -char *help_get( help_t **help, char *title ); -int help_add_mem( help_t **help, const char *title, const char *content_ ); -char *help_get_whatsnew( help_t **help, int old ); +G_GNUC_MALLOC help_t *help_init(help_t **help, const char *helpfile); +void help_free(help_t **help); +char *help_get(help_t **help, char *title); +int help_add_mem(help_t **help, const char *title, const char *content_); +char *help_get_whatsnew(help_t **help, int old); #endif @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -33,8 +33,8 @@ GSList *child_list = NULL; static int ipc_child_recv_fd = -1; -static void ipc_master_takeover_fail( struct bitlbee_child *child, gboolean both ); -static gboolean ipc_send_fd( int fd, int send_fd ); +static void ipc_master_takeover_fail(struct bitlbee_child *child, gboolean both); +static gboolean ipc_send_fd(int fd, int send_fd); /* On Solaris and possibly other systems passing FDs between processes is * not possible (or at least not using the method used in this file. @@ -43,188 +43,183 @@ static gboolean ipc_send_fd( int fd, int send_fd ); #define CMSG_SPACE(len) 1 #endif -static void ipc_master_cmd_client( irc_t *data, char **cmd ) +static void ipc_master_cmd_client(irc_t *data, char **cmd) { /* Normally data points at an irc_t block, but for the IPC master this is different. We think this scary cast is better than creating a new command_t structure, just to make the compiler happy. */ - struct bitlbee_child *child = (void*) data; - - if( child && cmd[1] ) - { - child->host = g_strdup( cmd[1] ); - child->nick = g_strdup( cmd[2] ); - child->realname = g_strdup( cmd[3] ); - } - + struct bitlbee_child *child = (void *) data; + + if (child && cmd[1]) { + child->host = g_strdup(cmd[1]); + child->nick = g_strdup(cmd[2]); + child->realname = g_strdup(cmd[3]); + } + /* CLIENT == On initial connects, HELLO is after /RESTARTs. */ - if( g_strcasecmp( cmd[0], "CLIENT" ) == 0 ) - ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n", - (int) ( child ? child->pid : -1 ), cmd[2], cmd[1], cmd[3] ); + if (g_strcasecmp(cmd[0], "CLIENT") == 0) { + ipc_to_children_str("OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n", + (int) (child ? child->pid : -1), cmd[2], cmd[1], cmd[3]); + } } -static void ipc_master_cmd_nick( irc_t *data, char **cmd ) +static void ipc_master_cmd_nick(irc_t *data, char **cmd) { - struct bitlbee_child *child = (void*) data; - - if( child && cmd[1] ) - { - g_free( child->nick ); - child->nick = g_strdup( cmd[1] ); + struct bitlbee_child *child = (void *) data; + + if (child && cmd[1]) { + g_free(child->nick); + child->nick = g_strdup(cmd[1]); } } -static void ipc_master_cmd_die( irc_t *data, char **cmd ) +static void ipc_master_cmd_die(irc_t *data, char **cmd) { - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - ipc_to_children_str( "DIE\r\n" ); - - bitlbee_shutdown( NULL, -1, 0 ); + if (global.conf->runmode == RUNMODE_FORKDAEMON) { + ipc_to_children_str("DIE\r\n"); + } + + bitlbee_shutdown(NULL, -1, 0); } -static void ipc_master_cmd_deaf( irc_t *data, char **cmd ) +static void ipc_master_cmd_deaf(irc_t *data, char **cmd) { - if( global.conf->runmode == RUNMODE_DAEMON ) - { - b_event_remove( global.listen_watch_source_id ); - close( global.listen_socket ); - + if (global.conf->runmode == RUNMODE_DAEMON) { + b_event_remove(global.listen_watch_source_id); + close(global.listen_socket); + global.listen_socket = global.listen_watch_source_id = -1; - - ipc_to_children_str( "OPERMSG :Closed listening socket, waiting " - "for all users to disconnect." ); - } - else - { - ipc_to_children_str( "OPERMSG :The DEAF command only works in " - "normal daemon mode. Try DIE instead." ); + + ipc_to_children_str("OPERMSG :Closed listening socket, waiting " + "for all users to disconnect."); + } else { + ipc_to_children_str("OPERMSG :The DEAF command only works in " + "normal daemon mode. Try DIE instead."); } } -void ipc_master_cmd_rehash( irc_t *data, char **cmd ) +void ipc_master_cmd_rehash(irc_t *data, char **cmd) { runmode_t oldmode; - + oldmode = global.conf->runmode; - - g_free( global.conf ); - global.conf = conf_load( 0, NULL ); - - if( global.conf->runmode != oldmode ) - { - log_message( LOGLVL_WARNING, "Can't change RunMode setting at runtime, restoring original setting" ); + + g_free(global.conf); + global.conf = conf_load(0, NULL); + + if (global.conf->runmode != oldmode) { + log_message(LOGLVL_WARNING, "Can't change RunMode setting at runtime, restoring original setting"); global.conf->runmode = oldmode; } - - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - ipc_to_children( cmd ); + + if (global.conf->runmode == RUNMODE_FORKDAEMON) { + ipc_to_children(cmd); + } } -void ipc_master_cmd_restart( irc_t *data, char **cmd ) +void ipc_master_cmd_restart(irc_t *data, char **cmd) { - if( global.conf->runmode != RUNMODE_FORKDAEMON ) - { + if (global.conf->runmode != RUNMODE_FORKDAEMON) { /* Tell child that this is unsupported. */ return; } - + global.restart = -1; - bitlbee_shutdown( NULL, -1, 0 ); + bitlbee_shutdown(NULL, -1, 0); } -void ipc_master_cmd_identify( irc_t *data, char **cmd ) +void ipc_master_cmd_identify(irc_t *data, char **cmd) { - struct bitlbee_child *child = (void*) data, *old = NULL; + struct bitlbee_child *child = (void *) data, *old = NULL; char *resp; GSList *l; - - if( !child || !child->nick || strcmp( child->nick, cmd[1] ) != 0 ) + + if (!child || !child->nick || strcmp(child->nick, cmd[1]) != 0) { return; - - g_free( child->password ); - child->password = g_strdup( cmd[2] ); - - for( l = child_list; l; l = l->next ) - { + } + + g_free(child->password); + child->password = g_strdup(cmd[2]); + + for (l = child_list; l; l = l->next) { old = l->data; - if( child != old && - old->nick && nick_cmp( NULL, old->nick, child->nick ) == 0 && - old->password && strcmp( old->password, child->password ) == 0 ) + if (child != old && + old->nick && nick_cmp(NULL, old->nick, child->nick) == 0 && + old->password && strcmp(old->password, child->password) == 0) { break; + } } - - if( l && !child->to_child && !old->to_child ) - { + + if (l && !child->to_child && !old->to_child) { resp = "TAKEOVER INIT\r\n"; child->to_child = old; old->to_child = child; - } - else - { + } else { /* Won't need the fd since we can't send it anywhere. */ - closesocket( child->to_fd ); + closesocket(child->to_fd); child->to_fd = -1; resp = "TAKEOVER NO\r\n"; } - - if( write( child->ipc_fd, resp, strlen( resp ) ) != strlen( resp ) ) - ipc_master_free_one( child ); + + if (write(child->ipc_fd, resp, strlen(resp)) != strlen(resp)) { + ipc_master_free_one(child); + } } -void ipc_master_cmd_takeover( irc_t *data, char **cmd ) +void ipc_master_cmd_takeover(irc_t *data, char **cmd) { - struct bitlbee_child *child = (void*) data; + struct bitlbee_child *child = (void *) data; char *fwd = NULL; - + /* Normal daemon mode doesn't keep these and has simplified code for takeovers. */ - if( child == NULL ) + if (child == NULL) { return; - - if( child->to_child == NULL || - g_slist_find( child_list, child->to_child ) == NULL ) - return ipc_master_takeover_fail( child, FALSE ); - - if( strcmp( cmd[1], "AUTH" ) == 0 ) - { + } + + if (child->to_child == NULL || + g_slist_find(child_list, child->to_child) == NULL) { + return ipc_master_takeover_fail(child, FALSE); + } + + if (strcmp(cmd[1], "AUTH") == 0) { /* New connection -> Master */ - if( child->to_child && + if (child->to_child && child->nick && child->to_child->nick && cmd[2] && child->password && child->to_child->password && cmd[3] && - strcmp( child->nick, child->to_child->nick ) == 0 && - strcmp( child->nick, cmd[2] ) == 0 && - strcmp( child->password, child->to_child->password ) == 0 && - strcmp( child->password, cmd[3] ) == 0 ) - { - ipc_send_fd( child->to_child->ipc_fd, child->to_fd ); - - fwd = irc_build_line( cmd ); - if( write( child->to_child->ipc_fd, fwd, strlen( fwd ) ) != strlen( fwd ) ) - ipc_master_free_one( child ); - g_free( fwd ); + strcmp(child->nick, child->to_child->nick) == 0 && + strcmp(child->nick, cmd[2]) == 0 && + strcmp(child->password, child->to_child->password) == 0 && + strcmp(child->password, cmd[3]) == 0) { + ipc_send_fd(child->to_child->ipc_fd, child->to_fd); + + fwd = irc_build_line(cmd); + if (write(child->to_child->ipc_fd, fwd, strlen(fwd)) != strlen(fwd)) { + ipc_master_free_one(child); + } + g_free(fwd); + } else { + return ipc_master_takeover_fail(child, TRUE); } - else - return ipc_master_takeover_fail( child, TRUE ); - } - else if( strcmp( cmd[1], "DONE" ) == 0 || strcmp( cmd[1], "FAIL" ) == 0 ) - { + } else if (strcmp(cmd[1], "DONE") == 0 || strcmp(cmd[1], "FAIL") == 0) { /* Old connection -> Master */ int fd; - + /* The copy was successful (or not), we don't need it anymore. */ - closesocket( child->to_fd ); + closesocket(child->to_fd); child->to_fd = -1; - + /* Pass it through to the other party, and flush all state. */ - fwd = irc_build_line( cmd ); + fwd = irc_build_line(cmd); fd = child->to_child->ipc_fd; child->to_child->to_child = NULL; child->to_child = NULL; - if( write( fd, fwd, strlen( fwd ) ) != strlen( fwd ) ) - ipc_master_free_one( child ); - g_free( fwd ); + if (write(fd, fwd, strlen(fwd)) != strlen(fwd)) { + ipc_master_free_one(child); + } + g_free(fwd); } } @@ -246,192 +241,188 @@ static const command_t ipc_master_commands[] = { }; -static void ipc_child_cmd_die( irc_t *irc, char **cmd ) +static void ipc_child_cmd_die(irc_t *irc, char **cmd) { - irc_abort( irc, 0, "Shutdown requested by operator" ); + irc_abort(irc, 0, "Shutdown requested by operator"); } -static void ipc_child_cmd_wallops( irc_t *irc, char **cmd ) +static void ipc_child_cmd_wallops(irc_t *irc, char **cmd) { - if( !( irc->status & USTATUS_LOGGED_IN ) ) + if (!(irc->status & USTATUS_LOGGED_IN)) { return; - - if( strchr( irc->umode, 'w' ) ) - irc_write( irc, ":%s WALLOPS :%s", irc->root->host, cmd[1] ); + } + + if (strchr(irc->umode, 'w')) { + irc_write(irc, ":%s WALLOPS :%s", irc->root->host, cmd[1]); + } } -static void ipc_child_cmd_wall( irc_t *irc, char **cmd ) +static void ipc_child_cmd_wall(irc_t *irc, char **cmd) { - if( !( irc->status & USTATUS_LOGGED_IN ) ) + if (!(irc->status & USTATUS_LOGGED_IN)) { return; - - if( strchr( irc->umode, 's' ) ) - irc_write( irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1] ); + } + + if (strchr(irc->umode, 's')) { + irc_write(irc, ":%s NOTICE %s :%s", irc->root->host, irc->user->nick, cmd[1]); + } } -static void ipc_child_cmd_opermsg( irc_t *irc, char **cmd ) +static void ipc_child_cmd_opermsg(irc_t *irc, char **cmd) { - if( !( irc->status & USTATUS_LOGGED_IN ) ) + if (!(irc->status & USTATUS_LOGGED_IN)) { return; - - if( strchr( irc->umode, 'o' ) ) - irc_write( irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1] ); + } + + if (strchr(irc->umode, 'o')) { + irc_write(irc, ":%s NOTICE %s :*** OperMsg *** %s", irc->root->host, irc->user->nick, cmd[1]); + } } -static void ipc_child_cmd_rehash( irc_t *irc, char **cmd ) +static void ipc_child_cmd_rehash(irc_t *irc, char **cmd) { runmode_t oldmode; - + oldmode = global.conf->runmode; - - g_free( global.conf ); - global.conf = conf_load( 0, NULL ); - + + g_free(global.conf); + global.conf = conf_load(0, NULL); + global.conf->runmode = oldmode; } -static void ipc_child_cmd_kill( irc_t *irc, char **cmd ) +static void ipc_child_cmd_kill(irc_t *irc, char **cmd) { - if( !( irc->status & USTATUS_LOGGED_IN ) ) + if (!(irc->status & USTATUS_LOGGED_IN)) { return; - - if( nick_cmp( NULL, cmd[1], irc->user->nick ) != 0 ) - return; /* It's not for us. */ - - irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, cmd[2] ); - irc_abort( irc, 0, "Killed by operator: %s", cmd[2] ); + } + + if (nick_cmp(NULL, cmd[1], irc->user->nick) != 0) { + return; /* It's not for us. */ + + } + irc_write(irc, ":%s!%s@%s KILL %s :%s", irc->root->nick, irc->root->nick, irc->root->host, irc->user->nick, + cmd[2]); + irc_abort(irc, 0, "Killed by operator: %s", cmd[2]); } -static void ipc_child_cmd_hello( irc_t *irc, char **cmd ) +static void ipc_child_cmd_hello(irc_t *irc, char **cmd) { - if( !( irc->status & USTATUS_LOGGED_IN ) ) - ipc_to_master_str( "HELLO\r\n" ); - else - ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); + if (!(irc->status & USTATUS_LOGGED_IN)) { + ipc_to_master_str("HELLO\r\n"); + } else { + ipc_to_master_str("HELLO %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname); + } } -static void ipc_child_cmd_takeover_yes( void *data ); -static void ipc_child_cmd_takeover_no( void *data ); +static void ipc_child_cmd_takeover_yes(void *data); +static void ipc_child_cmd_takeover_no(void *data); -static void ipc_child_cmd_takeover( irc_t *irc, char **cmd ) +static void ipc_child_cmd_takeover(irc_t *irc, char **cmd) { - if( strcmp( cmd[1], "NO" ) == 0 ) - { + if (strcmp(cmd[1], "NO") == 0) { /* Master->New connection */ /* No takeover, finish the login. */ - } - else if( strcmp( cmd[1], "INIT" ) == 0 ) - { + } else if (strcmp(cmd[1], "INIT") == 0) { /* Master->New connection */ - if( !set_getbool( &irc->b->set, "allow_takeover" ) ) - { - ipc_child_cmd_takeover_no( irc ); + if (!set_getbool(&irc->b->set, "allow_takeover")) { + ipc_child_cmd_takeover_no(irc); return; } - + /* Offer to take over the old session, unless for some reason we're already logging into IM connections. */ - if( irc->login_source_id != -1 ) - query_add( irc, NULL, - "You're already connected to this server. " - "Would you like to take over this session?", - ipc_child_cmd_takeover_yes, - ipc_child_cmd_takeover_no, NULL, irc ); - + if (irc->login_source_id != -1) { + query_add(irc, NULL, + "You're already connected to this server. " + "Would you like to take over this session?", + ipc_child_cmd_takeover_yes, + ipc_child_cmd_takeover_no, NULL, irc); + } + /* This one's going to connect to accounts, avoid that. */ - b_event_remove( irc->login_source_id ); + b_event_remove(irc->login_source_id); irc->login_source_id = -1; - } - else if( strcmp( cmd[1], "AUTH" ) == 0 ) - { + } else if (strcmp(cmd[1], "AUTH") == 0) { /* Master->Old connection */ - if( irc->password && cmd[2] && cmd[3] && + if (irc->password && cmd[2] && cmd[3] && ipc_child_recv_fd != -1 && - strcmp( irc->user->nick, cmd[2] ) == 0 && - strcmp( irc->password, cmd[3] ) == 0 && - set_getbool( &irc->b->set, "allow_takeover" ) ) - { - irc_switch_fd( irc, ipc_child_recv_fd ); - irc_sync( irc ); - irc_rootmsg( irc, "You've successfully taken over your old session" ); + strcmp(irc->user->nick, cmd[2]) == 0 && + strcmp(irc->password, cmd[3]) == 0 && + set_getbool(&irc->b->set, "allow_takeover")) { + irc_switch_fd(irc, ipc_child_recv_fd); + irc_sync(irc); + irc_rootmsg(irc, "You've successfully taken over your old session"); ipc_child_recv_fd = -1; - - ipc_to_master_str( "TAKEOVER DONE\r\n" ); - } - else - { - ipc_to_master_str( "TAKEOVER FAIL\r\n" ); + + ipc_to_master_str("TAKEOVER DONE\r\n"); + } else { + ipc_to_master_str("TAKEOVER FAIL\r\n"); } - } - else if( strcmp( cmd[1], "DONE" ) == 0 ) - { + } else if (strcmp(cmd[1], "DONE") == 0) { /* Master->New connection (now taken over by old process) */ - irc_free( irc ); - } - else if( strcmp( cmd[1], "FAIL" ) == 0 ) - { + irc_free(irc); + } else if (strcmp(cmd[1], "FAIL") == 0) { /* Master->New connection */ - irc_rootmsg( irc, "Could not take over old session" ); + irc_rootmsg(irc, "Could not take over old session"); } } -static void ipc_child_cmd_takeover_yes( void *data ) +static void ipc_child_cmd_takeover_yes(void *data) { irc_t *irc = data, *old = NULL; char *to_auth[] = { "TAKEOVER", "AUTH", irc->user->nick, irc->password, NULL }; - + /* Master->New connection */ - ipc_to_master_str( "TAKEOVER AUTH %s :%s\r\n", - irc->user->nick, irc->password ); - - if( global.conf->runmode == RUNMODE_DAEMON ) - { + ipc_to_master_str("TAKEOVER AUTH %s :%s\r\n", + irc->user->nick, irc->password); + + if (global.conf->runmode == RUNMODE_DAEMON) { GSList *l; - - for( l = irc_connection_list; l; l = l->next ) - { + + for (l = irc_connection_list; l; l = l->next) { old = l->data; - - if( irc != old && + + if (irc != old && irc->user->nick && old->user->nick && irc->password && old->password && - strcmp( irc->user->nick, old->user->nick ) == 0 && - strcmp( irc->password, old->password ) == 0 ) + strcmp(irc->user->nick, old->user->nick) == 0 && + strcmp(irc->password, old->password) == 0) { break; + } } - if( l == NULL ) - { + if (l == NULL) { to_auth[1] = "FAIL"; - ipc_child_cmd_takeover( irc, to_auth ); + ipc_child_cmd_takeover(irc, to_auth); return; } } - + /* Drop credentials, we'll shut down soon and shouldn't overwrite any settings. */ - irc_rootmsg( irc, "Trying to take over existing session" ); - - irc_desync( irc ); - - if( old ) - { - ipc_child_recv_fd = dup( irc->fd ); - ipc_child_cmd_takeover( old, to_auth ); - } - + irc_rootmsg(irc, "Trying to take over existing session"); + + irc_desync(irc); + + if (old) { + ipc_child_recv_fd = dup(irc->fd); + ipc_child_cmd_takeover(old, to_auth); + } + /* TODO: irc_setpass() should do all of this. */ - irc_setpass( irc, NULL ); + irc_setpass(irc, NULL); irc->status &= ~USTATUS_IDENTIFIED; - irc_umode_set( irc, "-R", 1 ); - - if( old ) - irc_abort( irc, FALSE, NULL ); + irc_umode_set(irc, "-R", 1); + + if (old) { + irc_abort(irc, FALSE, NULL); + } } -static void ipc_child_cmd_takeover_no( void *data ) +static void ipc_child_cmd_takeover_no(void *data) { - ipc_to_master_str( "TAKEOVER NO\r\n" ); - cmd_identify_finish( data, 0, 0 ); + ipc_to_master_str("TAKEOVER NO\r\n"); + cmd_identify_finish(data, 0, 0); } static const command_t ipc_child_commands[] = { @@ -446,102 +437,105 @@ static const command_t ipc_child_commands[] = { { NULL } }; -gboolean ipc_child_identify( irc_t *irc ) +gboolean ipc_child_identify(irc_t *irc) { - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { + if (global.conf->runmode == RUNMODE_FORKDAEMON) { #ifndef NO_FD_PASSING - if( !ipc_send_fd( global.listen_socket, irc->fd ) ) + if (!ipc_send_fd(global.listen_socket, irc->fd)) { ipc_child_disable(); - - ipc_to_master_str( "IDENTIFY %s :%s\r\n", irc->user->nick, irc->password ); + } + + ipc_to_master_str("IDENTIFY %s :%s\r\n", irc->user->nick, irc->password); #endif - + return TRUE; - } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { + } else if (global.conf->runmode == RUNMODE_DAEMON) { GSList *l; irc_t *old = NULL; char *to_init[] = { "TAKEOVER", "INIT", NULL }; - - for( l = irc_connection_list; l; l = l->next ) - { + + for (l = irc_connection_list; l; l = l->next) { old = l->data; - - if( irc != old && + + if (irc != old && irc->user->nick && old->user->nick && irc->password && old->password && - strcmp( irc->user->nick, old->user->nick ) == 0 && - strcmp( irc->password, old->password ) == 0 ) + strcmp(irc->user->nick, old->user->nick) == 0 && + strcmp(irc->password, old->password) == 0) { break; + } } - if( l == NULL || old == NULL || - !set_getbool( &irc->b->set, "allow_takeover" ) || - !set_getbool( &old->b->set, "allow_takeover" ) ) + if (l == NULL || old == NULL || + !set_getbool(&irc->b->set, "allow_takeover") || + !set_getbool(&old->b->set, "allow_takeover")) { return FALSE; - - ipc_child_cmd_takeover( irc, to_init ); - + } + + ipc_child_cmd_takeover(irc, to_init); + return TRUE; - } - else + } else { return FALSE; + } } -static void ipc_master_takeover_fail( struct bitlbee_child *child, gboolean both ) +static void ipc_master_takeover_fail(struct bitlbee_child *child, gboolean both) { - if( child == NULL || g_slist_find( child_list, child ) == NULL ) + if (child == NULL || g_slist_find(child_list, child) == NULL) { return; - - if( both && child->to_child != NULL ) - ipc_master_takeover_fail( child->to_child, FALSE ); - - if( child->to_fd > -1 ) - { + } + + if (both && child->to_child != NULL) { + ipc_master_takeover_fail(child->to_child, FALSE); + } + + if (child->to_fd > -1) { /* Send this error only to the new connection, which can be recognised by to_fd being set. */ - if( write( child->ipc_fd, "TAKEOVER FAIL\r\n", 15 ) != 15 ) - { - ipc_master_free_one( child ); + if (write(child->ipc_fd, "TAKEOVER FAIL\r\n", 15) != 15) { + ipc_master_free_one(child); return; } - close( child->to_fd ); + close(child->to_fd); child->to_fd = -1; } child->to_child = NULL; } -static void ipc_command_exec( void *data, char **cmd, const command_t *commands ) +static void ipc_command_exec(void *data, char **cmd, const command_t *commands) { int i, j; - - if( !cmd[0] ) + + if (!cmd[0]) { return; - - for( i = 0; commands[i].command; i ++ ) - if( g_strcasecmp( commands[i].command, cmd[0] ) == 0 ) - { + } + + for (i = 0; commands[i].command; i++) { + if (g_strcasecmp(commands[i].command, cmd[0]) == 0) { /* There is no typo in this line: */ - for( j = 1; cmd[j]; j ++ ) + for (j = 1; cmd[j]; j++) { ; + } j--; - - if( j < commands[i].required_parameters ) + + if (j < commands[i].required_parameters) { break; - - if( commands[i].flags & IPC_CMD_TO_CHILDREN ) - ipc_to_children( cmd ); - else - commands[i].execute( data, cmd ); - + } + + if (commands[i].flags & IPC_CMD_TO_CHILDREN) { + ipc_to_children(cmd); + } else { + commands[i].execute(data, cmd); + } + break; } + } } /* Return just one line. Returns NULL if something broke, an empty string on temporary "errors" (EAGAIN and friends). */ -static char *ipc_readline( int fd, int *recv_fd ) +static char *ipc_readline(int fd, int *recv_fd) { struct msghdr msg; struct iovec iov; @@ -549,280 +543,265 @@ static char *ipc_readline( int fd, int *recv_fd ) struct cmsghdr *cmsg; char buf[513], *eol; int size; - + /* Because this is internal communication, it should be pretty safe to just peek at the message, find its length (by searching for the end-of-line) and then just read that message. With internal sockets and limites message length, messages should always be complete. Saves us quite a lot of code and buffering. */ - size = recv( fd, buf, sizeof( buf ) - 1, MSG_PEEK ); - if( size == 0 || ( size < 0 && !sockerr_again() ) ) + size = recv(fd, buf, sizeof(buf) - 1, MSG_PEEK); + if (size == 0 || (size < 0 && !sockerr_again())) { return NULL; - else if( size < 0 ) /* && sockerr_again() */ - return( g_strdup( "" ) ); - else + } else if (size < 0) { /* && sockerr_again() */ + return(g_strdup("")); + } else { buf[size] = 0; - - if( ( eol = strstr( buf, "\r\n" ) ) == NULL ) + } + + if ((eol = strstr(buf, "\r\n")) == NULL) { return NULL; - else + } else { size = eol - buf + 2; - + } + iov.iov_base = buf; iov.iov_len = size; - - memset( &msg, 0, sizeof( msg ) ); + + memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; #ifndef NO_FD_PASSING msg.msg_control = ccmsg; - msg.msg_controllen = sizeof( ccmsg ); + msg.msg_controllen = sizeof(ccmsg); #endif - - if( recvmsg( fd, &msg, 0 ) != size ) + + if (recvmsg(fd, &msg, 0) != size) { return NULL; - + } + #ifndef NO_FD_PASSING - if( recv_fd ) - for( cmsg = CMSG_FIRSTHDR( &msg ); cmsg; cmsg = CMSG_NXTHDR( &msg, cmsg ) ) - if( cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS ) - { + if (recv_fd) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { /* Getting more than one shouldn't happen but if it does, make sure we don't leave them around. */ - if( *recv_fd != -1 ) - close( *recv_fd ); - - *recv_fd = *(int*) CMSG_DATA( cmsg ); + if (*recv_fd != -1) { + close(*recv_fd); + } + + *recv_fd = *(int *) CMSG_DATA(cmsg); /* fprintf( stderr, "pid %d received fd %d\n", (int) getpid(), *recv_fd ); */ } + } + } #endif - + /* fprintf( stderr, "pid %d received: %s", (int) getpid(), buf ); */ - return g_strndup( buf, size - 2 ); + return g_strndup(buf, size - 2); } -gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ) +gboolean ipc_master_read(gpointer data, gint source, b_input_condition cond) { struct bitlbee_child *child = data; char *buf, **cmd; - - if( ( buf = ipc_readline( source, &child->to_fd ) ) ) - { - cmd = irc_parse_line( buf ); - if( cmd ) - { - ipc_command_exec( child, cmd, ipc_master_commands ); - g_free( cmd ); + + if ((buf = ipc_readline(source, &child->to_fd))) { + cmd = irc_parse_line(buf); + if (cmd) { + ipc_command_exec(child, cmd, ipc_master_commands); + g_free(cmd); } - g_free( buf ); - } - else - { - ipc_master_free_fd( source ); + g_free(buf); + } else { + ipc_master_free_fd(source); } - + return TRUE; } -gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ) +gboolean ipc_child_read(gpointer data, gint source, b_input_condition cond) { char *buf, **cmd; - - if( ( buf = ipc_readline( source, &ipc_child_recv_fd ) ) ) - { - cmd = irc_parse_line( buf ); - if( cmd ) - { - ipc_command_exec( data, cmd, ipc_child_commands ); - g_free( cmd ); + + if ((buf = ipc_readline(source, &ipc_child_recv_fd))) { + cmd = irc_parse_line(buf); + if (cmd) { + ipc_command_exec(data, cmd, ipc_child_commands); + g_free(cmd); } - g_free( buf ); - } - else - { + g_free(buf); + } else { ipc_child_disable(); } - + return TRUE; } -void ipc_to_master( char **cmd ) +void ipc_to_master(char **cmd) { - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { - char *s = irc_build_line( cmd ); - ipc_to_master_str( "%s", s ); - g_free( s ); - } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { - ipc_command_exec( NULL, cmd, ipc_master_commands ); + if (global.conf->runmode == RUNMODE_FORKDAEMON) { + char *s = irc_build_line(cmd); + ipc_to_master_str("%s", s); + g_free(s); + } else if (global.conf->runmode == RUNMODE_DAEMON) { + ipc_command_exec(NULL, cmd, ipc_master_commands); } } -void ipc_to_master_str( char *format, ... ) +void ipc_to_master_str(char *format, ...) { char *msg_buf; va_list params; - va_start( params, format ); - msg_buf = g_strdup_vprintf( format, params ); - va_end( params ); - - if( strlen( msg_buf ) > 512 ) - { + va_start(params, format); + msg_buf = g_strdup_vprintf(format, params); + va_end(params); + + if (strlen(msg_buf) > 512) { /* Don't send it, it's too long... */ - } - else if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { - if( global.listen_socket >= 0 ) - if( write( global.listen_socket, msg_buf, strlen( msg_buf ) ) <= 0 ) + } else if (global.conf->runmode == RUNMODE_FORKDAEMON) { + if (global.listen_socket >= 0) { + if (write(global.listen_socket, msg_buf, strlen(msg_buf)) <= 0) { ipc_child_disable(); - } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { + } + } + } else if (global.conf->runmode == RUNMODE_DAEMON) { char **cmd, *s; - - if( ( s = strchr( msg_buf, '\r' ) ) ) + + if ((s = strchr(msg_buf, '\r'))) { *s = 0; - - cmd = irc_parse_line( msg_buf ); - ipc_command_exec( NULL, cmd, ipc_master_commands ); - g_free( cmd ); + } + + cmd = irc_parse_line(msg_buf); + ipc_command_exec(NULL, cmd, ipc_master_commands); + g_free(cmd); } - - g_free( msg_buf ); + + g_free(msg_buf); } -void ipc_to_children( char **cmd ) +void ipc_to_children(char **cmd) { - if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { - char *msg_buf = irc_build_line( cmd ); - ipc_to_children_str( "%s", msg_buf ); - g_free( msg_buf ); - } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { + if (global.conf->runmode == RUNMODE_FORKDAEMON) { + char *msg_buf = irc_build_line(cmd); + ipc_to_children_str("%s", msg_buf); + g_free(msg_buf); + } else if (global.conf->runmode == RUNMODE_DAEMON) { GSList *l; - - for( l = irc_connection_list; l; l = l->next ) - ipc_command_exec( l->data, cmd, ipc_child_commands ); + + for (l = irc_connection_list; l; l = l->next) { + ipc_command_exec(l->data, cmd, ipc_child_commands); + } } } -void ipc_to_children_str( char *format, ... ) +void ipc_to_children_str(char *format, ...) { char *msg_buf; va_list params; - va_start( params, format ); - msg_buf = g_strdup_vprintf( format, params ); - va_end( params ); - - if( strlen( msg_buf ) > 512 ) - { + va_start(params, format); + msg_buf = g_strdup_vprintf(format, params); + va_end(params); + + if (strlen(msg_buf) > 512) { /* Don't send it, it's too long... */ - } - else if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { - int msg_len = strlen( msg_buf ); + } else if (global.conf->runmode == RUNMODE_FORKDAEMON) { + int msg_len = strlen(msg_buf); GSList *l, *next; - - for( l = child_list; l; l = next ) - { + + for (l = child_list; l; l = next) { struct bitlbee_child *c = l->data; - + next = l->next; - if( write( c->ipc_fd, msg_buf, msg_len ) <= 0 ) - ipc_master_free_one( c ); + if (write(c->ipc_fd, msg_buf, msg_len) <= 0) { + ipc_master_free_one(c); + } } - } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { + } else if (global.conf->runmode == RUNMODE_DAEMON) { char **cmd, *s; - - if( ( s = strchr( msg_buf, '\r' ) ) ) + + if ((s = strchr(msg_buf, '\r'))) { *s = 0; - - cmd = irc_parse_line( msg_buf ); - ipc_to_children( cmd ); - g_free( cmd ); + } + + cmd = irc_parse_line(msg_buf); + ipc_to_children(cmd); + g_free(cmd); } - - g_free( msg_buf ); + + g_free(msg_buf); } -static gboolean ipc_send_fd( int fd, int send_fd ) +static gboolean ipc_send_fd(int fd, int send_fd) { struct msghdr msg; struct iovec iov; char ccmsg[CMSG_SPACE(sizeof(fd))]; struct cmsghdr *cmsg; - - memset( &msg, 0, sizeof( msg ) ); + + memset(&msg, 0, sizeof(msg)); iov.iov_base = "0x90\r\n"; /* Ja, noppes */ iov.iov_len = 6; msg.msg_iov = &iov; msg.msg_iovlen = 1; - + #ifndef NO_FD_PASSING msg.msg_control = ccmsg; - msg.msg_controllen = sizeof( ccmsg ); - cmsg = CMSG_FIRSTHDR( &msg ); + msg.msg_controllen = sizeof(ccmsg); + cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN( sizeof( send_fd ) ); - *(int*)CMSG_DATA( cmsg ) = send_fd; + cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd)); + *(int *) CMSG_DATA(cmsg) = send_fd; msg.msg_controllen = cmsg->cmsg_len; #endif - - return sendmsg( fd, &msg, 0 ) == 6; + + return sendmsg(fd, &msg, 0) == 6; } -void ipc_master_free_one( struct bitlbee_child *c ) +void ipc_master_free_one(struct bitlbee_child *c) { GSList *l; - - b_event_remove( c->ipc_inpa ); - closesocket( c->ipc_fd ); - - if( c->to_fd != -1 ) - close( c->to_fd ); - - g_free( c->host ); - g_free( c->nick ); - g_free( c->realname ); - g_free( c->password ); - g_free( c ); - - child_list = g_slist_remove( child_list, c ); - + + b_event_remove(c->ipc_inpa); + closesocket(c->ipc_fd); + + if (c->to_fd != -1) { + close(c->to_fd); + } + + g_free(c->host); + g_free(c->nick); + g_free(c->realname); + g_free(c->password); + g_free(c); + + child_list = g_slist_remove(child_list, c); + /* Also, if any child has a reference to this one, remove it. */ - for( l = child_list; l; l = l->next ) - { + for (l = child_list; l; l = l->next) { struct bitlbee_child *oc = l->data; - - if( oc->to_child == c ) - ipc_master_takeover_fail( oc, FALSE ); + + if (oc->to_child == c) { + ipc_master_takeover_fail(oc, FALSE); + } } } -void ipc_master_free_fd( int fd ) +void ipc_master_free_fd(int fd) { GSList *l; struct bitlbee_child *c; - - for( l = child_list; l; l = l->next ) - { + + for (l = child_list; l; l = l->next) { c = l->data; - if( c->ipc_fd == fd ) - { - ipc_master_free_one( c ); + if (c->ipc_fd == fd) { + ipc_master_free_one(c); break; } } @@ -830,75 +809,73 @@ void ipc_master_free_fd( int fd ) void ipc_master_free_all() { - while( child_list ) - ipc_master_free_one( child_list->data ); + while (child_list) { + ipc_master_free_one(child_list->data); + } } void ipc_child_disable() { - b_event_remove( global.listen_watch_source_id ); - close( global.listen_socket ); - + b_event_remove(global.listen_watch_source_id); + close(global.listen_socket); + global.listen_socket = -1; } char *ipc_master_save_state() { - char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" ); - int fd = mkstemp( fn ); + char *fn = g_strdup("/tmp/bee-restart.XXXXXX"); + int fd = mkstemp(fn); GSList *l; FILE *fp; int i; - - if( fd == -1 ) - { - log_message( LOGLVL_ERROR, "Could not create temporary file: %s", strerror( errno ) ); - g_free( fn ); + + if (fd == -1) { + log_message(LOGLVL_ERROR, "Could not create temporary file: %s", strerror(errno)); + g_free(fn); return NULL; } - + /* This is more convenient now. */ - fp = fdopen( fd, "w" ); - - for( l = child_list, i = 0; l; l = l->next ) - i ++; - + fp = fdopen(fd, "w"); + + for (l = child_list, i = 0; l; l = l->next) { + i++; + } + /* Number of client processes. */ - fprintf( fp, "%d\n", i ); - - for( l = child_list; l; l = l->next ) - fprintf( fp, "%d %d\n", (int) ((struct bitlbee_child*)l->data)->pid, - ((struct bitlbee_child*)l->data)->ipc_fd ); - - if( fclose( fp ) == 0 ) - { - return fn; + fprintf(fp, "%d\n", i); + + for (l = child_list; l; l = l->next) { + fprintf(fp, "%d %d\n", (int) ((struct bitlbee_child*) l->data)->pid, + ((struct bitlbee_child*) l->data)->ipc_fd); } - else - { - unlink( fn ); - g_free( fn ); + + if (fclose(fp) == 0) { + return fn; + } else { + unlink(fn); + g_free(fn); return NULL; } } -static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond ) +static gboolean new_ipc_client(gpointer data, gint serversock, b_input_condition cond) { - struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 ); - + struct bitlbee_child *child = g_new0(struct bitlbee_child, 1); + child->to_fd = -1; - child->ipc_fd = accept( serversock, NULL, 0 ); - if( child->ipc_fd == -1 ) - { - log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) ); + child->ipc_fd = accept(serversock, NULL, 0); + if (child->ipc_fd == -1) { + log_message(LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno)); return TRUE; } - - child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); - - child_list = g_slist_prepend( child_list, child ); - + + child->ipc_inpa = b_input_add(child->ipc_fd, B_EV_IO_READ, ipc_master_read, child); + + child_list = g_slist_prepend(child_list, child); + return TRUE; } @@ -907,12 +884,13 @@ int ipc_master_listen_socket() struct sockaddr_un un_addr; int serversock; - if (!IPCSOCKET || !*IPCSOCKET) + if (!IPCSOCKET || !*IPCSOCKET) { return 1; + } /* Clean up old socket files that were hanging around.. */ if (unlink(IPCSOCKET) == -1 && errno != ENOENT) { - log_message( LOGLVL_ERROR, "Could not remove old IPC socket at %s: %s", IPCSOCKET, strerror(errno) ); + log_message(LOGLVL_ERROR, "Could not remove old IPC socket at %s: %s", IPCSOCKET, strerror(errno)); return 0; } @@ -922,67 +900,66 @@ int ipc_master_listen_socket() serversock = socket(AF_UNIX, SOCK_STREAM, PF_UNIX); if (serversock == -1) { - log_message( LOGLVL_WARNING, "Unable to create UNIX socket: %s", strerror(errno) ); + log_message(LOGLVL_WARNING, "Unable to create UNIX socket: %s", strerror(errno)); return 0; } - if (bind(serversock, (struct sockaddr *)&un_addr, sizeof(un_addr)) == -1) { - log_message( LOGLVL_WARNING, "Unable to bind UNIX socket to %s: %s", IPCSOCKET, strerror(errno) ); + if (bind(serversock, (struct sockaddr *) &un_addr, sizeof(un_addr)) == -1) { + log_message(LOGLVL_WARNING, "Unable to bind UNIX socket to %s: %s", IPCSOCKET, strerror(errno)); return 0; } if (listen(serversock, 5) == -1) { - log_message( LOGLVL_WARNING, "Unable to listen on UNIX socket: %s", strerror(errno) ); + log_message(LOGLVL_WARNING, "Unable to listen on UNIX socket: %s", strerror(errno)); return 0; } - - b_input_add( serversock, B_EV_IO_READ, new_ipc_client, NULL ); - + + b_input_add(serversock, B_EV_IO_READ, new_ipc_client, NULL); + return 1; } -int ipc_master_load_state( char *statefile ) +int ipc_master_load_state(char *statefile) { struct bitlbee_child *child; FILE *fp; int i, n; - - if( statefile == NULL ) + + if (statefile == NULL) { return 0; - - fp = fopen( statefile, "r" ); - unlink( statefile ); /* Why do it later? :-) */ - if( fp == NULL ) + } + + fp = fopen(statefile, "r"); + unlink(statefile); /* Why do it later? :-) */ + if (fp == NULL) { return 0; - - if( fscanf( fp, "%d", &n ) != 1 ) - { - log_message( LOGLVL_WARNING, "Could not import state information for child processes." ); - fclose( fp ); + } + + if (fscanf(fp, "%d", &n) != 1) { + log_message(LOGLVL_WARNING, "Could not import state information for child processes."); + fclose(fp); return 0; } - - log_message( LOGLVL_INFO, "Importing information for %d child processes.", n ); - for( i = 0; i < n; i ++ ) - { - child = g_new0( struct bitlbee_child, 1 ); - - if( fscanf( fp, "%d %d", (int *) &child->pid, &child->ipc_fd ) != 2 ) - { - log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i ); - g_free( child ); - fclose( fp ); + + log_message(LOGLVL_INFO, "Importing information for %d child processes.", n); + for (i = 0; i < n; i++) { + child = g_new0(struct bitlbee_child, 1); + + if (fscanf(fp, "%d %d", (int *) &child->pid, &child->ipc_fd) != 2) { + log_message(LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i); + g_free(child); + fclose(fp); return 0; } - child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child ); + child->ipc_inpa = b_input_add(child->ipc_fd, B_EV_IO_READ, ipc_master_read, child); child->to_fd = -1; - - child_list = g_slist_prepend( child_list, child ); - } - - ipc_to_children_str( "HELLO\r\n" ); - ipc_to_children_str( "OPERMSG :New %s master process started (version %s)\r\n", PACKAGE, BITLBEE_VERSION ); - - fclose( fp ); + + child_list = g_slist_prepend(child_list, child); + } + + ipc_to_children_str("HELLO\r\n"); + ipc_to_children_str("OPERMSG :New %s master process started (version %s)\r\n", PACKAGE, BITLBEE_VERSION); + + fclose(fp); return 1; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -27,45 +27,44 @@ #include "bitlbee.h" -struct bitlbee_child -{ +struct bitlbee_child { pid_t pid; int ipc_fd; gint ipc_inpa; - + char *host; char *nick; char *realname; - + char *password; - + /* For takeovers: */ struct bitlbee_child *to_child; int to_fd; }; -gboolean ipc_master_read( gpointer data, gint source, b_input_condition cond ); -gboolean ipc_child_read( gpointer data, gint source, b_input_condition cond ); +gboolean ipc_master_read(gpointer data, gint source, b_input_condition cond); +gboolean ipc_child_read(gpointer data, gint source, b_input_condition cond); -void ipc_master_free_one( struct bitlbee_child *child ); -void ipc_master_free_fd( int fd ); +void ipc_master_free_one(struct bitlbee_child *child); +void ipc_master_free_fd(int fd); void ipc_master_free_all(); void ipc_child_disable(); -gboolean ipc_child_identify( irc_t *irc ); +gboolean ipc_child_identify(irc_t *irc); -void ipc_to_master( char **cmd ); -void ipc_to_master_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 ); -void ipc_to_children( char **cmd ); -void ipc_to_children_str( char *format, ... ) G_GNUC_PRINTF( 1, 2 ); +void ipc_to_master(char **cmd); +void ipc_to_master_str(char *format, ...) G_GNUC_PRINTF(1, 2); +void ipc_to_children(char **cmd); +void ipc_to_children_str(char *format, ...) G_GNUC_PRINTF(1, 2); /* We need this function in inetd mode, so let's just make it non-static. */ -void ipc_master_cmd_rehash( irc_t *data, char **cmd ); +void ipc_master_cmd_rehash(irc_t *data, char **cmd); char *ipc_master_save_state(); -int ipc_master_load_state( char *statefile ); +int ipc_master_load_state(char *statefile); int ipc_master_listen_socket(); extern GSList *child_list; @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -31,141 +31,139 @@ 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 ); -static char *set_eval_password( set_t *set, char *value ); -static char *set_eval_bw_compat( set_t *set, char *value ); -static char *set_eval_utf8_nicks( set_t *set, char *value ); +static gboolean irc_userping(gpointer _irc, gint fd, b_input_condition cond); +static char *set_eval_charset(set_t *set, char *value); +static char *set_eval_password(set_t *set, char *value); +static char *set_eval_bw_compat(set_t *set, char *value); +static char *set_eval_utf8_nicks(set_t *set, char *value); -irc_t *irc_new( int fd ) +irc_t *irc_new(int fd) { irc_t *irc; struct sockaddr_storage sock; - socklen_t socklen = sizeof( sock ); + socklen_t socklen = sizeof(sock); char *host = NULL, *myhost = NULL; irc_user_t *iu; GSList *l; set_t *s; bee_t *b; - - irc = g_new0( irc_t, 1 ); - + + irc = g_new0(irc_t, 1); + irc->fd = fd; - sock_make_nonblocking( irc->fd ); - - irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc ); - + sock_make_nonblocking(irc->fd); + + irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc); + irc->status = USTATUS_OFFLINE; irc->last_pong = gettime(); - - irc->nick_user_hash = g_hash_table_new( g_str_hash, g_str_equal ); - irc->watches = g_hash_table_new( g_str_hash, g_str_equal ); - - irc->iconv = (GIConv) -1; - irc->oconv = (GIConv) -1; - - if( global.conf->hostname ) - { - myhost = g_strdup( global.conf->hostname ); - } - else if( getsockname( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) - { - char buf[NI_MAXHOST+1]; - - if( getnameinfo( (struct sockaddr *) &sock, socklen, buf, - NI_MAXHOST, NULL, 0, 0 ) == 0 ) - { - myhost = g_strdup( ipv6_unwrap( buf ) ); + + irc->nick_user_hash = g_hash_table_new(g_str_hash, g_str_equal); + irc->watches = g_hash_table_new(g_str_hash, g_str_equal); + + irc->iconv = (GIConv) - 1; + irc->oconv = (GIConv) - 1; + + if (global.conf->hostname) { + myhost = g_strdup(global.conf->hostname); + } else if (getsockname(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { + char buf[NI_MAXHOST + 1]; + + if (getnameinfo((struct sockaddr *) &sock, socklen, buf, + NI_MAXHOST, NULL, 0, 0) == 0) { + myhost = g_strdup(ipv6_unwrap(buf)); } } - - if( getpeername( irc->fd, (struct sockaddr*) &sock, &socklen ) == 0 ) - { - char buf[NI_MAXHOST+1]; - if( getnameinfo( (struct sockaddr *)&sock, socklen, buf, - NI_MAXHOST, NULL, 0, 0 ) == 0 ) - { - host = g_strdup( ipv6_unwrap( buf ) ); + if (getpeername(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) { + char buf[NI_MAXHOST + 1]; + + if (getnameinfo((struct sockaddr *) &sock, socklen, buf, + NI_MAXHOST, NULL, 0, 0) == 0) { + host = g_strdup(ipv6_unwrap(buf)); } } - - if( host == NULL ) - host = g_strdup( "localhost.localdomain" ); - if( myhost == NULL ) - myhost = g_strdup( "localhost.localdomain" ); - - if( global.conf->ping_interval > 0 && global.conf->ping_timeout > 0 ) - irc->ping_source_id = b_timeout_add( global.conf->ping_interval * 1000, irc_userping, irc ); - - irc_connection_list = g_slist_append( irc_connection_list, irc ); - + + if (host == NULL) { + host = g_strdup("localhost.localdomain"); + } + if (myhost == NULL) { + myhost = g_strdup("localhost.localdomain"); + } + + if (global.conf->ping_interval > 0 && global.conf->ping_timeout > 0) { + irc->ping_source_id = b_timeout_add(global.conf->ping_interval * 1000, irc_userping, irc); + } + + irc_connection_list = g_slist_append(irc_connection_list, irc); + b = irc->b = bee_new(); b->ui_data = irc; b->ui = &irc_ui_funcs; - - s = set_add( &b->set, "allow_takeover", "true", set_eval_bool, irc ); - s = set_add( &b->set, "away_devoice", "true", set_eval_bw_compat, irc ); + + s = set_add(&b->set, "allow_takeover", "true", set_eval_bool, irc); + s = set_add(&b->set, "away_devoice", "true", set_eval_bw_compat, irc); s->flags |= SET_HIDDEN; - s = set_add( &b->set, "away_reply_timeout", "3600", set_eval_int, irc ); - s = set_add( &b->set, "charset", "utf-8", set_eval_charset, irc ); - s = set_add( &b->set, "default_target", "root", NULL, irc ); - s = set_add( &b->set, "display_namechanges", "false", set_eval_bool, irc ); - s = set_add( &b->set, "display_timestamps", "true", set_eval_bool, irc ); - s = set_add( &b->set, "handle_unknown", "add_channel", NULL, irc ); - s = set_add( &b->set, "last_version", "0", NULL, irc ); + s = set_add(&b->set, "away_reply_timeout", "3600", set_eval_int, irc); + s = set_add(&b->set, "charset", "utf-8", set_eval_charset, irc); + s = set_add(&b->set, "default_target", "root", NULL, irc); + s = set_add(&b->set, "display_namechanges", "false", set_eval_bool, irc); + s = set_add(&b->set, "display_timestamps", "true", set_eval_bool, irc); + s = set_add(&b->set, "handle_unknown", "add_channel", NULL, irc); + s = set_add(&b->set, "last_version", "0", NULL, irc); s->flags |= SET_HIDDEN; - s = set_add( &b->set, "lcnicks", "true", set_eval_bool, irc ); - s = set_add( &b->set, "nick_format", "%-@nick", NULL, irc ); - s = set_add( &b->set, "offline_user_quits", "true", set_eval_bool, irc ); - s = set_add( &b->set, "ops", "both", set_eval_irc_channel_ops, irc ); - s = set_add( &b->set, "paste_buffer", "false", set_eval_bool, irc ); - s->old_key = g_strdup( "buddy_sendbuffer" ); - s = set_add( &b->set, "paste_buffer_delay", "200", set_eval_int, irc ); - s->old_key = g_strdup( "buddy_sendbuffer_delay" ); - s = set_add( &b->set, "password", NULL, set_eval_password, irc ); + s = set_add(&b->set, "lcnicks", "true", set_eval_bool, irc); + s = set_add(&b->set, "nick_format", "%-@nick", NULL, irc); + s = set_add(&b->set, "offline_user_quits", "true", set_eval_bool, irc); + s = set_add(&b->set, "ops", "both", set_eval_irc_channel_ops, irc); + s = set_add(&b->set, "paste_buffer", "false", set_eval_bool, irc); + s->old_key = g_strdup("buddy_sendbuffer"); + s = set_add(&b->set, "paste_buffer_delay", "200", set_eval_int, irc); + s->old_key = g_strdup("buddy_sendbuffer_delay"); + s = set_add(&b->set, "password", NULL, set_eval_password, irc); s->flags |= SET_NULL_OK | SET_PASSWORD; - s = set_add( &b->set, "private", "true", set_eval_bool, irc ); - s = set_add( &b->set, "query_order", "lifo", NULL, irc ); - s = set_add( &b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc ); + s = set_add(&b->set, "private", "true", set_eval_bool, irc); + s = set_add(&b->set, "query_order", "lifo", NULL, irc); + s = set_add(&b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc); s->flags |= SET_HIDDEN; - s = set_add( &b->set, "show_offline", "false", set_eval_bw_compat, irc ); + s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc); s->flags |= SET_HIDDEN; - s = set_add( &b->set, "simulate_netsplit", "true", set_eval_bool, irc ); - s = set_add( &b->set, "timezone", "local", set_eval_timezone, irc ); - s = set_add( &b->set, "to_char", ": ", set_eval_to_char, irc ); - s = set_add( &b->set, "typing_notice", "false", set_eval_bool, irc ); - s = set_add( &b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc ); - - irc->root = iu = irc_user_new( irc, ROOT_NICK ); - iu->host = g_strdup( myhost ); - iu->fullname = g_strdup( ROOT_FN ); + s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc); + s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc); + s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc); + s = set_add(&b->set, "typing_notice", "false", set_eval_bool, irc); + s = set_add(&b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc); + + irc->root = iu = irc_user_new(irc, ROOT_NICK); + iu->host = g_strdup(myhost); + iu->fullname = g_strdup(ROOT_FN); iu->f = &irc_user_root_funcs; - - iu = irc_user_new( irc, NS_NICK ); - iu->host = g_strdup( myhost ); - iu->fullname = g_strdup( ROOT_FN ); + + iu = irc_user_new(irc, NS_NICK); + iu->host = g_strdup(myhost); + iu->fullname = g_strdup(ROOT_FN); iu->f = &irc_user_root_funcs; - - irc->user = g_new0( irc_user_t, 1 ); - irc->user->host = g_strdup( host ); - - conf_loaddefaults( irc ); - + + irc->user = g_new0(irc_user_t, 1); + irc->user->host = g_strdup(host); + + conf_loaddefaults(irc); + /* Evaluator sets the iconv/oconv structures. */ - set_eval_charset( set_find( &b->set, "charset" ), set_getstr( &b->set, "charset" ) ); - - irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" ); - if( isatty( irc->fd ) ) - irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, - "If you read this, you most likely accidentally " - "started BitlBee in inetd mode on the command line. " - "You probably want to run it in (Fork)Daemon mode. " - "See doc/README for more information." ); - - g_free( myhost ); - g_free( host ); - + set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset")); + + irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on"); + if (isatty(irc->fd)) { + irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, + "If you read this, you most likely accidentally " + "started BitlBee in inetd mode on the command line. " + "You probably want to run it in (Fork)Daemon mode. " + "See doc/README for more information."); + } + + g_free(myhost); + g_free(host); + /* libpurple doesn't like fork()s after initializing itself, so this is the right moment to initialize it. */ #ifdef WITH_PURPLE @@ -176,249 +174,245 @@ irc_t *irc_new( int fd ) avoid shared CSPRNG state. This is required by NSS, which refuses to work if a fork is detected */ ssl_init(); - - for( l = irc_plugins; l; l = l->next ) - { + + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->irc_new ) - p->irc_new( irc ); + if (p->irc_new) { + p->irc_new(irc); + } } - + return irc; } /* immed=1 makes this function pretty much equal to irc_free(), except that this one will "log". In case the connection is already broken and we shouldn't try to write to it. */ -void irc_abort( irc_t *irc, int immed, char *format, ... ) +void irc_abort(irc_t *irc, int immed, char *format, ...) { char *reason = NULL; - - if( format != NULL ) - { + + if (format != NULL) { va_list params; - - va_start( params, format ); - reason = g_strdup_vprintf( format, params ); - va_end( params ); - } - - if( reason ) - irc_write( irc, "ERROR :Closing link: %s", reason ); - - ipc_to_master_str( "OPERMSG :Client exiting: %s@%s [%s]\r\n", - irc->user->nick ? irc->user->nick : "(NONE)", - irc->user->host, reason ? : "" ); - - g_free( reason ); - - irc_flush( irc ); - if( immed ) - { - irc_free( irc ); - } - else - { - b_event_remove( irc->ping_source_id ); - irc->ping_source_id = b_timeout_add( 1, (b_event_handler) irc_free, irc ); + + va_start(params, format); + reason = g_strdup_vprintf(format, params); + va_end(params); + } + + if (reason) { + irc_write(irc, "ERROR :Closing link: %s", reason); + } + + ipc_to_master_str("OPERMSG :Client exiting: %s@%s [%s]\r\n", + irc->user->nick ? irc->user->nick : "(NONE)", + irc->user->host, reason ? : ""); + + g_free(reason); + + irc_flush(irc); + if (immed) { + irc_free(irc); + } else { + b_event_remove(irc->ping_source_id); + irc->ping_source_id = b_timeout_add(1, (b_event_handler) irc_free, irc); } } -static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ); +static gboolean irc_free_hashkey(gpointer key, gpointer value, gpointer data); -void irc_free( irc_t * irc ) +void irc_free(irc_t * irc) { GSList *l; - + irc->status |= USTATUS_SHUTDOWN; - - log_message( LOGLVL_INFO, "Destroying connection with fd %d", irc->fd ); - - 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 ); - - for( l = irc_plugins; l; l = l->next ) - { + + log_message(LOGLVL_INFO, "Destroying connection with fd %d", irc->fd); + + 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); + } + } + + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->irc_free ) - p->irc_free( irc ); - } - - irc_connection_list = g_slist_remove( irc_connection_list, irc ); - - while( irc->queries != NULL ) - query_del( irc, irc->queries ); - + if (p->irc_free) { + p->irc_free(irc); + } + } + + irc_connection_list = g_slist_remove(irc_connection_list, irc); + + while (irc->queries != NULL) { + query_del(irc, irc->queries); + } + /* This is a little bit messy: bee_free() frees all b->users which calls us back to free the corresponding irc->users. So do this before we clear the remaining ones ourselves. */ - bee_free( irc->b ); - - while( irc->users ) - irc_user_free( irc, (irc_user_t *) irc->users->data ); - - while( irc->channels ) - irc_channel_free( irc->channels->data ); - - if( irc->ping_source_id > 0 ) - b_event_remove( irc->ping_source_id ); - if( irc->r_watch_source_id > 0 ) - b_event_remove( irc->r_watch_source_id ); - if( irc->w_watch_source_id > 0 ) - b_event_remove( irc->w_watch_source_id ); - - closesocket( irc->fd ); + bee_free(irc->b); + + while (irc->users) { + irc_user_free(irc, (irc_user_t *) irc->users->data); + } + + while (irc->channels) { + irc_channel_free(irc->channels->data); + } + + if (irc->ping_source_id > 0) { + b_event_remove(irc->ping_source_id); + } + if (irc->r_watch_source_id > 0) { + b_event_remove(irc->r_watch_source_id); + } + if (irc->w_watch_source_id > 0) { + b_event_remove(irc->w_watch_source_id); + } + + closesocket(irc->fd); irc->fd = -1; - - g_hash_table_foreach_remove( irc->nick_user_hash, irc_free_hashkey, NULL ); - g_hash_table_destroy( irc->nick_user_hash ); - - g_hash_table_foreach_remove( irc->watches, irc_free_hashkey, NULL ); - g_hash_table_destroy( irc->watches ); - - if( irc->iconv != (GIConv) -1 ) - g_iconv_close( irc->iconv ); - if( irc->oconv != (GIConv) -1 ) - g_iconv_close( irc->oconv ); - - g_free( irc->sendbuffer ); - g_free( irc->readbuffer ); - g_free( irc->password ); - - g_free( irc ); - - if( global.conf->runmode == RUNMODE_INETD || + + g_hash_table_foreach_remove(irc->nick_user_hash, irc_free_hashkey, NULL); + g_hash_table_destroy(irc->nick_user_hash); + + g_hash_table_foreach_remove(irc->watches, irc_free_hashkey, NULL); + g_hash_table_destroy(irc->watches); + + if (irc->iconv != (GIConv) - 1) { + g_iconv_close(irc->iconv); + } + if (irc->oconv != (GIConv) - 1) { + g_iconv_close(irc->oconv); + } + + g_free(irc->sendbuffer); + g_free(irc->readbuffer); + g_free(irc->password); + + g_free(irc); + + if (global.conf->runmode == RUNMODE_INETD || global.conf->runmode == RUNMODE_FORKDAEMON || - ( global.conf->runmode == RUNMODE_DAEMON && - global.listen_socket == -1 && - irc_connection_list == NULL ) ) + (global.conf->runmode == RUNMODE_DAEMON && + global.listen_socket == -1 && + irc_connection_list == NULL)) { b_main_quit(); + } } -static gboolean irc_free_hashkey( gpointer key, gpointer value, gpointer data ) +static gboolean irc_free_hashkey(gpointer key, gpointer value, gpointer data) { - g_free( key ); - - return( TRUE ); + g_free(key); + + return(TRUE); } /* USE WITH CAUTION! Sets pass without checking */ -void irc_setpass (irc_t *irc, const char *pass) +void irc_setpass(irc_t *irc, const char *pass) { - g_free (irc->password); - + g_free(irc->password); + if (pass) { - irc->password = g_strdup (pass); + irc->password = g_strdup(pass); } else { irc->password = NULL; } } -static char *set_eval_password( set_t *set, char *value ) +static char *set_eval_password(set_t *set, char *value) { irc_t *irc = set->data; - - if( irc->status & USTATUS_IDENTIFIED && value ) - { - irc_setpass( irc, value ); + + if (irc->status & USTATUS_IDENTIFIED && value) { + irc_setpass(irc, value); return NULL; - } - else - { + } else { return SET_INVALID; } } -static char **irc_splitlines( char *buffer ); +static char **irc_splitlines(char *buffer); -void irc_process( irc_t *irc ) +void irc_process(irc_t *irc) { char **lines, *temp, **cmd; int i; - if( irc->readbuffer != NULL ) - { - lines = irc_splitlines( irc->readbuffer ); - - for( i = 0; *lines[i] != '\0'; i ++ ) - { + if (irc->readbuffer != NULL) { + lines = irc_splitlines(irc->readbuffer); + + for (i = 0; *lines[i] != '\0'; i++) { char *conv = NULL; - + /* [WvG] If the last line isn't empty, it's an incomplete line and we should wait for the rest to come in before processing it. */ - if( lines[i+1] == NULL ) - { - temp = g_strdup( lines[i] ); - g_free( irc->readbuffer ); + if (lines[i + 1] == NULL) { + temp = g_strdup(lines[i]); + g_free(irc->readbuffer); irc->readbuffer = temp; - i ++; + i++; break; } - - if( irc->iconv != (GIConv) -1 ) - { + + if (irc->iconv != (GIConv) - 1) { gsize bytes_read, bytes_written; - - conv = g_convert_with_iconv( lines[i], -1, irc->iconv, - &bytes_read, &bytes_written, NULL ); - - if( conv == NULL || bytes_read != strlen( lines[i] ) ) - { + + conv = g_convert_with_iconv(lines[i], -1, irc->iconv, + &bytes_read, &bytes_written, NULL); + + if (conv == NULL || bytes_read != strlen(lines[i])) { /* GLib can do strange things if things are not in the expected charset, so let's be a little bit paranoid here: */ - if( irc->status & USTATUS_LOGGED_IN ) - { - irc_rootmsg( irc, "Error: Charset mismatch detected. The charset " - "setting is currently set to %s, so please make " - "sure your IRC client will send and accept text in " - "that charset, or tell BitlBee which charset to " - "expect by changing the charset setting. See " - "`help set charset' for more information. Your " - "message was ignored.", - set_getstr( &irc->b->set, "charset" ) ); - - g_free( conv ); + if (irc->status & USTATUS_LOGGED_IN) { + irc_rootmsg(irc, "Error: Charset mismatch detected. The charset " + "setting is currently set to %s, so please make " + "sure your IRC client will send and accept text in " + "that charset, or tell BitlBee which charset to " + "expect by changing the charset setting. See " + "`help set charset' for more information. Your " + "message was ignored.", + set_getstr(&irc->b->set, "charset")); + + g_free(conv); conv = NULL; - } - else - { - irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, - "Warning: invalid characters received at login time." ); - - conv = g_strdup( lines[i] ); - for( temp = conv; *temp; temp ++ ) - if( *temp & 0x80 ) + } else { + irc_write(irc, ":%s NOTICE AUTH :%s", irc->root->host, + "Warning: invalid characters received at login time."); + + conv = g_strdup(lines[i]); + for (temp = conv; *temp; temp++) { + if (*temp & 0x80) { *temp = '?'; + } + } } } lines[i] = conv; } - - if( lines[i] && ( cmd = irc_parse_line( lines[i] ) ) ) - { - irc_exec( irc, cmd ); - g_free( cmd ); + + if (lines[i] && (cmd = irc_parse_line(lines[i]))) { + irc_exec(irc, cmd); + g_free(cmd); } - - g_free( conv ); - + + g_free(conv); + /* Shouldn't really happen, but just in case... */ - if( !g_slist_find( irc_connection_list, irc ) ) - { - g_free( lines ); + if (!g_slist_find(irc_connection_list, irc)) { + g_free(lines); return; } } - - if( lines[i] != NULL ) - { - g_free( irc->readbuffer ); + + if (lines[i] != NULL) { + g_free(irc->readbuffer); irc->readbuffer = NULL; } - - g_free( lines ); + + g_free(lines); } } @@ -426,255 +420,250 @@ void irc_process( irc_t *irc ) and, unless the string contains an incomplete line at the end, ends with an empty string. Could use g_strsplit() but this one does it in-place. (So yes, it's destructive.) */ -static char **irc_splitlines( char *buffer ) +static char **irc_splitlines(char *buffer) { int i, j, n = 3; char **lines; /* Allocate n+1 elements. */ - lines = g_new( char *, n + 1 ); - + lines = g_new(char *, n + 1); + lines[0] = buffer; - + /* Split the buffer in several strings, and accept any kind of line endings, * knowing that ERC on Windows may send something interesting like \r\r\n, * and surely there must be clients that think just \n is enough... */ - for( i = 0, j = 0; buffer[i] != '\0'; i ++ ) - { - if( buffer[i] == '\r' || buffer[i] == '\n' ) - { - while( buffer[i] == '\r' || buffer[i] == '\n' ) + for (i = 0, j = 0; buffer[i] != '\0'; i++) { + if (buffer[i] == '\r' || buffer[i] == '\n') { + while (buffer[i] == '\r' || buffer[i] == '\n') { buffer[i++] = '\0'; - + } + lines[++j] = buffer + i; - - if( j >= n ) - { + + if (j >= n) { n *= 2; - lines = g_renew( char *, lines, n + 1 ); + lines = g_renew(char *, lines, n + 1); } - if( buffer[i] == '\0' ) + if (buffer[i] == '\0') { break; + } } } - - /* NULL terminate our list. */ + + /* NULL terminate our list. */ lines[++j] = NULL; - + return lines; } /* Split an IRC-style line into little parts/arguments. */ -char **irc_parse_line( char *line ) +char **irc_parse_line(char *line) { int i, j; char **cmd; - + /* Move the line pointer to the start of the command, skipping spaces and the optional prefix. */ - if( line[0] == ':' ) - { - for( i = 0; line[i] && line[i] != ' '; i ++ ); + if (line[0] == ':') { + for (i = 0; line[i] && line[i] != ' '; i++) { + ; + } line = line + i; } - for( i = 0; line[i] == ' '; i ++ ); + for (i = 0; line[i] == ' '; i++) { + ; + } line = line + i; - + /* If we're already at the end of the line, return. If not, we're going to need at least one element. */ - if( line[0] == '\0') + if (line[0] == '\0') { return NULL; - + } + /* Count the number of char **cmd elements we're going to need. */ j = 1; - for( i = 0; line[i] != '\0'; i ++ ) - { - if( line[i] == ' ' ) - { - j ++; - - if( line[i+1] == ':' ) + for (i = 0; line[i] != '\0'; i++) { + if (line[i] == ' ') { + j++; + + if (line[i + 1] == ':') { break; + } } - } + } /* Allocate the space we need. */ - cmd = g_new( char *, j + 1 ); + cmd = g_new(char *, j + 1); cmd[j] = NULL; - + /* Do the actual line splitting, format is: * Input: "PRIVMSG #bitlbee :foo bar" * Output: cmd[0]=="PRIVMSG", cmd[1]=="#bitlbee", cmd[2]=="foo bar", cmd[3]==NULL */ cmd[0] = line; - for( i = 0, j = 0; line[i] != '\0'; i ++ ) - { - if( line[i] == ' ' ) - { + for (i = 0, j = 0; line[i] != '\0'; i++) { + if (line[i] == ' ') { line[i] = '\0'; cmd[++j] = line + i + 1; - - if( line[i+1] == ':' ) - { - cmd[j] ++; + + if (line[i + 1] == ':') { + cmd[j]++; break; } } } - + return cmd; } /* Converts such an array back into a command string. Mainly used for the IPC code right now. */ -char *irc_build_line( char **cmd ) +char *irc_build_line(char **cmd) { int i, len; char *s; - - if( cmd[0] == NULL ) + + if (cmd[0] == NULL) { return NULL; - + } + len = 1; - for( i = 0; cmd[i]; i ++ ) - len += strlen( cmd[i] ) + 1; - - if( strchr( cmd[i-1], ' ' ) != NULL ) - len ++; - - s = g_new0( char, len + 1 ); - for( i = 0; cmd[i]; i ++ ) - { - if( cmd[i+1] == NULL && strchr( cmd[i], ' ' ) != NULL ) - strcat( s, ":" ); - - strcat( s, cmd[i] ); - - if( cmd[i+1] ) - strcat( s, " " ); - } - strcat( s, "\r\n" ); - + for (i = 0; cmd[i]; i++) { + len += strlen(cmd[i]) + 1; + } + + if (strchr(cmd[i - 1], ' ') != NULL) { + len++; + } + + s = g_new0(char, len + 1); + for (i = 0; cmd[i]; i++) { + if (cmd[i + 1] == NULL && strchr(cmd[i], ' ') != NULL) { + strcat(s, ":"); + } + + strcat(s, cmd[i]); + + if (cmd[i + 1]) { + strcat(s, " "); + } + } + strcat(s, "\r\n"); + return s; } -void irc_write( irc_t *irc, char *format, ... ) +void irc_write(irc_t *irc, char *format, ...) { va_list params; - va_start( params, format ); - irc_vawrite( irc, format, params ); - va_end( params ); + va_start(params, format); + irc_vawrite(irc, format, params); + va_end(params); return; } -void irc_write_all( int now, char *format, ... ) +void irc_write_all(int now, char *format, ...) { va_list params; - GSList *temp; - - va_start( params, format ); - + GSList *temp; + + va_start(params, format); + temp = irc_connection_list; - while( temp != NULL ) - { + while (temp != NULL) { irc_t *irc = temp->data; - - if( now ) - { - g_free( irc->sendbuffer ); - irc->sendbuffer = g_strdup( "\r\n" ); + + if (now) { + g_free(irc->sendbuffer); + irc->sendbuffer = g_strdup("\r\n"); } - irc_vawrite( temp->data, format, params ); - if( now ) - { - bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ); + irc_vawrite(temp->data, format, params); + if (now) { + bitlbee_io_current_client_write(irc, irc->fd, B_EV_IO_WRITE); } temp = temp->next; } - - va_end( params ); + + va_end(params); return; -} +} -void irc_vawrite( irc_t *irc, char *format, va_list params ) +void irc_vawrite(irc_t *irc, char *format, va_list params) { int size; - char line[IRC_MAX_LINE+1]; - + char line[IRC_MAX_LINE + 1]; + /* Don't try to write anything new anymore when shutting down. */ - if( irc->status & USTATUS_SHUTDOWN ) + if (irc->status & USTATUS_SHUTDOWN) { return; - - memset( line, 0, sizeof( line ) ); - g_vsnprintf( line, IRC_MAX_LINE - 2, format, params ); - strip_newlines( line ); - - if( irc->oconv != (GIConv) -1 ) - { + } + + memset(line, 0, sizeof(line)); + g_vsnprintf(line, IRC_MAX_LINE - 2, format, params); + strip_newlines(line); + + if (irc->oconv != (GIConv) - 1) { gsize bytes_read, bytes_written; char *conv; - - conv = g_convert_with_iconv( line, -1, irc->oconv, - &bytes_read, &bytes_written, NULL ); - - if( bytes_read == strlen( line ) ) - strncpy( line, conv, IRC_MAX_LINE - 2 ); - - g_free( conv ); - } - g_strlcat( line, "\r\n", IRC_MAX_LINE + 1 ); - - if( irc->sendbuffer != NULL ) - { - size = strlen( irc->sendbuffer ) + strlen( line ); - irc->sendbuffer = g_renew ( char, irc->sendbuffer, size + 1 ); - strcpy( ( irc->sendbuffer + strlen( irc->sendbuffer ) ), line ); - } - else - { + + conv = g_convert_with_iconv(line, -1, irc->oconv, + &bytes_read, &bytes_written, NULL); + + if (bytes_read == strlen(line)) { + strncpy(line, conv, IRC_MAX_LINE - 2); + } + + g_free(conv); + } + g_strlcat(line, "\r\n", IRC_MAX_LINE + 1); + + if (irc->sendbuffer != NULL) { + size = strlen(irc->sendbuffer) + strlen(line); + irc->sendbuffer = g_renew(char, irc->sendbuffer, size + 1); + strcpy((irc->sendbuffer + strlen(irc->sendbuffer)), line); + } else { irc->sendbuffer = g_strdup(line); } - - if( irc->w_watch_source_id == 0 ) - { + + if (irc->w_watch_source_id == 0) { /* If the buffer is empty we can probably write, so call the write event handler immediately. If it returns TRUE, it should be called again, so add the event to the queue. If it's FALSE, we emptied the buffer and saved ourselves some work in the event queue. */ /* Really can't be done as long as the code doesn't do error checking very well: if( bitlbee_io_current_client_write( irc, irc->fd, B_EV_IO_WRITE ) ) */ - + /* So just always do it via the event handler. */ - irc->w_watch_source_id = b_input_add( irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc ); + irc->w_watch_source_id = b_input_add(irc->fd, B_EV_IO_WRITE, bitlbee_io_current_client_write, irc); } - + return; } /* Flush sendbuffer if you can. If it fails, fail silently and let some I/O event handler clean up. */ -void irc_flush( irc_t *irc ) +void irc_flush(irc_t *irc) { ssize_t n; size_t len; - - if( irc->sendbuffer == NULL ) + + if (irc->sendbuffer == NULL) { return; - - len = strlen( irc->sendbuffer ); - if( ( n = send( irc->fd, irc->sendbuffer, len, 0 ) ) == len ) - { - g_free( irc->sendbuffer ); + } + + len = strlen(irc->sendbuffer); + if ((n = send(irc->fd, irc->sendbuffer, len, 0)) == len) { + g_free(irc->sendbuffer); irc->sendbuffer = NULL; - - b_event_remove( irc->w_watch_source_id ); + + b_event_remove(irc->w_watch_source_id); irc->w_watch_source_id = 0; - } - else if( n > 0 ) - { - char *s = g_strdup( irc->sendbuffer + n ); - g_free( irc->sendbuffer ); + } else if (n > 0) { + char *s = g_strdup(irc->sendbuffer + n); + g_free(irc->sendbuffer); irc->sendbuffer = s; } /* Otherwise something went wrong and we don't currently care @@ -684,119 +673,114 @@ void irc_flush( irc_t *irc ) /* Meant for takeover functionality. Transfer an IRC connection to a different socket. */ -void irc_switch_fd( irc_t *irc, int fd ) +void irc_switch_fd(irc_t *irc, int fd) { - irc_write( irc, "ERROR :Transferring session to a new connection" ); - irc_flush( irc ); /* Write it now or forget about it forever. */ - - if( irc->sendbuffer ) - { - b_event_remove( irc->w_watch_source_id ); + irc_write(irc, "ERROR :Transferring session to a new connection"); + irc_flush(irc); /* Write it now or forget about it forever. */ + + if (irc->sendbuffer) { + b_event_remove(irc->w_watch_source_id); irc->w_watch_source_id = 0; - g_free( irc->sendbuffer ); + g_free(irc->sendbuffer); irc->sendbuffer = NULL; } - - b_event_remove( irc->r_watch_source_id ); - closesocket( irc->fd ); + + b_event_remove(irc->r_watch_source_id); + closesocket(irc->fd); irc->fd = fd; - irc->r_watch_source_id = b_input_add( irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc ); + irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc); } -void irc_sync( irc_t *irc ) +void irc_sync(irc_t *irc) { GSList *l; - - irc_write( irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, - irc->user->user, irc->user->host, irc->user->nick, - irc->umode ); - - for( l = irc->channels; l; l = l->next ) - { + + irc_write(irc, ":%s!%s@%s MODE %s :+%s", irc->user->nick, + irc->user->user, irc->user->host, irc->user->nick, + irc->umode); + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_send_join( ic, irc->user ); + if (ic->flags & IRC_CHANNEL_JOINED) { + irc_send_join(ic, irc->user); + } } - + /* We may be waiting for a PONG from the previous client connection. */ irc->pinging = FALSE; } -void irc_desync( irc_t *irc ) +void irc_desync(irc_t *irc) { GSList *l; - - for( l = irc->channels; l; l = l->next ) - irc_channel_del_user( l->data, irc->user, IRC_CDU_KICK, - "Switching to old session" ); - - irc_write( irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, - irc->user->user, irc->user->host, irc->user->nick, - irc->umode ); + + for (l = irc->channels; l; l = l->next) { + irc_channel_del_user(l->data, irc->user, IRC_CDU_KICK, + "Switching to old session"); + } + + irc_write(irc, ":%s!%s@%s MODE %s :-%s", irc->user->nick, + irc->user->user, irc->user->host, irc->user->nick, + irc->umode); } -int irc_check_login( irc_t *irc ) +int irc_check_login(irc_t *irc) { - if( irc->user->user && irc->user->nick ) - { - if( global.conf->authmode == AUTHMODE_CLOSED && !( irc->status & USTATUS_AUTHORIZED ) ) - { - irc_send_num( irc, 464, ":This server is password-protected." ); + if (irc->user->user && irc->user->nick) { + if (global.conf->authmode == AUTHMODE_CLOSED && !(irc->status & USTATUS_AUTHORIZED)) { + irc_send_num(irc, 464, ":This server is password-protected."); return 0; - } - else - { + } else { irc_channel_t *ic; irc_user_t *iu = irc->user; - - irc->user = irc_user_new( irc, iu->nick ); + + irc->user = irc_user_new(irc, iu->nick); irc->user->user = iu->user; irc->user->host = iu->host; irc->user->fullname = iu->fullname; irc->user->f = &irc_user_self_funcs; - g_free( iu->nick ); - g_free( iu ); - - if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON ) - ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname ); - + g_free(iu->nick); + g_free(iu); + + if (global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON) { + ipc_to_master_str("CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, + irc->user->fullname); + } + irc->status |= USTATUS_LOGGED_IN; - - irc_send_login( irc ); - + + irc_send_login(irc); + irc->umode[0] = '\0'; - irc_umode_set( irc, "+" UMODE, TRUE ); - - ic = irc->default_channel = irc_channel_new( irc, ROOT_CHAN ); - irc_channel_set_topic( ic, CONTROL_TOPIC, irc->root ); - set_setstr( &ic->set, "auto_join", "true" ); - irc_channel_auto_joins( irc, NULL ); - + irc_umode_set(irc, "+" UMODE, TRUE); + + ic = irc->default_channel = irc_channel_new(irc, ROOT_CHAN); + irc_channel_set_topic(ic, CONTROL_TOPIC, irc->root); + set_setstr(&ic->set, "auto_join", "true"); + irc_channel_auto_joins(irc, NULL); + irc->root->last_channel = irc->default_channel; - - irc_rootmsg( irc, - "Welcome to the BitlBee gateway!\n\n" - "If you've never used BitlBee before, please do read the help " - "information using the \x02help\x02 command. Lots of FAQs are " - "answered there.\n" - "If you already have an account on this server, just use the " - "\x02identify\x02 command to identify yourself." ); - + + irc_rootmsg(irc, + "Welcome to the BitlBee gateway!\n\n" + "If you've never used BitlBee before, please do read the help " + "information using the \x02help\x02 command. Lots of FAQs are " + "answered there.\n" + "If you already have an account on this server, just use the " + "\x02identify\x02 command to identify yourself."); + /* This is for bug #209 (use PASS to identify to NickServ). */ - if( irc->password != NULL ) - { - char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL }; - - irc_setpass( irc, NULL ); - root_command( irc, send_cmd ); - g_free( send_cmd[1] ); + if (irc->password != NULL) { + char *send_cmd[] = { "identify", g_strdup(irc->password), NULL }; + + irc_setpass(irc, NULL); + root_command(irc, send_cmd); + g_free(send_cmd[1]); } - + return 1; } - } - else - { + } else { /* More information needed. */ return 0; } @@ -804,7 +788,7 @@ int irc_check_login( irc_t *irc ) /* TODO: This is a mess, but this function is a bit too complicated to be converted to something more generic. */ -void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) +void irc_umode_set(irc_t *irc, const char *s, gboolean allow_priv) { /* allow_priv: Set to 0 if s contains user input, 1 if you want to set a "privileged" mode (+o, +R, etc). */ @@ -813,127 +797,125 @@ void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ) int i; char changes[512], st2 = 2; char badflag = 0; - - memset( m, 0, sizeof( m ) ); - + + memset(m, 0, sizeof(m)); + /* Keep track of which modes are enabled in this array. */ - for( t = irc->umode; *t; t ++ ) - if( *t < sizeof( m ) ) - m[(int)*t] = 1; - + for (t = irc->umode; *t; t++) { + if (*t < sizeof(m)) { + m[(int) *t] = 1; + } + } + i = 0; - for( t = s; *t && i < sizeof( changes ) - 3; t ++ ) - { - if( *t == '+' || *t == '-' ) + for (t = s; *t && i < sizeof(changes) - 3; t++) { + if (*t == '+' || *t == '-') { st = *t == '+'; - else if( ( st == 0 && ( !strchr( UMODES_KEEP, *t ) || allow_priv ) ) || - ( st == 1 && strchr( UMODES, *t ) ) || - ( st == 1 && allow_priv && strchr( UMODES_PRIV, *t ) ) ) - { - if( m[(int)*t] != st) - { + } else if ((st == 0 && (!strchr(UMODES_KEEP, *t) || allow_priv)) || + (st == 1 && strchr(UMODES, *t)) || + (st == 1 && allow_priv && strchr(UMODES_PRIV, *t))) { + if (m[(int) *t] != st) { /* If we're actually making a change, remember this for the response. */ - if( st != st2 ) + if (st != st2) { st2 = st, changes[i++] = st ? '+' : '-'; + } changes[i++] = *t; } - m[(int)*t] = st; - } - else + m[(int) *t] = st; + } else { badflag = 1; + } } changes[i] = '\0'; - + /* Convert the m array back into an umode string. */ - memset( irc->umode, 0, sizeof( irc->umode ) ); - for( i = 'A'; i <= 'z' && strlen( irc->umode ) < ( sizeof( irc->umode ) - 1 ); i ++ ) - if( m[i] ) + memset(irc->umode, 0, sizeof(irc->umode)); + for (i = 'A'; i <= 'z' && strlen(irc->umode) < (sizeof(irc->umode) - 1); i++) { + if (m[i]) { irc->umode[strlen(irc->umode)] = i; - - if( badflag ) - irc_send_num( irc, 501, ":Unknown MODE flag" ); - if( *changes ) - irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, - irc->user->user, irc->user->host, irc->user->nick, - changes ); + } + } + + if (badflag) { + irc_send_num(irc, 501, ":Unknown MODE flag"); + } + if (*changes) { + irc_write(irc, ":%s!%s@%s MODE %s :%s", irc->user->nick, + irc->user->user, irc->user->host, irc->user->nick, + changes); + } } /* Returns 0 if everything seems to be okay, a number >0 when there was a timeout. The number returned is the number of seconds we received no pongs from the user. When not connected yet, we don't ping but drop the connection when the user fails to connect in IRC_LOGIN_TIMEOUT secs. */ -static gboolean irc_userping( gpointer _irc, gint fd, b_input_condition cond ) +static gboolean irc_userping(gpointer _irc, gint fd, b_input_condition cond) { double now = gettime(); irc_t *irc = _irc; int fail = 0; - - if( !( irc->status & USTATUS_LOGGED_IN ) ) - { - if( now > ( irc->last_pong + IRC_LOGIN_TIMEOUT ) ) - fail = now - irc->last_pong; - } - else - { - if( now > ( irc->last_pong + global.conf->ping_timeout ) ) - { + + if (!(irc->status & USTATUS_LOGGED_IN)) { + if (now > (irc->last_pong + IRC_LOGIN_TIMEOUT)) { fail = now - irc->last_pong; } - else - { - irc_write( irc, "PING :%s", IRC_PING_STRING ); + } else { + if (now > (irc->last_pong + global.conf->ping_timeout)) { + fail = now - irc->last_pong; + } else { + irc_write(irc, "PING :%s", IRC_PING_STRING); } } - - if( fail > 0 ) - { - irc_abort( irc, 0, "Ping Timeout: %d seconds", fail ); + + if (fail > 0) { + irc_abort(irc, 0, "Ping Timeout: %d seconds", fail); return FALSE; } - + return TRUE; } -static char *set_eval_charset( set_t *set, char *value ) +static char *set_eval_charset(set_t *set, char *value) { - irc_t *irc = (irc_t*) set->data; + irc_t *irc = (irc_t *) set->data; char *test; gsize test_bytes = 0; GIConv ic, oc; - if( g_strcasecmp( value, "none" ) == 0 ) - value = g_strdup( "utf-8" ); + if (g_strcasecmp(value, "none") == 0) { + value = g_strdup("utf-8"); + } - if( ( oc = g_iconv_open( value, "utf-8" ) ) == (GIConv) -1 ) - { + if ((oc = g_iconv_open(value, "utf-8")) == (GIConv) - 1) { return NULL; } - + /* Do a test iconv to see if the user picked an IRC-compatible charset (for example utf-16 goes *horribly* wrong). */ - if( ( test = g_convert_with_iconv( " ", 1, oc, NULL, &test_bytes, NULL ) ) == NULL || - test_bytes > 1 ) - { - g_free( test ); - g_iconv_close( oc ); - irc_rootmsg( irc, "Unsupported character set: The IRC protocol " - "only supports 8-bit character sets." ); + if ((test = g_convert_with_iconv(" ", 1, oc, NULL, &test_bytes, NULL)) == NULL || + test_bytes > 1) { + g_free(test); + g_iconv_close(oc); + irc_rootmsg(irc, "Unsupported character set: The IRC protocol " + "only supports 8-bit character sets."); return NULL; } - g_free( test ); - - if( ( ic = g_iconv_open( "utf-8", value ) ) == (GIConv) -1 ) - { - g_iconv_close( oc ); + g_free(test); + + if ((ic = g_iconv_open("utf-8", value)) == (GIConv) - 1) { + g_iconv_close(oc); return NULL; } - - if( irc->iconv != (GIConv) -1 ) - g_iconv_close( irc->iconv ); - if( irc->oconv != (GIConv) -1 ) - g_iconv_close( irc->oconv ); - + + if (irc->iconv != (GIConv) - 1) { + g_iconv_close(irc->iconv); + } + if (irc->oconv != (GIConv) - 1) { + g_iconv_close(irc->oconv); + } + irc->iconv = ic; irc->oconv = oc; @@ -942,51 +924,52 @@ static char *set_eval_charset( set_t *set, char *value ) /* Mostly meant for upgrades. If one of these is set to the non-default, set show_users of all channels to something with the same effect. */ -static char *set_eval_bw_compat( set_t *set, char *value ) +static char *set_eval_bw_compat(set_t *set, char *value) { irc_t *irc = set->data; char *val; GSList *l; - - irc_rootmsg( irc, "Setting `%s' is obsolete, use the `show_users' " - "channel setting instead.", set->key ); - - if( strcmp( set->key, "away_devoice" ) == 0 && !bool2int( value ) ) + + irc_rootmsg(irc, "Setting `%s' is obsolete, use the `show_users' " + "channel setting instead.", set->key); + + if (strcmp(set->key, "away_devoice") == 0 && !bool2int(value)) { val = "online,special%,away"; - else if( strcmp( set->key, "show_offline" ) == 0 && bool2int( value ) ) + } else if (strcmp(set->key, "show_offline") == 0 && bool2int(value)) { val = "online@,special%,away+,offline"; - else + } else { val = "online+,special%,away"; - - for( l = irc->channels; l; l = l->next ) - { + } + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; /* No need to check channel type, if the setting doesn't exist it will just be ignored. */ - set_setstr( &ic->set, "show_users", val ); + set_setstr(&ic->set, "show_users", val); } - + return SET_INVALID; } -static char *set_eval_utf8_nicks( set_t *set, char *value ) +static char *set_eval_utf8_nicks(set_t *set, char *value) { irc_t *irc = set->data; - gboolean val = bool2int( value ); - + gboolean val = bool2int(value); + /* Do *NOT* unset this flag in the middle of a session. There will be UTF-8 nicks around already so if we suddenly disable support for them, various functions might behave strangely. */ - if( val ) + if (val) { irc->status |= IRC_UTF8_NICKS; - else if( irc->status & IRC_UTF8_NICKS ) - irc_rootmsg( irc, "You need to reconnect to BitlBee for this " - "change to take effect." ); - - return set_eval_bool( set, value ); + } else if (irc->status & IRC_UTF8_NICKS) { + irc_rootmsg(irc, "You need to reconnect to BitlBee for this " + "change to take effect."); + } + + return set_eval_bool(set, value); } -void register_irc_plugin( const struct irc_plugin *p ) +void register_irc_plugin(const struct irc_plugin *p) { - irc_plugins = g_slist_prepend( irc_plugins, (gpointer) p ); + irc_plugins = g_slist_prepend(irc_plugins, (gpointer) p); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -41,8 +41,7 @@ #define CTYPES "&#" /* Valid channel name prefixes */ -typedef enum -{ +typedef enum { USTATUS_OFFLINE = 0, USTATUS_AUTHORIZED = 1, /* Gave the correct server password (PASS). */ USTATUS_LOGGED_IN = 2, /* USER+NICK(+PASS) finished. */ @@ -60,15 +59,14 @@ typedef enum OPER_HACK_IDENTIFY_FORCE = 0x02100, OPER_HACK_REGISTER = 0x200, OPER_HACK_ACCOUNT_PASSWORD = 0x400, - OPER_HACK_ANY = 0x3700, /* To check for them all at once. */ - + OPER_HACK_ANY = 0x3700, /* To check for them all at once. */ + IRC_UTF8_NICKS = 0x10000, /* Disable ASCII restrictions on buddy nicks. */ } irc_status_t; struct irc_user; -typedef struct irc -{ +typedef struct irc { int fd; irc_status_t status; double last_pong; @@ -79,16 +77,16 @@ typedef struct irc struct irc_user *root; struct irc_user *user; - + char *password; /* HACK: Used to save the user's password, but before logging in, this may contain a password we should send to identify after USER/NICK are received. */ char umode[8]; - + struct query *queries; GSList *file_transfers; - + GSList *users, *channels; struct irc_channel *default_channel; GHashTable *nick_user_hash; @@ -98,117 +96,108 @@ typedef struct irc gint w_watch_source_id; gint ping_source_id; gint login_source_id; /* To slightly delay some events at login time. */ - + struct otr *otr; /* OTR state and book keeping, used by the OTR plugin. TODO: Some mechanism for plugindata. */ - + struct bee *b; } irc_t; -typedef enum -{ +typedef enum { /* Replaced with iu->last_channel IRC_USER_PRIVATE = 1, */ IRC_USER_AWAY = 2, - + IRC_USER_OTR_ENCRYPTED = 0x10000, IRC_USER_OTR_TRUSTED = 0x20000, } irc_user_flags_t; -typedef struct irc_user -{ +typedef struct irc_user { irc_t *irc; - + char *nick; char *user; char *host; char *fullname; - + /* Nickname in lowercase for case insensitive searches */ char *key; - + irc_user_flags_t flags; struct irc_channel *last_channel; - + GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */ guint pastebuf_timer; time_t away_reply_timeout; /* Only send a 301 if this time passed. */ - + struct bee_user *bu; - + const struct irc_user_funcs *f; } irc_user_t; -struct irc_user_funcs -{ - gboolean (*privmsg)( irc_user_t *iu, const char *msg ); - gboolean (*ctcp)( irc_user_t *iu, char * const* ctcp ); +struct irc_user_funcs { + gboolean (*privmsg)(irc_user_t *iu, const char *msg); + gboolean (*ctcp)(irc_user_t *iu, char * const* ctcp); }; extern const struct irc_user_funcs irc_user_root_funcs; extern const struct irc_user_funcs irc_user_self_funcs; -typedef enum -{ +typedef enum { IRC_CHANNEL_JOINED = 1, /* The user is currently in the channel. */ IRC_CHANNEL_TEMP = 2, /* Erase the channel when the user leaves, and don't save it. */ - + /* Hack: Set this flag right before jumping into IM when we expect a call to imcb_chat_new(). */ IRC_CHANNEL_CHAT_PICKME = 0x10000, } irc_channel_flags_t; -typedef struct irc_channel -{ +typedef struct irc_channel { irc_t *irc; char *name; char mode[8]; int flags; - + char *topic; char *topic_who; time_t topic_time; - + GSList *users; /* struct irc_channel_user */ struct irc_user *last_target; struct set *set; - + GString *pastebuf; /* Paste buffer (combine lines into a multiline msg). */ guint pastebuf_timer; - + const struct irc_channel_funcs *f; void *data; } irc_channel_t; -struct irc_channel_funcs -{ - gboolean (*privmsg)( irc_channel_t *ic, const char *msg ); - gboolean (*join)( irc_channel_t *ic ); - gboolean (*part)( irc_channel_t *ic, const char *msg ); - gboolean (*topic)( irc_channel_t *ic, const char *new_topic ); - gboolean (*invite)( irc_channel_t *ic, irc_user_t *iu ); - void (*kick)( irc_channel_t *ic, irc_user_t *iu, const char *msg ); - - gboolean (*_init)( irc_channel_t *ic ); - gboolean (*_free)( irc_channel_t *ic ); +struct irc_channel_funcs { + gboolean (*privmsg)(irc_channel_t *ic, const char *msg); + gboolean (*join)(irc_channel_t *ic); + gboolean (*part)(irc_channel_t *ic, const char *msg); + gboolean (*topic)(irc_channel_t *ic, const char *new_topic); + gboolean (*invite)(irc_channel_t *ic, irc_user_t *iu); + void (*kick)(irc_channel_t *ic, irc_user_t *iu, const char *msg); + + gboolean (*_init)(irc_channel_t *ic); + gboolean (*_free)(irc_channel_t *ic); }; -typedef enum -{ +typedef enum { IRC_CHANNEL_USER_OP = 1, IRC_CHANNEL_USER_HALFOP = 2, IRC_CHANNEL_USER_VOICE = 4, IRC_CHANNEL_USER_NONE = 8, } irc_channel_user_flags_t; -typedef struct irc_channel_user -{ +typedef struct irc_channel_user { irc_user_t *iu; int flags; } irc_channel_user_t; -typedef enum -{ +typedef enum { IRC_CC_TYPE_DEFAULT = 0x00001, IRC_CC_TYPE_REST = 0x00002, /* Still not implemented. */ IRC_CC_TYPE_GROUP = 0x00004, @@ -218,8 +207,7 @@ typedef enum IRC_CC_TYPE_INVERT = 0x00100, } irc_control_channel_type_t; -struct irc_control_channel -{ +struct irc_control_channel { irc_control_channel_type_t type; struct bee_group *group; struct account *account; @@ -229,8 +217,7 @@ struct irc_control_channel extern const struct bee_ui_funcs irc_ui_funcs; -typedef enum -{ +typedef enum { IRC_CDU_SILENT, IRC_CDU_PART, IRC_CDU_KICK, @@ -239,30 +226,29 @@ typedef enum /* 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 -{ +typedef struct irc_plugin { /* Called at the end of irc_new(). Can be used to add settings, etc. */ - gboolean (*irc_new)( irc_t *irc ); + gboolean (*irc_new)(irc_t *irc); /* At the end of irc_free(). */ - void (*irc_free)( irc_t *irc ); - + void (*irc_free)(irc_t *irc); + /* Problem with the following two functions is ordering if multiple plugins are handling them. Let's keep fixing that problem for whenever it becomes important. */ - + /* 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, char *msg, int flags ); + char* (*filter_msg_out)(irc_user_t * iu, 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, char *msg, int flags ); - + char* (*filter_msg_in)(irc_user_t * iu, char *msg, int flags); + /* From storage.c functions. Ideally these should not be used and instead data should be stored in settings which will get saved automatically. Consider these deprecated! */ - void (*storage_load)( irc_t *irc ); - void (*storage_save)( irc_t *irc ); - void (*storage_remove)( const char *nick ); + void (*storage_load)(irc_t *irc); + void (*storage_save)(irc_t *irc); + void (*storage_remove)(const char *nick); } irc_plugin_t; extern GSList *irc_plugins; /* struct irc_plugin */ @@ -270,94 +256,94 @@ extern GSList *irc_plugins; /* struct irc_plugin */ /* irc.c */ extern GSList *irc_connection_list; -irc_t *irc_new( int fd ); -void irc_abort( irc_t *irc, int immed, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); -void irc_free( irc_t *irc ); -void irc_setpass (irc_t *irc, const char *pass); +irc_t *irc_new(int fd); +void irc_abort(irc_t *irc, int immed, char *format, ...) G_GNUC_PRINTF(3, 4); +void irc_free(irc_t *irc); +void irc_setpass(irc_t *irc, const char *pass); -void irc_process( irc_t *irc ); -char **irc_parse_line( char *line ); -char *irc_build_line( char **cmd ); +void irc_process(irc_t *irc); +char **irc_parse_line(char *line); +char *irc_build_line(char **cmd); -void irc_write( irc_t *irc, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); -void irc_write_all( int now, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); -void irc_vawrite( irc_t *irc, char *format, va_list params ); +void irc_write(irc_t *irc, char *format, ...) G_GNUC_PRINTF(2, 3); +void irc_write_all(int now, char *format, ...) G_GNUC_PRINTF(2, 3); +void irc_vawrite(irc_t *irc, char *format, va_list params); -void irc_flush( irc_t *irc ); -void irc_switch_fd( irc_t *irc, int fd ); -void irc_sync( irc_t *irc ); -void irc_desync( irc_t *irc ); +void irc_flush(irc_t *irc); +void irc_switch_fd(irc_t *irc, int fd); +void irc_sync(irc_t *irc); +void irc_desync(irc_t *irc); -int irc_check_login( irc_t *irc ); +int irc_check_login(irc_t *irc); -void irc_umode_set( irc_t *irc, const char *s, gboolean allow_priv ); +void irc_umode_set(irc_t *irc, const char *s, gboolean allow_priv); -void register_irc_plugin( const struct irc_plugin *p ); +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 ); -irc_channel_t *irc_channel_get( irc_t *irc, char *id ); -int irc_channel_free( irc_channel_t *ic ); -void irc_channel_free_soon( irc_channel_t *ic ); -int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu ); -int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu, irc_channel_del_user_type_t type, const char *msg ); -irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu ); -struct irc_channel *irc_channel_with_user( irc_t *irc, irc_user_t *iu ); -int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who ); -void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags ); -void irc_channel_set_mode( irc_channel_t *ic, const char *s ); -void irc_channel_auto_joins( irc_t *irc, struct account *acc ); -void irc_channel_printf( irc_channel_t *ic, char *format, ... ); -gboolean irc_channel_name_ok( const char *name ); -void irc_channel_name_strip( char *name ); -int irc_channel_name_cmp( const char *a_, const char *b_ ); -void irc_channel_update_ops( irc_channel_t *ic, char *value ); -char *set_eval_irc_channel_ops( struct set *set, char *value ); -gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu ); +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); +irc_channel_t *irc_channel_get(irc_t *irc, char *id); +int irc_channel_free(irc_channel_t *ic); +void irc_channel_free_soon(irc_channel_t *ic); +int irc_channel_add_user(irc_channel_t *ic, irc_user_t *iu); +int irc_channel_del_user(irc_channel_t *ic, irc_user_t *iu, irc_channel_del_user_type_t type, const char *msg); +irc_channel_user_t *irc_channel_has_user(irc_channel_t *ic, irc_user_t *iu); +struct irc_channel *irc_channel_with_user(irc_t *irc, irc_user_t *iu); +int irc_channel_set_topic(irc_channel_t *ic, const char *topic, const irc_user_t *who); +void irc_channel_user_set_mode(irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags); +void irc_channel_set_mode(irc_channel_t *ic, const char *s); +void irc_channel_auto_joins(irc_t *irc, struct account *acc); +void irc_channel_printf(irc_channel_t *ic, char *format, ...); +gboolean irc_channel_name_ok(const char *name); +void irc_channel_name_strip(char *name); +int irc_channel_name_cmp(const char *a_, const char *b_); +void irc_channel_update_ops(irc_channel_t *ic, char *value); +char *set_eval_irc_channel_ops(struct set *set, char *value); +gboolean irc_channel_wants_user(irc_channel_t *ic, irc_user_t *iu); /* irc_commands.c */ -void irc_exec( irc_t *irc, char **cmd ); +void irc_exec(irc_t *irc, char **cmd); /* irc_send.c */ -void irc_send_num( irc_t *irc, int code, char *format, ... ) G_GNUC_PRINTF( 3, 4 ); -void irc_send_login( irc_t *irc ); -void irc_send_motd( irc_t *irc ); -const char *irc_user_msgdest( irc_user_t *iu ); -void irc_rootmsg( irc_t *irc, char *format, ... ); -void irc_usermsg( irc_user_t *iu, char *format, ... ); -void irc_usernotice( irc_user_t *iu, char *format, ... ); -void irc_send_join( irc_channel_t *ic, irc_user_t *iu ); -void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason ); -void irc_send_quit( irc_user_t *iu, const char *reason ); -void irc_send_kick( irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const char *reason ); -void irc_send_names( irc_channel_t *ic ); -void irc_send_topic( irc_channel_t *ic, gboolean topic_change ); -void irc_send_whois( irc_user_t *iu ); -void irc_send_who( irc_t *irc, GSList *l, const char *channel ); -void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix ); -void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg ); -void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 ); -void irc_send_nick( irc_user_t *iu, const char *new_nick ); -void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu, - irc_channel_user_flags_t old_flags, irc_channel_user_flags_t new_flags ); -void irc_send_invite( irc_user_t *iu, irc_channel_t *ic ); +void irc_send_num(irc_t *irc, int code, char *format, ...) G_GNUC_PRINTF(3, 4); +void irc_send_login(irc_t *irc); +void irc_send_motd(irc_t *irc); +const char *irc_user_msgdest(irc_user_t *iu); +void irc_rootmsg(irc_t *irc, char *format, ...); +void irc_usermsg(irc_user_t *iu, char *format, ...); +void irc_usernotice(irc_user_t *iu, char *format, ...); +void irc_send_join(irc_channel_t *ic, irc_user_t *iu); +void irc_send_part(irc_channel_t *ic, irc_user_t *iu, const char *reason); +void irc_send_quit(irc_user_t *iu, const char *reason); +void irc_send_kick(irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const char *reason); +void irc_send_names(irc_channel_t *ic); +void irc_send_topic(irc_channel_t *ic, gboolean topic_change); +void irc_send_whois(irc_user_t *iu); +void irc_send_who(irc_t *irc, GSList *l, const char *channel); +void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix); +void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char *msg); +void irc_send_msg_f(irc_user_t *iu, const char *type, const char *dst, const char *format, ...) G_GNUC_PRINTF(4, 5); +void irc_send_nick(irc_user_t *iu, const char *new_nick); +void irc_send_channel_user_mode_diff(irc_channel_t *ic, irc_user_t *iu, + irc_channel_user_flags_t old_flags, irc_channel_user_flags_t new_flags); +void irc_send_invite(irc_user_t *iu, irc_channel_t *ic); /* irc_user.c */ -irc_user_t *irc_user_new( irc_t *irc, const char *nick ); -int irc_user_free( irc_t *irc, irc_user_t *iu ); -irc_user_t *irc_user_by_name( irc_t *irc, const char *nick ); -int irc_user_set_nick( irc_user_t *iu, const char *new_nick ); -gint irc_user_cmp( gconstpointer a_, gconstpointer b_ ); -const char *irc_user_get_away( irc_user_t *iu ); -void irc_user_quit( irc_user_t *iu, const char *msg ); +irc_user_t *irc_user_new(irc_t *irc, const char *nick); +int irc_user_free(irc_t *irc, irc_user_t *iu); +irc_user_t *irc_user_by_name(irc_t *irc, const char *nick); +int irc_user_set_nick(irc_user_t *iu, const char *new_nick); +gint irc_user_cmp(gconstpointer a_, gconstpointer b_); +const char *irc_user_get_away(irc_user_t *iu); +void irc_user_quit(irc_user_t *iu, const char *msg); /* irc_util.c */ -char *set_eval_timezone( struct set *set, char *value ); -char *irc_format_timestamp( irc_t *irc, time_t msg_ts ); +char *set_eval_timezone(struct set *set, char *value); +char *irc_format_timestamp(irc_t *irc, time_t msg_ts); /* irc_im.c */ -void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu ); -void bee_irc_user_nick_reset( irc_user_t *iu ); +void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu); +void bee_irc_user_nick_reset(irc_user_t *iu); #endif diff --git a/irc_channel.c b/irc_channel.c index 4fe0fad4..b4257ba6 100644 --- a/irc_channel.c +++ b/irc_channel.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -25,796 +25,827 @@ #include "bitlbee.h" -static char *set_eval_channel_type( set_t *set, char *value ); -static gint irc_channel_user_cmp( gconstpointer a_, gconstpointer b_ ); +static char *set_eval_channel_type(set_t *set, char *value); +static gint irc_channel_user_cmp(gconstpointer a_, gconstpointer b_); static const struct irc_channel_funcs control_channel_funcs; extern const struct irc_channel_funcs irc_channel_im_chat_funcs; -irc_channel_t *irc_channel_new( irc_t *irc, const char *name ) +irc_channel_t *irc_channel_new(irc_t *irc, const char *name) { irc_channel_t *ic; set_t *s; - - if( !irc_channel_name_ok( name ) || irc_channel_by_name( irc, name ) ) + + if (!irc_channel_name_ok(name) || irc_channel_by_name(irc, name)) { return NULL; - - ic = g_new0( irc_channel_t, 1 ); + } + + ic = g_new0(irc_channel_t, 1); ic->irc = irc; - ic->name = g_strdup( name ); - strcpy( ic->mode, CMODE ); - - irc_channel_add_user( ic, irc->root ); - - irc->channels = g_slist_append( irc->channels, ic ); - - set_add( &ic->set, "auto_join", "false", set_eval_bool, ic ); - - s = set_add( &ic->set, "type", "control", set_eval_channel_type, ic ); + ic->name = g_strdup(name); + strcpy(ic->mode, CMODE); + + irc_channel_add_user(ic, irc->root); + + irc->channels = g_slist_append(irc->channels, ic); + + set_add(&ic->set, "auto_join", "false", set_eval_bool, ic); + + s = set_add(&ic->set, "type", "control", set_eval_channel_type, ic); s->flags |= SET_NOSAVE; /* Layer violation (XML format detail) */ - - if( name[0] == '&' ) - set_setstr( &ic->set, "type", "control" ); - else /* if( name[0] == '#' ) */ - set_setstr( &ic->set, "type", "chat" ); - + + if (name[0] == '&') { + set_setstr(&ic->set, "type", "control"); + } else { /* if( name[0] == '#' ) */ + set_setstr(&ic->set, "type", "chat"); + } + return ic; } -irc_channel_t *irc_channel_by_name( irc_t *irc, const char *name ) +irc_channel_t *irc_channel_by_name(irc_t *irc, const char *name) { GSList *l; - - for( l = irc->channels; l; l = l->next ) - { + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - if( irc_channel_name_cmp( name, ic->name ) == 0 ) + + if (irc_channel_name_cmp(name, ic->name) == 0) { return ic; + } } - + return NULL; } -irc_channel_t *irc_channel_get( irc_t *irc, char *id ) +irc_channel_t *irc_channel_get(irc_t *irc, char *id) { irc_channel_t *ic, *ret = NULL; GSList *l; int nr; - - if( sscanf( id, "%d", &nr ) == 1 && nr < 1000 ) - { - for( l = irc->channels; l; l = l->next ) - { + + if (sscanf(id, "%d", &nr) == 1 && nr < 1000) { + for (l = irc->channels; l; l = l->next) { ic = l->data; - if( ( nr-- ) == 0 ) + if ((nr--) == 0) { return ic; + } } - + return NULL; } - + /* Exact match first: Partial match only sucks if there's a channel #aa and #aabb */ - if( ( ret = irc_channel_by_name( irc, id ) ) ) + if ((ret = irc_channel_by_name(irc, id))) { return ret; - - for( l = irc->channels; l; l = l->next ) - { + } + + for (l = irc->channels; l; l = l->next) { ic = l->data; - - if( strstr( ic->name, id ) ) - { + + if (strstr(ic->name, id)) { /* Make sure it's a unique match. */ - if( !ret ) + if (!ret) { ret = ic; - else + } else { return NULL; + } } } - + return ret; } -int irc_channel_free( irc_channel_t *ic ) +int irc_channel_free(irc_channel_t *ic) { irc_t *irc; GSList *l; - - if( ic == NULL ) + + if (ic == NULL) { return 0; + } irc = ic->irc; - - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_channel_del_user( ic, irc->user, IRC_CDU_KICK, "Cleaning up channel" ); - - if( ic->f->_free ) - ic->f->_free( ic ); - - while( ic->set ) - set_del( &ic->set, ic->set->key ); - - irc->channels = g_slist_remove( irc->channels, ic ); - while( ic->users ) - { - g_free( ic->users->data ); - ic->users = g_slist_remove( ic->users, ic->users->data ); - } - - for( l = irc->users; l; l = l->next ) - { + + if (ic->flags & IRC_CHANNEL_JOINED) { + irc_channel_del_user(ic, irc->user, IRC_CDU_KICK, "Cleaning up channel"); + } + + if (ic->f->_free) { + ic->f->_free(ic); + } + + while (ic->set) { + set_del(&ic->set, ic->set->key); + } + + irc->channels = g_slist_remove(irc->channels, ic); + while (ic->users) { + g_free(ic->users->data); + ic->users = g_slist_remove(ic->users, ic->users->data); + } + + for (l = irc->users; l; l = l->next) { irc_user_t *iu = l->data; - - if( iu->last_channel == ic ) + + if (iu->last_channel == ic) { iu->last_channel = irc->default_channel; + } + } + + if (ic->pastebuf_timer) { + b_event_remove(ic->pastebuf_timer); } - - if( ic->pastebuf_timer ) b_event_remove( ic->pastebuf_timer ); - - g_free( ic->name ); - g_free( ic->topic ); - g_free( ic->topic_who ); - g_free( ic ); - + + g_free(ic->name); + g_free(ic->topic); + g_free(ic->topic_who); + g_free(ic); + return 1; } -struct irc_channel_free_data -{ +struct irc_channel_free_data { irc_t *irc; irc_channel_t *ic; char *name; }; -static gboolean irc_channel_free_callback( gpointer data, gint fd, b_input_condition cond ) +static gboolean irc_channel_free_callback(gpointer data, gint fd, b_input_condition cond) { struct irc_channel_free_data *d = data; - - if( g_slist_find( irc_connection_list, d->irc ) && - irc_channel_by_name( d->irc, d->name ) == d->ic && - !( d->ic->flags & IRC_CHANNEL_JOINED ) ) - irc_channel_free( d->ic ); - - g_free( d->name ); - g_free( d ); + + if (g_slist_find(irc_connection_list, d->irc) && + irc_channel_by_name(d->irc, d->name) == d->ic && + !(d->ic->flags & IRC_CHANNEL_JOINED)) { + irc_channel_free(d->ic); + } + + g_free(d->name); + g_free(d); return FALSE; } /* Free the channel, but via the event loop, so after finishing whatever event we're currently handling. */ -void irc_channel_free_soon( irc_channel_t *ic ) +void irc_channel_free_soon(irc_channel_t *ic) { - struct irc_channel_free_data *d = g_new0( struct irc_channel_free_data, 1 ); - + struct irc_channel_free_data *d = g_new0(struct irc_channel_free_data, 1); + d->irc = ic->irc; d->ic = ic; - d->name = g_strdup( ic->name ); - - b_timeout_add( 0, irc_channel_free_callback, d ); + d->name = g_strdup(ic->name); + + b_timeout_add(0, irc_channel_free_callback, d); } -static char *set_eval_channel_type( set_t *set, char *value ) +static char *set_eval_channel_type(set_t *set, char *value) { struct irc_channel *ic = set->data; const struct irc_channel_funcs *new; - - if( strcmp( value, "control" ) == 0 ) + + if (strcmp(value, "control") == 0) { new = &control_channel_funcs; - else if( ic != ic->irc->default_channel && strcmp( value, "chat" ) == 0 ) + } else if (ic != ic->irc->default_channel && strcmp(value, "chat") == 0) { new = &irc_channel_im_chat_funcs; - else + } else { return SET_INVALID; - + } + /* TODO: Return values. */ - if( ic->f && ic->f->_free ) - ic->f->_free( ic ); - + if (ic->f && ic->f->_free) { + ic->f->_free(ic); + } + ic->f = new; - - if( ic->f && ic->f->_init ) - ic->f->_init( ic ); - + + if (ic->f && ic->f->_init) { + ic->f->_init(ic); + } + return value; } -int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu ) +int irc_channel_add_user(irc_channel_t *ic, irc_user_t *iu) { irc_channel_user_t *icu; - - if( irc_channel_has_user( ic, iu ) ) + + if (irc_channel_has_user(ic, iu)) { return 0; - - icu = g_new0( irc_channel_user_t, 1 ); + } + + icu = g_new0(irc_channel_user_t, 1); icu->iu = iu; - - ic->users = g_slist_insert_sorted( ic->users, icu, irc_channel_user_cmp ); - - irc_channel_update_ops( ic, set_getstr( &ic->irc->b->set, "ops" ) ); - - if( iu == ic->irc->user || ic->flags & IRC_CHANNEL_JOINED ) - { + + ic->users = g_slist_insert_sorted(ic->users, icu, irc_channel_user_cmp); + + irc_channel_update_ops(ic, set_getstr(&ic->irc->b->set, "ops")); + + if (iu == ic->irc->user || ic->flags & IRC_CHANNEL_JOINED) { ic->flags |= IRC_CHANNEL_JOINED; - irc_send_join( ic, iu ); + irc_send_join(ic, iu); } - + return 1; } -int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu, irc_channel_del_user_type_t type, const char *msg ) +int irc_channel_del_user(irc_channel_t *ic, irc_user_t *iu, irc_channel_del_user_type_t type, const char *msg) { irc_channel_user_t *icu; - - if( !( icu = irc_channel_has_user( ic, iu ) ) ) + + if (!(icu = irc_channel_has_user(ic, iu))) { return 0; - - ic->users = g_slist_remove( ic->users, icu ); - g_free( icu ); - - if( !( ic->flags & IRC_CHANNEL_JOINED ) || type == IRC_CDU_SILENT ) {} - /* Do nothing. The caller should promise it won't screw - up state of the IRC client. :-) */ - else if( type == IRC_CDU_PART ) - irc_send_part( ic, iu, msg ); - else if( type == IRC_CDU_KICK ) - irc_send_kick( ic, iu, ic->irc->root, msg ); - - if( iu == ic->irc->user ) - { + } + + ic->users = g_slist_remove(ic->users, icu); + g_free(icu); + + if (!(ic->flags & IRC_CHANNEL_JOINED) || type == IRC_CDU_SILENT) { + } + /* Do nothing. The caller should promise it won't screw + up state of the IRC client. :-) */ + else if (type == IRC_CDU_PART) { + irc_send_part(ic, iu, msg); + } else if (type == IRC_CDU_KICK) { + irc_send_kick(ic, iu, ic->irc->root, msg); + } + + if (iu == ic->irc->user) { ic->flags &= ~IRC_CHANNEL_JOINED; - - if( ic->irc->status & USTATUS_SHUTDOWN ) - { + + if (ic->irc->status & USTATUS_SHUTDOWN) { /* Don't do anything fancy when we're shutting down anyway. */ - } - else if( ic->flags & IRC_CHANNEL_TEMP ) - { - irc_channel_free_soon( ic ); - } - else - { + } else if (ic->flags & IRC_CHANNEL_TEMP) { + irc_channel_free_soon(ic); + } else { /* Flush userlist now. The user won't see it anyway. */ - while( ic->users ) - { - g_free( ic->users->data ); - ic->users = g_slist_remove( ic->users, ic->users->data ); + while (ic->users) { + g_free(ic->users->data); + ic->users = g_slist_remove(ic->users, ic->users->data); } - irc_channel_add_user( ic, ic->irc->root ); + irc_channel_add_user(ic, ic->irc->root); } } - + return 1; } -irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu ) +irc_channel_user_t *irc_channel_has_user(irc_channel_t *ic, irc_user_t *iu) { GSList *l; - - for( l = ic->users; l; l = l->next ) - { + + for (l = ic->users; l; l = l->next) { irc_channel_user_t *icu = l->data; - - if( icu->iu == iu ) + + if (icu->iu == iu) { return icu; + } } - + return NULL; } /* Find a channel we're currently in, that currently has iu in it. */ -struct irc_channel *irc_channel_with_user( irc_t *irc, irc_user_t *iu ) +struct irc_channel *irc_channel_with_user(irc_t *irc, irc_user_t *iu) { GSList *l; - - for( l = irc->channels; l; l = l->next ) - { + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 ) + + if (strcmp(set_getstr(&ic->set, "type"), "control") != 0) { continue; - - if( ( ic->flags & IRC_CHANNEL_JOINED ) && - irc_channel_has_user( ic, iu ) ) + } + + if ((ic->flags & IRC_CHANNEL_JOINED) && + irc_channel_has_user(ic, iu)) { return ic; + } } - + /* If there was no match, try once more but just see if the user *would* be in the channel, i.e. if s/he were online. */ - if( iu->bu == NULL ) + if (iu->bu == NULL) { return NULL; - - for( l = irc->channels; l; l = l->next ) - { + } + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 ) + + if (strcmp(set_getstr(&ic->set, "type"), "control") != 0) { continue; - - if( ( ic->flags & IRC_CHANNEL_JOINED ) && - irc_channel_wants_user( ic, iu ) ) + } + + if ((ic->flags & IRC_CHANNEL_JOINED) && + irc_channel_wants_user(ic, iu)) { return ic; + } } - + return NULL; } -int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *iu ) +int irc_channel_set_topic(irc_channel_t *ic, const char *topic, const irc_user_t *iu) { - g_free( ic->topic ); - ic->topic = g_strdup( topic ); - - g_free( ic->topic_who ); - if( iu ) - ic->topic_who = g_strdup_printf( "%s!%s@%s", iu->nick, iu->user, iu->host ); - else + g_free(ic->topic); + ic->topic = g_strdup(topic); + + g_free(ic->topic_who); + if (iu) { + ic->topic_who = g_strdup_printf("%s!%s@%s", iu->nick, iu->user, iu->host); + } else { ic->topic_who = NULL; - - ic->topic_time = time( NULL ); - - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_send_topic( ic, TRUE ); - + } + + ic->topic_time = time(NULL); + + if (ic->flags & IRC_CHANNEL_JOINED) { + irc_send_topic(ic, TRUE); + } + return 1; } -void irc_channel_user_set_mode( irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags ) +void irc_channel_user_set_mode(irc_channel_t *ic, irc_user_t *iu, irc_channel_user_flags_t flags) { - irc_channel_user_t *icu = irc_channel_has_user( ic, iu ); - - if( !icu || icu->flags == flags ) + irc_channel_user_t *icu = irc_channel_has_user(ic, iu); + + if (!icu || icu->flags == flags) { return; - - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_send_channel_user_mode_diff( ic, iu, icu->flags, flags ); - + } + + if (ic->flags & IRC_CHANNEL_JOINED) { + irc_send_channel_user_mode_diff(ic, iu, icu->flags, flags); + } + icu->flags = flags; } -void irc_channel_set_mode( irc_channel_t *ic, const char *s ) +void irc_channel_set_mode(irc_channel_t *ic, const char *s) { irc_t *irc = ic->irc; char m[128], st = 1; const char *t; int i; char changes[512], *p, st2 = 2; - - memset( m, 0, sizeof( m ) ); - - for( t = ic->mode; *t; t ++ ) - if( *t < sizeof( m ) ) - m[(int)*t] = 1; - + + memset(m, 0, sizeof(m)); + + for (t = ic->mode; *t; t++) { + if (*t < sizeof(m)) { + m[(int) *t] = 1; + } + } + p = changes; - for( t = s; *t; t ++ ) - { - if( *t == '+' || *t == '-' ) + for (t = s; *t; t++) { + if (*t == '+' || *t == '-') { st = *t == '+'; - else if( strchr( CMODES, *t ) ) - { - if( m[(int)*t] != st) - { - if( st != st2 ) + } else if (strchr(CMODES, *t)) { + if (m[(int) *t] != st) { + if (st != st2) { st2 = st, *p++ = st ? '+' : '-'; + } *p++ = *t; } - m[(int)*t] = st; + m[(int) *t] = st; } } *p = '\0'; - - memset( ic->mode, 0, sizeof( ic->mode ) ); - - for( i = 'A'; i <= 'z' && strlen( ic->mode ) < ( sizeof( ic->mode ) - 1 ); i ++ ) - if( m[i] ) + + memset(ic->mode, 0, sizeof(ic->mode)); + + for (i = 'A'; i <= 'z' && strlen(ic->mode) < (sizeof(ic->mode) - 1); i++) { + if (m[i]) { ic->mode[strlen(ic->mode)] = i; - - if( *changes && ( ic->flags & IRC_CHANNEL_JOINED ) ) - irc_write( irc, ":%s!%s@%s MODE %s :%s", irc->root->nick, - irc->root->user, irc->root->host, ic->name, - changes ); + } + } + + if (*changes && (ic->flags & IRC_CHANNEL_JOINED)) { + irc_write(irc, ":%s!%s@%s MODE %s :%s", irc->root->nick, + irc->root->user, irc->root->host, ic->name, + changes); + } } -void irc_channel_auto_joins( irc_t *irc, account_t *acc ) +void irc_channel_auto_joins(irc_t *irc, account_t *acc) { GSList *l; - - for( l = irc->channels; l; l = l->next ) - { + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - gboolean aj = set_getbool( &ic->set, "auto_join" ); + gboolean aj = set_getbool(&ic->set, "auto_join"); char *type; - - if( acc && - ( type = set_getstr( &ic->set, "chat_type" ) ) && - strcmp( type, "room" ) == 0 ) - { + + if (acc && + (type = set_getstr(&ic->set, "chat_type")) && + strcmp(type, "room") == 0) { /* Bit of an ugly special case: Handle chatrooms here, we can only auto-join them if their account is online. */ char *acc_s; - - if( !aj || ( ic->flags & IRC_CHANNEL_JOINED ) ) + + if (!aj || (ic->flags & IRC_CHANNEL_JOINED)) { /* Only continue if this one's marked as auto_join or if we're in it already. (Possible if the client auto-rejoined it before identyfing.) */ continue; - else if( !( acc_s = set_getstr( &ic->set, "account" ) ) ) + } else if (!(acc_s = set_getstr(&ic->set, "account"))) { continue; - else if( account_get( irc->b, acc_s ) != acc ) + } else if (account_get(irc->b, acc_s) != acc) { continue; - else if( acc->ic == NULL || !( acc->ic->flags & OPT_LOGGED_IN ) ) + } else if (acc->ic == NULL || !(acc->ic->flags & OPT_LOGGED_IN)) { continue; - else - ic->f->join( ic ); - } - else if( aj ) - { - irc_channel_add_user( ic, irc->user ); + } else { + ic->f->join(ic); + } + } else if (aj) { + irc_channel_add_user(ic, irc->user); } } } -void irc_channel_printf( irc_channel_t *ic, char *format, ... ) +void irc_channel_printf(irc_channel_t *ic, char *format, ...) { va_list params; char *text; - - va_start( params, format ); - text = g_strdup_vprintf( format, params ); - va_end( params ); - - irc_send_msg( ic->irc->root, "PRIVMSG", ic->name, text, NULL ); - g_free( text ); + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + irc_send_msg(ic->irc->root, "PRIVMSG", ic->name, text, NULL); + g_free(text); } -gboolean irc_channel_name_ok( const char *name_ ) +gboolean irc_channel_name_ok(const char *name_) { - const unsigned char *name = (unsigned char*) name_; + const unsigned char *name = (unsigned char *) name_; int i; - - if( name_[0] == '\0' ) + + if (name_[0] == '\0') { return FALSE; - + } + /* Check if the first character is in CTYPES (#&) */ - if( strchr( CTYPES, name_[0] ) == NULL ) + if (strchr(CTYPES, name_[0]) == NULL) { return FALSE; - + } + /* RFC 1459 keeps amazing me: While only a "few" chars are allowed in nicknames, channel names can be pretty much anything as long as they start with # or &. I'll be a little bit more strict and disallow all non-printable characters. */ - for( i = 1; name[i]; i ++ ) - if( name[i] <= ' ' || name[i] == ',' ) + for (i = 1; name[i]; i++) { + if (name[i] <= ' ' || name[i] == ',') { return FALSE; - + } + } + return TRUE; } -void irc_channel_name_strip( char *name ) +void irc_channel_name_strip(char *name) { int i, j; - - for( i = j = 0; name[i]; i ++ ) - if( name[i] > ' ' && name[i] != ',' ) + + for (i = j = 0; name[i]; i++) { + if (name[i] > ' ' && name[i] != ',') { name[j++] = name[i]; - + } + } + name[j] = '\0'; } -int irc_channel_name_cmp( const char *a_, const char *b_ ) +int irc_channel_name_cmp(const char *a_, const char *b_) { static unsigned char case_map[256]; - const unsigned char *a = (unsigned char*) a_, *b = (unsigned char*) b_; + const unsigned char *a = (unsigned char *) a_, *b = (unsigned char *) b_; int i; - - if( case_map['A'] == '\0' ) - { - for( i = 33; i < 256; i ++ ) - if( i != ',' ) + + if (case_map['A'] == '\0') { + for (i = 33; i < 256; i++) { + if (i != ',') { case_map[i] = i; - - for( i = 0; i < 26; i ++ ) - case_map['A'+i] = 'a' + i; - + } + } + + for (i = 0; i < 26; i++) { + case_map['A' + i] = 'a' + i; + } + case_map['['] = '{'; case_map[']'] = '}'; case_map['~'] = '`'; case_map['\\'] = '|'; } - - if( !irc_channel_name_ok( a_ ) || !irc_channel_name_ok( b_ ) ) + + if (!irc_channel_name_ok(a_) || !irc_channel_name_ok(b_)) { return -1; - - for( i = 0; a[i] && b[i] && case_map[a[i]] && case_map[b[i]]; i ++ ) - { - if( case_map[a[i]] == case_map[b[i]] ) + } + + for (i = 0; a[i] && b[i] && case_map[a[i]] && case_map[b[i]]; i++) { + if (case_map[a[i]] == case_map[b[i]]) { continue; - else + } else { return case_map[a[i]] - case_map[b[i]]; + } } - + return case_map[a[i]] - case_map[b[i]]; } -static gint irc_channel_user_cmp( gconstpointer a_, gconstpointer b_ ) +static gint irc_channel_user_cmp(gconstpointer a_, gconstpointer b_) { const irc_channel_user_t *a = a_, *b = b_; - - return irc_user_cmp( a->iu, b->iu ); + + return irc_user_cmp(a->iu, b->iu); } -void irc_channel_update_ops( irc_channel_t *ic, char *value ) +void irc_channel_update_ops(irc_channel_t *ic, char *value) { - irc_channel_user_set_mode( ic, ic->irc->root, - ( strcmp( value, "both" ) == 0 || - strcmp( value, "root" ) == 0 ) ? IRC_CHANNEL_USER_OP : 0 ); - irc_channel_user_set_mode( ic, ic->irc->user, - ( strcmp( value, "both" ) == 0 || - strcmp( value, "user" ) == 0 ) ? IRC_CHANNEL_USER_OP : 0 ); + irc_channel_user_set_mode(ic, ic->irc->root, + (strcmp(value, "both") == 0 || + strcmp(value, "root") == 0) ? IRC_CHANNEL_USER_OP : 0); + irc_channel_user_set_mode(ic, ic->irc->user, + (strcmp(value, "both") == 0 || + strcmp(value, "user") == 0) ? IRC_CHANNEL_USER_OP : 0); } -char *set_eval_irc_channel_ops( set_t *set, char *value ) +char *set_eval_irc_channel_ops(set_t *set, char *value) { irc_t *irc = set->data; GSList *l; - - if( strcmp( value, "both" ) != 0 && strcmp( value, "none" ) != 0 && - strcmp( value, "user" ) != 0 && strcmp( value, "root" ) != 0 ) + + if (strcmp(value, "both") != 0 && strcmp(value, "none") != 0 && + strcmp(value, "user") != 0 && strcmp(value, "root") != 0) { return SET_INVALID; - - for( l = irc->channels; l; l = l->next ) - irc_channel_update_ops( l->data, value ); - + } + + for (l = irc->channels; l; l = l->next) { + irc_channel_update_ops(l->data, value); + } + return value; } /* Channel-type dependent functions, for control channels: */ -static gboolean control_channel_privmsg( irc_channel_t *ic, const char *msg ) +static gboolean control_channel_privmsg(irc_channel_t *ic, const char *msg) { irc_t *irc = ic->irc; irc_user_t *iu; const char *s; - + /* Scan for non-whitespace chars followed by a colon: */ - for( s = msg; *s && !g_ascii_isspace( *s ) && *s != ':' && *s != ','; s ++ ) {} - - if( *s == ':' || *s == ',' ) - { - char to[s-msg+1]; - - memset( to, 0, sizeof( to ) ); - strncpy( to, msg, s - msg ); - while( *(++s) && g_ascii_isspace( *s ) ) {} + for (s = msg; *s && !g_ascii_isspace(*s) && *s != ':' && *s != ','; s++) { + } + + if (*s == ':' || *s == ',') { + char to[s - msg + 1]; + + memset(to, 0, sizeof(to)); + strncpy(to, msg, s - msg); + while (*(++s) && g_ascii_isspace(*s)) { + } msg = s; - - if( !( iu = irc_user_by_name( irc, to ) ) ) - irc_channel_printf( ic, "User does not exist: %s", to ); - else + + if (!(iu = irc_user_by_name(irc, to))) { + irc_channel_printf(ic, "User does not exist: %s", to); + } else { ic->last_target = iu; - } - else if( g_strcasecmp( set_getstr( &irc->b->set, "default_target" ), "last" ) == 0 && - ic->last_target && g_slist_find( irc->users, ic->last_target ) ) + } + } else if (g_strcasecmp(set_getstr(&irc->b->set, "default_target"), "last") == 0 && + ic->last_target && g_slist_find(irc->users, ic->last_target)) { iu = ic->last_target; - else + } else { iu = irc->root; - - if( iu && iu->f->privmsg ) - { + } + + if (iu && iu->f->privmsg) { iu->last_channel = ic; - iu->f->privmsg( iu, msg ); + iu->f->privmsg(iu, msg); } - + return TRUE; } -static gboolean control_channel_invite( irc_channel_t *ic, irc_user_t *iu ) +static gboolean control_channel_invite(irc_channel_t *ic, irc_user_t *iu) { struct irc_control_channel *icc = ic->data; bee_user_t *bu = iu->bu; - - if( bu == NULL ) + + if (bu == NULL) { return FALSE; - - if( icc->type != IRC_CC_TYPE_GROUP ) - { - irc_send_num( ic->irc, 482, "%s :Invitations are only possible to fill_by=group channels", ic->name ); + } + + if (icc->type != IRC_CC_TYPE_GROUP) { + irc_send_num(ic->irc, 482, "%s :Invitations are only possible to fill_by=group channels", ic->name); return FALSE; } - - bu->ic->acc->prpl->add_buddy( bu->ic, bu->handle, - icc->group ? icc->group->name : NULL ); - + + bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle, + icc->group ? icc->group->name : NULL); + return TRUE; } -static void control_channel_kick( irc_channel_t *ic, irc_user_t *iu, const char *msg ) +static void control_channel_kick(irc_channel_t *ic, irc_user_t *iu, const char *msg) { struct irc_control_channel *icc = ic->data; bee_user_t *bu = iu->bu; - - if( bu == NULL ) + + if (bu == NULL) { return; - - if( icc->type != IRC_CC_TYPE_GROUP ) - { - irc_send_num( ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name ); + } + + if (icc->type != IRC_CC_TYPE_GROUP) { + irc_send_num(ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name); return; } - - bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, - icc->group ? icc->group->name : NULL ); + + bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, + icc->group ? icc->group->name : NULL); } -static char *set_eval_by_account( set_t *set, char *value ); -static char *set_eval_fill_by( set_t *set, char *value ); -static char *set_eval_by_group( set_t *set, char *value ); -static char *set_eval_by_protocol( set_t *set, char *value ); -static char *set_eval_show_users( set_t *set, char *value ); +static char *set_eval_by_account(set_t *set, char *value); +static char *set_eval_fill_by(set_t *set, char *value); +static char *set_eval_by_group(set_t *set, char *value); +static char *set_eval_by_protocol(set_t *set, char *value); +static char *set_eval_show_users(set_t *set, char *value); -static gboolean control_channel_init( irc_channel_t *ic ) +static gboolean control_channel_init(irc_channel_t *ic) { struct irc_control_channel *icc; - - set_add( &ic->set, "account", NULL, set_eval_by_account, ic ); - set_add( &ic->set, "fill_by", "all", set_eval_fill_by, ic ); - set_add( &ic->set, "group", NULL, set_eval_by_group, ic ); - set_add( &ic->set, "protocol", NULL, set_eval_by_protocol, ic ); - + + set_add(&ic->set, "account", NULL, set_eval_by_account, ic); + set_add(&ic->set, "fill_by", "all", set_eval_fill_by, ic); + set_add(&ic->set, "group", NULL, set_eval_by_group, ic); + set_add(&ic->set, "protocol", NULL, set_eval_by_protocol, ic); + /* When changing the default, also change it below. */ - set_add( &ic->set, "show_users", "online+,special%,away", set_eval_show_users, ic ); - - ic->data = icc = g_new0( struct irc_control_channel, 1 ); + set_add(&ic->set, "show_users", "online+,special%,away", set_eval_show_users, ic); + + ic->data = icc = g_new0(struct irc_control_channel, 1); icc->type = IRC_CC_TYPE_DEFAULT; - + /* Have to run the evaluator to initialize icc->modes. */ - set_setstr( &ic->set, "show_users", "online+,special%,away" ); - + set_setstr(&ic->set, "show_users", "online+,special%,away"); + /* For scripts that care. */ - irc_channel_set_mode( ic, "+C" ); - + irc_channel_set_mode(ic, "+C"); + return TRUE; } -static gboolean control_channel_join( irc_channel_t *ic ) +static gboolean control_channel_join(irc_channel_t *ic) { - bee_irc_channel_update( ic->irc, ic, NULL ); - + bee_irc_channel_update(ic->irc, ic, NULL); + return TRUE; } -static char *set_eval_by_account( set_t *set, char *value ) +static char *set_eval_by_account(set_t *set, char *value) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; account_t *acc; - - if( !( acc = account_get( ic->irc->b, value ) ) ) + + if (!(acc = account_get(ic->irc->b, value))) { return SET_INVALID; - + } + icc->account = acc; - if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_ACCOUNT ) - bee_irc_channel_update( ic->irc, ic, NULL ); - - return g_strdup( acc->tag ); + if ((icc->type & IRC_CC_TYPE_MASK) == IRC_CC_TYPE_ACCOUNT) { + bee_irc_channel_update(ic->irc, ic, NULL); + } + + return g_strdup(acc->tag); } -static char *set_eval_fill_by( set_t *set, char *value ) +static char *set_eval_fill_by(set_t *set, char *value) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; char *s; - - icc->type &= ~( IRC_CC_TYPE_MASK | IRC_CC_TYPE_INVERT ); - + + icc->type &= ~(IRC_CC_TYPE_MASK | IRC_CC_TYPE_INVERT); + s = value; - if( s[0] == '!' ) - { + if (s[0] == '!') { icc->type |= IRC_CC_TYPE_INVERT; - s ++; + s++; } - - if( strcmp( s, "all" ) == 0 ) + + if (strcmp(s, "all") == 0) { icc->type |= IRC_CC_TYPE_DEFAULT; - else if( strcmp( s, "rest" ) == 0 ) + } else if (strcmp(s, "rest") == 0) { icc->type |= IRC_CC_TYPE_REST; - else if( strcmp( s, "group" ) == 0 ) + } else if (strcmp(s, "group") == 0) { icc->type |= IRC_CC_TYPE_GROUP; - else if( strcmp( s, "account" ) == 0 ) + } else if (strcmp(s, "account") == 0) { icc->type |= IRC_CC_TYPE_ACCOUNT; - else if( strcmp( s, "protocol" ) == 0 ) + } else if (strcmp(s, "protocol") == 0) { icc->type |= IRC_CC_TYPE_PROTOCOL; - else + } else { return SET_INVALID; - - bee_irc_channel_update( ic->irc, ic, NULL ); + } + + bee_irc_channel_update(ic->irc, ic, NULL); return value; } -static char *set_eval_by_group( set_t *set, char *value ) +static char *set_eval_by_group(set_t *set, char *value) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; - - icc->group = bee_group_by_name( ic->irc->b, value, TRUE ); - if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_GROUP ) - bee_irc_channel_update( ic->irc, ic, NULL ); - - return g_strdup( icc->group->name ); + + icc->group = bee_group_by_name(ic->irc->b, value, TRUE); + if ((icc->type & IRC_CC_TYPE_MASK) == IRC_CC_TYPE_GROUP) { + bee_irc_channel_update(ic->irc, ic, NULL); + } + + return g_strdup(icc->group->name); } -static char *set_eval_by_protocol( set_t *set, char *value ) +static char *set_eval_by_protocol(set_t *set, char *value) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; struct prpl *prpl; - - if( !( prpl = find_protocol( value ) ) ) + + if (!(prpl = find_protocol(value))) { return SET_INVALID; - + } + icc->protocol = prpl; - if( ( icc->type & IRC_CC_TYPE_MASK ) == IRC_CC_TYPE_PROTOCOL ) - bee_irc_channel_update( ic->irc, ic, NULL ); - + if ((icc->type & IRC_CC_TYPE_MASK) == IRC_CC_TYPE_PROTOCOL) { + bee_irc_channel_update(ic->irc, ic, NULL); + } + return value; } -static char *set_eval_show_users( set_t *set, char *value ) +static char *set_eval_show_users(set_t *set, char *value) { struct irc_channel *ic = set->data; struct irc_control_channel *icc = ic->data; - char **parts = g_strsplit( value, ",", 0 ), **part; + char **parts = g_strsplit(value, ",", 0), **part; char modes[5]; - - memset( modes, 0, 5 ); - for( part = parts; *part; part ++ ) - { + + memset(modes, 0, 5); + for (part = parts; *part; part++) { char last, modechar = IRC_CHANNEL_USER_NONE; - - if( **part == '\0' ) + + if (**part == '\0') { goto fail; - - last = (*part)[strlen(*part+1)]; - if( last == '+' ) + } + + last = (*part)[strlen(*part + 1)]; + if (last == '+') { modechar = IRC_CHANNEL_USER_VOICE; - else if( last == '%' ) + } else if (last == '%') { modechar = IRC_CHANNEL_USER_HALFOP; - else if( last == '@' ) + } else if (last == '@') { modechar = IRC_CHANNEL_USER_OP; - - if( strncmp( *part, "offline", 7 ) == 0 ) + } + + if (strncmp(*part, "offline", 7) == 0) { modes[0] = modechar; - else if( strncmp( *part, "away", 4 ) == 0 ) + } else if (strncmp(*part, "away", 4) == 0) { modes[1] = modechar; - else if( strncmp( *part, "special", 7 ) == 0 ) + } else if (strncmp(*part, "special", 7) == 0) { modes[2] = modechar; - else if( strncmp( *part, "online", 6 ) == 0 ) + } else if (strncmp(*part, "online", 6) == 0) { modes[3] = modechar; - else + } else { goto fail; + } } - memcpy( icc->modes, modes, 5 ); - bee_irc_channel_update( ic->irc, ic, NULL ); - - g_strfreev( parts ); + memcpy(icc->modes, modes, 5); + bee_irc_channel_update(ic->irc, ic, NULL); + + g_strfreev(parts); return value; - + fail: - g_strfreev( parts ); - return SET_INVALID; + g_strfreev(parts); + return SET_INVALID; } /* Figure out if a channel is supposed to have the user, assuming s/he is online or otherwise also selected by the show_users setting. Only works for control channels, but does *not* check if this channel is of that type. Beware! */ -gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu ) +gboolean irc_channel_wants_user(irc_channel_t *ic, irc_user_t *iu) { struct irc_control_channel *icc = ic->data; gboolean ret = FALSE; - - if( iu->bu == NULL ) + + if (iu->bu == NULL) { return FALSE; - - switch( icc->type & IRC_CC_TYPE_MASK ) - { + } + + switch (icc->type & IRC_CC_TYPE_MASK) { case IRC_CC_TYPE_GROUP: ret = iu->bu->group == icc->group; break; @@ -829,29 +860,30 @@ gboolean irc_channel_wants_user( irc_channel_t *ic, irc_user_t *iu ) ret = TRUE; break; } - - if( icc->type & IRC_CC_TYPE_INVERT ) + + if (icc->type & IRC_CC_TYPE_INVERT) { ret = !ret; - + } + return ret; } -static gboolean control_channel_free( irc_channel_t *ic ) +static gboolean control_channel_free(irc_channel_t *ic) { struct irc_control_channel *icc = ic->data; - - set_del( &ic->set, "account" ); - set_del( &ic->set, "fill_by" ); - set_del( &ic->set, "group" ); - set_del( &ic->set, "protocol" ); - set_del( &ic->set, "show_users" ); - - g_free( icc ); + + set_del(&ic->set, "account"); + set_del(&ic->set, "fill_by"); + set_del(&ic->set, "group"); + set_del(&ic->set, "protocol"); + set_del(&ic->set, "show_users"); + + g_free(icc); ic->data = NULL; - + /* For scripts that care. */ - irc_channel_set_mode( ic, "-C" ); - + irc_channel_set_mode(ic, "-C"); + return TRUE; } @@ -862,7 +894,7 @@ static const struct irc_channel_funcs control_channel_funcs = { NULL, control_channel_invite, control_channel_kick, - + control_channel_init, control_channel_free, }; diff --git a/irc_commands.c b/irc_commands.c index f438193c..98579d99 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -28,105 +28,93 @@ #include "help.h" #include "ipc.h" -static void irc_cmd_pass( irc_t *irc, char **cmd ) +static void irc_cmd_pass(irc_t *irc, char **cmd) { - if( irc->status & USTATUS_LOGGED_IN ) - { + if (irc->status & USTATUS_LOGGED_IN) { char *send_cmd[] = { "identify", cmd[1], NULL }; - + /* We're already logged in, this client seems to send the PASS command last. (Possibly it won't send it at all if it turns out we don't require it, which will break this feature.) Try to identify using the given password. */ - root_command( irc, send_cmd ); + root_command(irc, send_cmd); return; } /* Handling in pre-logged-in state, first see if this server is password-protected: */ - else if( global.conf->auth_pass && - ( strncmp( global.conf->auth_pass, "md5:", 4 ) == 0 ? - md5_verify_password( cmd[1], global.conf->auth_pass + 4 ) == 0 : - strcmp( cmd[1], global.conf->auth_pass ) == 0 ) ) - { + else if (global.conf->auth_pass && + (strncmp(global.conf->auth_pass, "md5:", 4) == 0 ? + md5_verify_password(cmd[1], global.conf->auth_pass + 4) == 0 : + strcmp(cmd[1], global.conf->auth_pass) == 0)) { irc->status |= USTATUS_AUTHORIZED; - irc_check_login( irc ); - } - else if( global.conf->auth_pass ) - { - irc_send_num( irc, 464, ":Incorrect password" ); - } - else - { + irc_check_login(irc); + } else if (global.conf->auth_pass) { + irc_send_num(irc, 464, ":Incorrect password"); + } else { /* Remember the password and try to identify after USER/NICK. */ - irc_setpass( irc, cmd[1] ); - irc_check_login( irc ); + irc_setpass(irc, cmd[1]); + irc_check_login(irc); } } -static void irc_cmd_user( irc_t *irc, char **cmd ) +static void irc_cmd_user(irc_t *irc, char **cmd) { - irc->user->user = g_strdup( cmd[1] ); - irc->user->fullname = g_strdup( cmd[4] ); - - irc_check_login( irc ); + irc->user->user = g_strdup(cmd[1]); + irc->user->fullname = g_strdup(cmd[4]); + + irc_check_login(irc); } -static void irc_cmd_nick( irc_t *irc, char **cmd ) +static void irc_cmd_nick(irc_t *irc, char **cmd) { irc_user_t *iu; - - if( ( iu = irc_user_by_name( irc, cmd[1] ) ) && iu != irc->user ) - { - irc_send_num( irc, 433, "%s :This nick is already in use", cmd[1] ); - } - else if( !nick_ok( NULL, cmd[1] ) ) - { + + if ((iu = irc_user_by_name(irc, cmd[1])) && iu != irc->user) { + irc_send_num(irc, 433, "%s :This nick is already in use", cmd[1]); + } else if (!nick_ok(NULL, cmd[1])) { /* [SH] Invalid characters. */ - irc_send_num( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); - } - else if( irc->status & USTATUS_LOGGED_IN ) - { + irc_send_num(irc, 432, "%s :This nick contains invalid characters", cmd[1]); + } else if (irc->status & USTATUS_LOGGED_IN) { /* WATCH OUT: iu from the first if reused here to check if the new nickname is the same (other than case, possibly). If it is, no need to reset identify-status. */ - if( ( irc->status & USTATUS_IDENTIFIED ) && iu != irc->user ) - { - irc_setpass( irc, NULL ); + if ((irc->status & USTATUS_IDENTIFIED) && iu != irc->user) { + irc_setpass(irc, NULL); irc->status &= ~USTATUS_IDENTIFIED; - irc_umode_set( irc, "-R", 1 ); - irc_rootmsg( irc, "Changing nicks resets your identify status. " - "Re-identify or register a new account if you want " - "your configuration to be saved. See \x02help " - "nick_changes\x02." ); + irc_umode_set(irc, "-R", 1); + irc_rootmsg(irc, "Changing nicks resets your identify status. " + "Re-identify or register a new account if you want " + "your configuration to be saved. See \x02help " + "nick_changes\x02."); } - - if( strcmp( cmd[1], irc->user->nick ) != 0 ) - irc_user_set_nick( irc->user, cmd[1] ); - } - else - { - g_free( irc->user->nick ); - irc->user->nick = g_strdup( cmd[1] ); - - irc_check_login( irc ); + + if (strcmp(cmd[1], irc->user->nick) != 0) { + irc_user_set_nick(irc->user, cmd[1]); + } + } else { + g_free(irc->user->nick); + irc->user->nick = g_strdup(cmd[1]); + + irc_check_login(irc); } } -static void irc_cmd_quit( irc_t *irc, char **cmd ) +static void irc_cmd_quit(irc_t *irc, char **cmd) { - if( cmd[1] && *cmd[1] ) - irc_abort( irc, 0, "Quit: %s", cmd[1] ); - else - irc_abort( irc, 0, "Leaving..." ); + if (cmd[1] && *cmd[1]) { + irc_abort(irc, 0, "Quit: %s", cmd[1]); + } else { + irc_abort(irc, 0, "Leaving..."); + } } -static void irc_cmd_ping( irc_t *irc, char **cmd ) +static void irc_cmd_ping(irc_t *irc, char **cmd) { - irc_write( irc, ":%s PONG %s :%s", irc->root->host, - irc->root->host, cmd[1]?cmd[1]:irc->root->host ); + irc_write(irc, ":%s PONG %s :%s", irc->root->host, + irc->root->host, cmd[1] ? cmd[1] : irc->root->host); } -static void irc_cmd_pong( irc_t *irc, char **cmd ) +static void irc_cmd_pong(irc_t *irc, char **cmd) { /* We could check the value we get back from the user, but in fact we don't care, we're just happy s/he's still alive. */ @@ -134,57 +122,46 @@ static void irc_cmd_pong( irc_t *irc, char **cmd ) irc->pinging = 0; } -static void irc_cmd_join( irc_t *irc, char **cmd ) +static void irc_cmd_join(irc_t *irc, char **cmd) { char *comma, *s = cmd[1]; - - while( s ) - { + + while (s) { irc_channel_t *ic; - - if( ( comma = strchr( s, ',' ) ) ) + + if ((comma = strchr(s, ','))) { *comma = '\0'; - - if( ( ic = irc_channel_by_name( irc, s ) ) == NULL && - ( ic = irc_channel_new( irc, s ) ) ) - { - if( strcmp( set_getstr( &ic->set, "type" ), "control" ) != 0 ) - { + } + + if ((ic = irc_channel_by_name(irc, s)) == NULL && + (ic = irc_channel_new(irc, s))) { + if (strcmp(set_getstr(&ic->set, "type"), "control") != 0) { /* Autoconfiguration is for control channels only ATM. */ - } - else if( bee_group_by_name( ic->irc->b, ic->name + 1, FALSE ) ) - { - set_setstr( &ic->set, "group", ic->name + 1 ); - set_setstr( &ic->set, "fill_by", "group" ); - } - else if( set_setstr( &ic->set, "protocol", ic->name + 1 ) ) - { - set_setstr( &ic->set, "fill_by", "protocol" ); - } - else if( set_setstr( &ic->set, "account", ic->name + 1 ) ) - { - set_setstr( &ic->set, "fill_by", "account" ); - } - else - { + } else if (bee_group_by_name(ic->irc->b, ic->name + 1, FALSE)) { + set_setstr(&ic->set, "group", ic->name + 1); + set_setstr(&ic->set, "fill_by", "group"); + } else if (set_setstr(&ic->set, "protocol", ic->name + 1)) { + set_setstr(&ic->set, "fill_by", "protocol"); + } else if (set_setstr(&ic->set, "account", ic->name + 1)) { + set_setstr(&ic->set, "fill_by", "account"); + } else { /* The set commands above will run this already, but if we didn't hit any, we have to fill the channel with the default population. */ - bee_irc_channel_update( ic->irc, ic, NULL ); + bee_irc_channel_update(ic->irc, ic, NULL); } - } - else if( ic == NULL ) - { - irc_send_num( irc, 479, "%s :Invalid channel name", s ); + } else if (ic == NULL) { + irc_send_num(irc, 479, "%s :Invalid channel name", s); goto next; } - - if( ic->flags & IRC_CHANNEL_JOINED ) + + if (ic->flags & IRC_CHANNEL_JOINED) { /* Dude, you're already there... RFC doesn't have any reply for that though? */ goto next; - - if( ic->f->join && !ic->f->join( ic ) ) + } + + if (ic->f->join && !ic->f->join(ic)) { /* The story is: FALSE either means the handler showed an error message, or is doing some work before the join should be confirmed. (In the @@ -192,555 +169,518 @@ static void irc_cmd_join( irc_t *irc, char **cmd ) confirmation.) TRUE means all's good, let the user join the channel right away. */ goto next; - - irc_channel_add_user( ic, irc->user ); - + } + + irc_channel_add_user(ic, irc->user); + next: - if( comma ) - { + if (comma) { s = comma + 1; *comma = ','; - } - else + } else { break; + } } } -static void irc_cmd_names( irc_t *irc, char **cmd ) +static void irc_cmd_names(irc_t *irc, char **cmd) { irc_channel_t *ic; - - if( cmd[1] && ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) - irc_send_names( ic ); + + if (cmd[1] && (ic = irc_channel_by_name(irc, cmd[1]))) { + irc_send_names(ic); + } /* With no args, we should show /names of all chans. Make the code below work well if necessary. else { - GSList *l; - - for( l = irc->channels; l; l = l->next ) - irc_send_names( l->data ); + GSList *l; + + for( l = irc->channels; l; l = l->next ) + irc_send_names( l->data ); } */ } -static void irc_cmd_part( irc_t *irc, char **cmd ) +static void irc_cmd_part(irc_t *irc, char **cmd) { irc_channel_t *ic; - - if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) - { - irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); - } - else if( irc_channel_del_user( ic, irc->user, IRC_CDU_PART, cmd[2] ) ) - { - if( ic->f->part ) - ic->f->part( ic, NULL ); - } - else - { - irc_send_num( irc, 442, "%s :You're not on that channel", cmd[1] ); + + if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { + irc_send_num(irc, 403, "%s :No such channel", cmd[1]); + } else if (irc_channel_del_user(ic, irc->user, IRC_CDU_PART, cmd[2])) { + if (ic->f->part) { + ic->f->part(ic, NULL); + } + } else { + irc_send_num(irc, 442, "%s :You're not on that channel", cmd[1]); } } -static void irc_cmd_whois( irc_t *irc, char **cmd ) +static void irc_cmd_whois(irc_t *irc, char **cmd) { char *nick = cmd[1]; - irc_user_t *iu = irc_user_by_name( irc, nick ); - - if( iu ) - irc_send_whois( iu ); - else - irc_send_num( irc, 401, "%s :Nick does not exist", nick ); + irc_user_t *iu = irc_user_by_name(irc, nick); + + if (iu) { + irc_send_whois(iu); + } else { + irc_send_num(irc, 401, "%s :Nick does not exist", nick); + } } -static void irc_cmd_whowas( irc_t *irc, char **cmd ) +static void irc_cmd_whowas(irc_t *irc, char **cmd) { /* For some reason irssi tries a whowas when whois fails. We can ignore this, but then the user never gets a "user not found" message from irssi which is a bit annoying. So just respond with not-found and irssi users will get better error messages */ - - irc_send_num( irc, 406, "%s :Nick does not exist", cmd[1] ); - irc_send_num( irc, 369, "%s :End of WHOWAS", cmd[1] ); + + irc_send_num(irc, 406, "%s :Nick does not exist", cmd[1]); + irc_send_num(irc, 369, "%s :End of WHOWAS", cmd[1]); } -static void irc_cmd_motd( irc_t *irc, char **cmd ) +static void irc_cmd_motd(irc_t *irc, char **cmd) { - irc_send_motd( irc ); + irc_send_motd(irc); } -static void irc_cmd_mode( irc_t *irc, char **cmd ) +static void irc_cmd_mode(irc_t *irc, char **cmd) { - if( irc_channel_name_ok( cmd[1] ) ) - { + if (irc_channel_name_ok(cmd[1])) { irc_channel_t *ic; - - if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) - irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); - else if( cmd[2] ) - { - if( *cmd[2] == '+' || *cmd[2] == '-' ) - irc_send_num( irc, 477, "%s :Can't change channel modes", cmd[1] ); - else if( *cmd[2] == 'b' ) - irc_send_num( irc, 368, "%s :No bans possible", cmd[1] ); + + if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { + irc_send_num(irc, 403, "%s :No such channel", cmd[1]); + } else if (cmd[2]) { + if (*cmd[2] == '+' || *cmd[2] == '-') { + irc_send_num(irc, 477, "%s :Can't change channel modes", cmd[1]); + } else if (*cmd[2] == 'b') { + irc_send_num(irc, 368, "%s :No bans possible", cmd[1]); + } + } else { + irc_send_num(irc, 324, "%s +%s", cmd[1], ic->mode); } - else - irc_send_num( irc, 324, "%s +%s", cmd[1], ic->mode ); - } - else - { - if( nick_cmp( NULL, cmd[1], irc->user->nick ) == 0 ) - { - if( cmd[2] ) - irc_umode_set( irc, cmd[2], 0 ); - else - irc_send_num( irc, 221, "+%s", irc->umode ); + } else { + if (nick_cmp(NULL, cmd[1], irc->user->nick) == 0) { + if (cmd[2]) { + irc_umode_set(irc, cmd[2], 0); + } else { + irc_send_num(irc, 221, "+%s", irc->umode); + } + } else { + irc_send_num(irc, 502, ":Don't touch their modes"); } - else - irc_send_num( irc, 502, ":Don't touch their modes" ); } } -static void irc_cmd_who( irc_t *irc, char **cmd ) +static void irc_cmd_who(irc_t *irc, char **cmd) { char *channel = cmd[1]; irc_channel_t *ic; irc_user_t *iu; - - if( !channel || *channel == '0' || *channel == '*' || !*channel ) - irc_send_who( irc, irc->users, "**" ); - else if( ( ic = irc_channel_by_name( irc, channel ) ) ) - irc_send_who( irc, ic->users, channel ); - else if( ( iu = irc_user_by_name( irc, channel ) ) ) - { + + if (!channel || *channel == '0' || *channel == '*' || !*channel) { + irc_send_who(irc, irc->users, "**"); + } else if ((ic = irc_channel_by_name(irc, channel))) { + irc_send_who(irc, ic->users, channel); + } else if ((iu = irc_user_by_name(irc, channel))) { /* Tiny hack! */ - GSList *l = g_slist_append( NULL, iu ); - irc_send_who( irc, l, channel ); - g_slist_free( l ); + GSList *l = g_slist_append(NULL, iu); + irc_send_who(irc, l, channel); + g_slist_free(l); + } else { + irc_send_num(irc, 403, "%s :No such channel", channel); } - else - irc_send_num( irc, 403, "%s :No such channel", channel ); } -static void irc_cmd_privmsg( irc_t *irc, char **cmd ) +static void irc_cmd_privmsg(irc_t *irc, char **cmd) { irc_channel_t *ic; irc_user_t *iu; - - if( !cmd[2] ) - { - irc_send_num( irc, 412, ":No text to send" ); + + if (!cmd[2]) { + irc_send_num(irc, 412, ":No text to send"); return; } - + /* Don't treat CTCP actions as real CTCPs, just convert them right now. */ - if( g_strncasecmp( cmd[2], "\001ACTION", 7 ) == 0 ) - { + if (g_strncasecmp(cmd[2], "\001ACTION", 7) == 0) { cmd[2] += 4; - memcpy( cmd[2], "/me", 3 ); - if( cmd[2][strlen(cmd[2])-1] == '\001' ) - cmd[2][strlen(cmd[2])-1] = '\0'; + memcpy(cmd[2], "/me", 3); + if (cmd[2][strlen(cmd[2]) - 1] == '\001') { + cmd[2][strlen(cmd[2]) - 1] = '\0'; + } } - - if( irc_channel_name_ok( cmd[1] ) && - ( ic = irc_channel_by_name( irc, cmd[1] ) ) ) - { - if( cmd[2][0] == '\001' ) - { + + if (irc_channel_name_ok(cmd[1]) && + (ic = irc_channel_by_name(irc, cmd[1]))) { + if (cmd[2][0] == '\001') { /* CTCPs to channels? Nah. Maybe later. */ + } else if (ic->f->privmsg) { + ic->f->privmsg(ic, cmd[2]); } - else if( ic->f->privmsg ) - ic->f->privmsg( ic, cmd[2] ); - } - else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) - { - if( cmd[2][0] == '\001' ) - { + } else if ((iu = irc_user_by_name(irc, cmd[1]))) { + if (cmd[2][0] == '\001') { char **ctcp; - - if( iu->f->ctcp == NULL ) + + if (iu->f->ctcp == NULL) { return; - if( cmd[2][strlen(cmd[2])-1] == '\001' ) - cmd[2][strlen(cmd[2])-1] = '\0'; - - ctcp = split_command_parts( cmd[2] + 1, 0 ); - iu->f->ctcp( iu, ctcp ); - } - else if( iu->f->privmsg ) - { + } + if (cmd[2][strlen(cmd[2]) - 1] == '\001') { + cmd[2][strlen(cmd[2]) - 1] = '\0'; + } + + ctcp = split_command_parts(cmd[2] + 1, 0); + iu->f->ctcp(iu, ctcp); + } else if (iu->f->privmsg) { iu->last_channel = NULL; - iu->f->privmsg( iu, cmd[2] ); + iu->f->privmsg(iu, cmd[2]); } - } - else - { - irc_send_num( irc, 401, "%s :No such nick/channel", cmd[1] ); + } else { + irc_send_num(irc, 401, "%s :No such nick/channel", cmd[1]); } } -static void irc_cmd_notice( irc_t *irc, char **cmd ) +static void irc_cmd_notice(irc_t *irc, char **cmd) { irc_user_t *iu; - - if( !cmd[2] ) - { - irc_send_num( irc, 412, ":No text to send" ); + + if (!cmd[2]) { + irc_send_num(irc, 412, ":No text to send"); return; } - + /* At least for now just echo. IIRC some IRC clients use self-notices for lag checks, so try to support that. */ - if( nick_cmp( NULL, cmd[1], irc->user->nick ) == 0 ) - irc_send_msg( irc->user, "NOTICE", irc->user->nick, cmd[2], NULL ); - else if( ( iu = irc_user_by_name( irc, cmd[1] ) ) ) - iu->f->privmsg( iu, cmd[2] ); + if (nick_cmp(NULL, cmd[1], irc->user->nick) == 0) { + irc_send_msg(irc->user, "NOTICE", irc->user->nick, cmd[2], NULL); + } else if ((iu = irc_user_by_name(irc, cmd[1]))) { + iu->f->privmsg(iu, cmd[2]); + } } -static void irc_cmd_nickserv( irc_t *irc, char **cmd ) +static void irc_cmd_nickserv(irc_t *irc, char **cmd) { /* [SH] This aliases the NickServ command to PRIVMSG root */ /* [TV] This aliases the NS command to PRIVMSG root as well */ - root_command( irc, cmd + 1 ); + root_command(irc, cmd + 1); } -static void irc_cmd_oper_hack( irc_t *irc, char **cmd ); +static void irc_cmd_oper_hack(irc_t *irc, char **cmd); -static void irc_cmd_oper( irc_t *irc, char **cmd ) +static void irc_cmd_oper(irc_t *irc, char **cmd) { /* Very non-standard evil but useful/secure hack, see below. */ - if( irc->status & OPER_HACK_ANY ) - return irc_cmd_oper_hack( irc, cmd ); - - if( global.conf->oper_pass && - ( strncmp( global.conf->oper_pass, "md5:", 4 ) == 0 ? - md5_verify_password( cmd[2], global.conf->oper_pass + 4 ) == 0 : - strcmp( cmd[2], global.conf->oper_pass ) == 0 ) ) - { - irc_umode_set( irc, "+o", 1 ); - irc_send_num( irc, 381, ":Password accepted" ); + if (irc->status & OPER_HACK_ANY) { + return irc_cmd_oper_hack(irc, cmd); } - else - { - irc_send_num( irc, 491, ":Incorrect password" ); + + if (global.conf->oper_pass && + (strncmp(global.conf->oper_pass, "md5:", 4) == 0 ? + md5_verify_password(cmd[2], global.conf->oper_pass + 4) == 0 : + strcmp(cmd[2], global.conf->oper_pass) == 0)) { + irc_umode_set(irc, "+o", 1); + irc_send_num(irc, 381, ":Password accepted"); + } else { + irc_send_num(irc, 491, ":Incorrect password"); } } -static void irc_cmd_oper_hack( irc_t *irc, char **cmd ) +static void irc_cmd_oper_hack(irc_t *irc, char **cmd) { - char *password = g_strjoinv( " ", cmd + 2 ); - + char *password = g_strjoinv(" ", cmd + 2); + /* /OPER can now also be used to enter IM/identify passwords without echoing. It's a hack but the extra password security is worth it. */ - if( irc->status & OPER_HACK_ACCOUNT_PASSWORD ) - { + if (irc->status & OPER_HACK_ACCOUNT_PASSWORD) { account_t *a; - - for( a = irc->b->accounts; a; a = a->next ) - if( strcmp( a->pass, PASSWORD_PENDING ) == 0 ) - { - set_setstr( &a->set, "password", password ); - irc_rootmsg( irc, "Password added to IM account " - "%s", a->tag ); + + for (a = irc->b->accounts; a; a = a->next) { + if (strcmp(a->pass, PASSWORD_PENDING) == 0) { + set_setstr(&a->set, "password", password); + irc_rootmsg(irc, "Password added to IM account " + "%s", a->tag); /* The IRC client may expect this. 491 suggests the OPER password was wrong, so the client won't expect a +o. It may however repeat the password prompt. We'll see. */ - irc_send_num( irc, 491, ":Password added to IM account " - "%s", a->tag ); + irc_send_num(irc, 491, ":Password added to IM account " + "%s", a->tag); } - } - else if( irc->status & OPER_HACK_IDENTIFY ) - { + } + } else if (irc->status & OPER_HACK_IDENTIFY) { char *send_cmd[] = { "identify", password, NULL, NULL }; irc->status &= ~OPER_HACK_IDENTIFY; - if( irc->status & OPER_HACK_IDENTIFY_NOLOAD ) - { + if (irc->status & OPER_HACK_IDENTIFY_NOLOAD) { send_cmd[1] = "-noload"; send_cmd[2] = password; - } - else if( irc->status & OPER_HACK_IDENTIFY_FORCE ) - { + } else if (irc->status & OPER_HACK_IDENTIFY_FORCE) { send_cmd[1] = "-force"; send_cmd[2] = password; } - irc_send_num( irc, 491, ":Trying to identify" ); - root_command( irc, send_cmd ); - } - else if( irc->status & OPER_HACK_REGISTER ) - { + irc_send_num(irc, 491, ":Trying to identify"); + root_command(irc, send_cmd); + } else if (irc->status & OPER_HACK_REGISTER) { char *send_cmd[] = { "register", password, NULL }; - irc_send_num( irc, 491, ":Trying to identify" ); - root_command( irc, send_cmd ); + irc_send_num(irc, 491, ":Trying to identify"); + root_command(irc, send_cmd); } - + irc->status &= ~OPER_HACK_ANY; - g_free( password ); + g_free(password); } -static void irc_cmd_invite( irc_t *irc, char **cmd ) +static void irc_cmd_invite(irc_t *irc, char **cmd) { irc_channel_t *ic; irc_user_t *iu; - - if( ( iu = irc_user_by_name( irc, cmd[1] ) ) == NULL ) - { - irc_send_num( irc, 401, "%s :No such nick", cmd[1] ); + + if ((iu = irc_user_by_name(irc, cmd[1])) == NULL) { + irc_send_num(irc, 401, "%s :No such nick", cmd[1]); return; - } - else if( ( ic = irc_channel_by_name( irc, cmd[2] ) ) == NULL ) - { - irc_send_num( irc, 403, "%s :No such channel", cmd[2] ); + } else if ((ic = irc_channel_by_name(irc, cmd[2])) == NULL) { + irc_send_num(irc, 403, "%s :No such channel", cmd[2]); return; } - - if( !ic->f->invite ) - irc_send_num( irc, 482, "%s :Can't invite people here", cmd[2] ); - else if( ic->f->invite( ic, iu ) ) - irc_send_num( irc, 341, "%s %s", iu->nick, ic->name ); + + if (!ic->f->invite) { + irc_send_num(irc, 482, "%s :Can't invite people here", cmd[2]); + } else if (ic->f->invite(ic, iu)) { + irc_send_num(irc, 341, "%s %s", iu->nick, ic->name); + } } -static void irc_cmd_kick( irc_t *irc, char **cmd ) +static void irc_cmd_kick(irc_t *irc, char **cmd) { irc_channel_t *ic; irc_user_t *iu; - - if( ( iu = irc_user_by_name( irc, cmd[2] ) ) == NULL ) - { - irc_send_num( irc, 401, "%s :No such nick", cmd[2] ); + + if ((iu = irc_user_by_name(irc, cmd[2])) == NULL) { + irc_send_num(irc, 401, "%s :No such nick", cmd[2]); return; - } - else if( ( ic = irc_channel_by_name( irc, cmd[1] ) ) == NULL ) - { - irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); + } else if ((ic = irc_channel_by_name(irc, cmd[1])) == NULL) { + irc_send_num(irc, 403, "%s :No such channel", cmd[1]); return; - } - else if( !ic->f->kick ) - { - irc_send_num( irc, 482, "%s :Can't kick people here", cmd[1] ); + } else if (!ic->f->kick) { + irc_send_num(irc, 482, "%s :Can't kick people here", cmd[1]); return; } - - ic->f->kick( ic, iu, cmd[3] ? cmd[3] : NULL ); + + ic->f->kick(ic, iu, cmd[3] ? cmd[3] : NULL); } -static void irc_cmd_userhost( irc_t *irc, char **cmd ) +static void irc_cmd_userhost(irc_t *irc, char **cmd) { int i; - + /* [TV] Usable USERHOST-implementation according to - RFC1459. Without this, mIRC shows an error - while connecting, and the used way of rejecting - breaks standards. + RFC1459. Without this, mIRC shows an error + while connecting, and the used way of rejecting + breaks standards. */ - - for( i = 1; cmd[i]; i ++ ) - { - irc_user_t *iu = irc_user_by_name( irc, cmd[i] ); - - if( iu ) - irc_send_num( irc, 302, ":%s=%c%s@%s", iu->nick, - irc_user_get_away( iu ) ? '-' : '+', - iu->user, iu->host ); + + for (i = 1; cmd[i]; i++) { + irc_user_t *iu = irc_user_by_name(irc, cmd[i]); + + if (iu) { + irc_send_num(irc, 302, ":%s=%c%s@%s", iu->nick, + irc_user_get_away(iu) ? '-' : '+', + iu->user, iu->host); + } } } -static void irc_cmd_ison( irc_t *irc, char **cmd ) +static void irc_cmd_ison(irc_t *irc, char **cmd) { char buff[IRC_MAX_LINE]; int lenleft, i; - + buff[0] = '\0'; - + /* [SH] Leave room for : and \0 */ lenleft = IRC_MAX_LINE - 2; - - for( i = 1; cmd[i]; i ++ ) - { + + for (i = 1; cmd[i]; i++) { char *this, *next; - + this = cmd[i]; - while( *this ) - { + while (*this) { irc_user_t *iu; - - if( ( next = strchr( this, ' ' ) ) ) + + if ((next = strchr(this, ' '))) { *next = 0; - - if( ( iu = irc_user_by_name( irc, this ) ) && - iu->bu && iu->bu->flags & BEE_USER_ONLINE ) - { - lenleft -= strlen( iu->nick ) + 1; - - if( lenleft < 0 ) + } + + if ((iu = irc_user_by_name(irc, this)) && + iu->bu && iu->bu->flags & BEE_USER_ONLINE) { + lenleft -= strlen(iu->nick) + 1; + + if (lenleft < 0) { break; - - strcat( buff, iu->nick ); - strcat( buff, " " ); + } + + strcat(buff, iu->nick); + strcat(buff, " "); } - - if( next ) - { + + if (next) { *next = ' '; this = next + 1; - } - else - { + } else { break; - } + } } - + /* *sigh* */ - if( lenleft < 0 ) + if (lenleft < 0) { break; + } + } + + if (strlen(buff) > 0) { + buff[strlen(buff) - 1] = '\0'; } - - if( strlen( buff ) > 0 ) - buff[strlen(buff)-1] = '\0'; - - irc_send_num( irc, 303, ":%s", buff ); + + irc_send_num(irc, 303, ":%s", buff); } -static void irc_cmd_watch( irc_t *irc, char **cmd ) +static void irc_cmd_watch(irc_t *irc, char **cmd) { int i; - + /* Obviously we could also mark a user structure as being watched, but what if the WATCH command is sent right after connecting? The user won't exist yet then... */ - for( i = 1; cmd[i]; i ++ ) - { + for (i = 1; cmd[i]; i++) { char *nick; irc_user_t *iu; - - if( !cmd[i][0] || !cmd[i][1] ) + + if (!cmd[i][0] || !cmd[i][1]) { break; - - nick = g_strdup( cmd[i] + 1 ); - nick_lc( irc, nick ); - - iu = irc_user_by_name( irc, nick ); - - if( cmd[i][0] == '+' ) - { - if( !g_hash_table_lookup( irc->watches, nick ) ) - g_hash_table_insert( irc->watches, nick, nick ); - - if( iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE ) - irc_send_num( irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, - iu->host, (int) time( NULL ), "is online" ); - else - irc_send_num( irc, 605, "%s %s %s %d :%s", nick, "*", "*", - (int) time( NULL ), "is offline" ); } - else if( cmd[i][0] == '-' ) - { + + nick = g_strdup(cmd[i] + 1); + nick_lc(irc, nick); + + iu = irc_user_by_name(irc, nick); + + if (cmd[i][0] == '+') { + if (!g_hash_table_lookup(irc->watches, nick)) { + g_hash_table_insert(irc->watches, nick, nick); + } + + if (iu && iu->bu && iu->bu->flags & BEE_USER_ONLINE) { + irc_send_num(irc, 604, "%s %s %s %d :%s", iu->nick, iu->user, + iu->host, (int) time(NULL), "is online"); + } else { + irc_send_num(irc, 605, "%s %s %s %d :%s", nick, "*", "*", + (int) time(NULL), "is offline"); + } + } else if (cmd[i][0] == '-') { gpointer okey, ovalue; - - if( g_hash_table_lookup_extended( irc->watches, nick, &okey, &ovalue ) ) - { - g_hash_table_remove( irc->watches, okey ); - g_free( okey ); - - irc_send_num( irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching" ); + + if (g_hash_table_lookup_extended(irc->watches, nick, &okey, &ovalue)) { + g_hash_table_remove(irc->watches, okey); + g_free(okey); + + irc_send_num(irc, 602, "%s %s %s %d :%s", nick, "*", "*", 0, "Stopped watching"); } } } } -static void irc_cmd_topic( irc_t *irc, char **cmd ) +static void irc_cmd_topic(irc_t *irc, char **cmd) { - irc_channel_t *ic = irc_channel_by_name( irc, cmd[1] ); + irc_channel_t *ic = irc_channel_by_name(irc, cmd[1]); const char *new = cmd[2]; - - if( ic == NULL ) - { - irc_send_num( irc, 403, "%s :No such channel", cmd[1] ); - } - else if( new ) - { - if( ic->f->topic == NULL ) - irc_send_num( irc, 482, "%s :Can't change this channel's topic", ic->name ); - else if( ic->f->topic( ic, new ) ) - irc_send_topic( ic, TRUE ); - } - else - { - irc_send_topic( ic, FALSE ); + + if (ic == NULL) { + irc_send_num(irc, 403, "%s :No such channel", cmd[1]); + } else if (new) { + if (ic->f->topic == NULL) { + irc_send_num(irc, 482, "%s :Can't change this channel's topic", ic->name); + } else if (ic->f->topic(ic, new)) { + irc_send_topic(ic, TRUE); + } + } else { + irc_send_topic(ic, FALSE); } } -static void irc_cmd_away( irc_t *irc, char **cmd ) +static void irc_cmd_away(irc_t *irc, char **cmd) { - if( cmd[1] && *cmd[1] ) - { - char away[strlen(cmd[1])+1]; + if (cmd[1] && *cmd[1]) { + char away[strlen(cmd[1]) + 1]; int i, j; - + /* Copy away string, but skip control chars. Mainly because Jabber really doesn't like them. */ - for( i = j = 0; cmd[1][i]; i ++ ) - if( (unsigned char) ( away[j] = cmd[1][i] ) >= ' ' ) - j ++; + for (i = j = 0; cmd[1][i]; i++) { + if ((unsigned char) (away[j] = cmd[1][i]) >= ' ') { + j++; + } + } away[j] = '\0'; - - irc_send_num( irc, 306, ":You're now away: %s", away ); - set_setstr( &irc->b->set, "away", away ); - } - else - { - irc_send_num( irc, 305, ":Welcome back" ); - set_setstr( &irc->b->set, "away", NULL ); + + irc_send_num(irc, 306, ":You're now away: %s", away); + set_setstr(&irc->b->set, "away", away); + } else { + irc_send_num(irc, 305, ":Welcome back"); + set_setstr(&irc->b->set, "away", NULL); } } -static void irc_cmd_list( irc_t *irc, char **cmd ) +static void irc_cmd_list(irc_t *irc, char **cmd) { GSList *l; - - for( l = irc->channels; l; l = l->next ) - { + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - irc_send_num( irc, 322, "%s %d :%s", - ic->name, g_slist_length( ic->users ), ic->topic ? : "" ); + + irc_send_num(irc, 322, "%s %d :%s", + ic->name, g_slist_length(ic->users), ic->topic ? : ""); } - irc_send_num( irc, 323, ":%s", "End of /LIST" ); + irc_send_num(irc, 323, ":%s", "End of /LIST"); } -static void irc_cmd_version( irc_t *irc, char **cmd ) +static void irc_cmd_version(irc_t *irc, char **cmd) { - irc_send_num( irc, 351, "%s-%s. %s :%s/%s ", - PACKAGE, BITLBEE_VERSION, irc->root->host, ARCH, CPU ); + irc_send_num(irc, 351, "%s-%s. %s :%s/%s ", + PACKAGE, BITLBEE_VERSION, irc->root->host, ARCH, CPU); } -static void irc_cmd_completions( irc_t *irc, char **cmd ) +static void irc_cmd_completions(irc_t *irc, char **cmd) { help_t *h; set_t *s; int i; - - irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK" ); - - for( i = 0; root_commands[i].command; i ++ ) - irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", root_commands[i].command ); - - for( h = global.help; h; h = h->next ) - irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title ); - - for( s = irc->b->set; s; s = s->next ) - irc_send_msg_f( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key ); - - irc_send_msg_raw( irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END" ); + + irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS OK"); + + for (i = 0; root_commands[i].command; i++) { + irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS %s", root_commands[i].command); + } + + for (h = global.help; h; h = h->next) { + irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS help %s", h->title); + } + + for (s = irc->b->set; s; s = s->next) { + irc_send_msg_f(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS set %s", s->key); + } + + irc_send_msg_raw(irc->root, "NOTICE", irc->user->nick, "COMPLETIONS END"); } -static void irc_cmd_rehash( irc_t *irc, char **cmd ) +static void irc_cmd_rehash(irc_t *irc, char **cmd) { - if( global.conf->runmode == RUNMODE_INETD ) - ipc_master_cmd_rehash( NULL, NULL ); - else - ipc_to_master( cmd ); - - irc_send_num( irc, 382, "%s :Rehashing", global.conf_file ); + if (global.conf->runmode == RUNMODE_INETD) { + ipc_master_cmd_rehash(NULL, NULL); + } else { + ipc_to_master(cmd); + } + + irc_send_num(irc, 382, "%s :Rehashing", global.conf_file); } static const command_t irc_commands[] = { @@ -783,51 +723,43 @@ static const command_t irc_commands[] = { { NULL } }; -void irc_exec( irc_t *irc, char *cmd[] ) -{ +void irc_exec(irc_t *irc, char *cmd[]) +{ int i, n_arg; - - if( !cmd[0] ) + + if (!cmd[0]) { return; - - for( i = 0; irc_commands[i].command; i++ ) - if( g_strcasecmp( irc_commands[i].command, cmd[0] ) == 0 ) - { + } + + for (i = 0; irc_commands[i].command; i++) { + if (g_strcasecmp(irc_commands[i].command, cmd[0]) == 0) { /* There should be no typo in the next line: */ - for( n_arg = 0; cmd[n_arg]; n_arg ++ ) + for (n_arg = 0; cmd[n_arg]; n_arg++) { ; - n_arg--; - - if( irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN ) - { - irc_send_num( irc, 462, ":Only allowed before logging in" ); - } - else if( irc_commands[i].flags & IRC_CMD_LOGGED_IN && !( irc->status & USTATUS_LOGGED_IN ) ) - { - irc_send_num( irc, 451, ":Register first" ); } - else if( irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr( irc->umode, 'o' ) ) - { - irc_send_num( irc, 481, ":Permission denied - You're not an IRC operator" ); - } - else if( n_arg < irc_commands[i].required_parameters ) - { - irc_send_num( irc, 461, "%s :Need more parameters", cmd[0] ); - } - else if( irc_commands[i].flags & IRC_CMD_TO_MASTER ) - { + n_arg--; + + if (irc_commands[i].flags & IRC_CMD_PRE_LOGIN && irc->status & USTATUS_LOGGED_IN) { + irc_send_num(irc, 462, ":Only allowed before logging in"); + } else if (irc_commands[i].flags & IRC_CMD_LOGGED_IN && !(irc->status & USTATUS_LOGGED_IN)) { + irc_send_num(irc, 451, ":Register first"); + } else if (irc_commands[i].flags & IRC_CMD_OPER_ONLY && !strchr(irc->umode, 'o')) { + irc_send_num(irc, 481, ":Permission denied - You're not an IRC operator"); + } else if (n_arg < irc_commands[i].required_parameters) { + irc_send_num(irc, 461, "%s :Need more parameters", cmd[0]); + } else if (irc_commands[i].flags & IRC_CMD_TO_MASTER) { /* IPC doesn't make sense in inetd mode, but the function will catch that. */ - ipc_to_master( cmd ); - } - else - { - irc_commands[i].execute( irc, cmd ); + ipc_to_master(cmd); + } else { + irc_commands[i].execute(irc, cmd); } - + return; } - - if( irc->status & USTATUS_LOGGED_IN ) - irc_send_num( irc, 421, "%s :Unknown command", cmd[0] ); + } + + if (irc->status & USTATUS_LOGGED_IN) { + irc_send_num(irc, 421, "%s :Unknown command", cmd[0]); + } } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -30,518 +30,501 @@ static const struct irc_user_funcs irc_user_im_funcs; -static void bee_irc_imc_connected( struct im_connection *ic ) +static void bee_irc_imc_connected(struct im_connection *ic) { - irc_t *irc = (irc_t*) ic->bee->ui_data; - - irc_channel_auto_joins( irc, ic->acc ); + irc_t *irc = (irc_t *) ic->bee->ui_data; + + irc_channel_auto_joins(irc, ic->acc); } -static void bee_irc_imc_disconnected( struct im_connection *ic ) +static void bee_irc_imc_disconnected(struct im_connection *ic) { /* Maybe try to send /QUITs here instead of later on. */ } -static gboolean bee_irc_user_new( bee_t *bee, bee_user_t *bu ) +static gboolean bee_irc_user_new(bee_t *bee, bee_user_t *bu) { irc_user_t *iu; - irc_t *irc = (irc_t*) bee->ui_data; - char nick[MAX_NICK_LENGTH+1], *s; - - memset( nick, 0, MAX_NICK_LENGTH + 1 ); - strcpy( nick, nick_get( bu ) ); - - bu->ui_data = iu = irc_user_new( irc, nick ); + irc_t *irc = (irc_t *) bee->ui_data; + char nick[MAX_NICK_LENGTH + 1], *s; + + memset(nick, 0, MAX_NICK_LENGTH + 1); + strcpy(nick, nick_get(bu)); + + bu->ui_data = iu = irc_user_new(irc, nick); iu->bu = bu; - - if( set_getbool( &irc->b->set, "private" ) ) + + if (set_getbool(&irc->b->set, "private")) { iu->last_channel = NULL; - else - iu->last_channel = irc_channel_with_user( irc, iu ); - - if( ( s = strchr( bu->handle, '@' ) ) ) - { - iu->host = g_strdup( s + 1 ); - iu->user = g_strndup( bu->handle, s - bu->handle ); - } - else - { - iu->user = g_strdup( bu->handle ); - if( bu->ic->acc->server ) - iu->host = g_strdup( bu->ic->acc->server ); - else - { + } else { + iu->last_channel = irc_channel_with_user(irc, iu); + } + + if ((s = strchr(bu->handle, '@'))) { + iu->host = g_strdup(s + 1); + iu->user = g_strndup(bu->handle, s - bu->handle); + } else { + iu->user = g_strdup(bu->handle); + if (bu->ic->acc->server) { + iu->host = g_strdup(bu->ic->acc->server); + } else { char *s; - for( s = bu->ic->acc->tag; g_ascii_isalnum( *s ); s ++ ); + for (s = bu->ic->acc->tag; g_ascii_isalnum(*s); s++) { + ; + } /* Only use the tag if we got to the end of the string. (So allow alphanumerics only. Hopefully not too restrictive.) */ - if( *s ) - iu->host = g_strdup( bu->ic->acc->prpl->name ); - else - iu->host = g_strdup( bu->ic->acc->tag ); + if (*s) { + iu->host = g_strdup(bu->ic->acc->prpl->name); + } else { + iu->host = g_strdup(bu->ic->acc->tag); + } } } - - while( ( s = strchr( iu->user, ' ' ) ) ) + + while ((s = strchr(iu->user, ' '))) { *s = '_'; - - if( bu->flags & BEE_USER_LOCAL ) - { - char *s = set_getstr( &bee->set, "handle_unknown" ); - - if( strcmp( s, "add_private" ) == 0 ) + } + + if (bu->flags & BEE_USER_LOCAL) { + char *s = set_getstr(&bee->set, "handle_unknown"); + + if (strcmp(s, "add_private") == 0) { iu->last_channel = NULL; - else if( strcmp( s, "add_channel" ) == 0 ) + } else if (strcmp(s, "add_channel") == 0) { iu->last_channel = irc->default_channel; + } } - + iu->f = &irc_user_im_funcs; - + return TRUE; } -static gboolean bee_irc_user_free( bee_t *bee, bee_user_t *bu ) +static gboolean bee_irc_user_free(bee_t *bee, bee_user_t *bu) { - return irc_user_free( bee->ui_data, (irc_user_t *) bu->ui_data ); + return irc_user_free(bee->ui_data, (irc_user_t *) bu->ui_data); } -static gboolean bee_irc_user_status( bee_t *bee, bee_user_t *bu, bee_user_t *old ) +static gboolean bee_irc_user_status(bee_t *bee, bee_user_t *bu, bee_user_t *old) { irc_t *irc = bee->ui_data; irc_user_t *iu = bu->ui_data; - + /* Do this outside the if below since away state can change without the online state changing. */ iu->flags &= ~IRC_USER_AWAY; - if( bu->flags & BEE_USER_AWAY || !( bu->flags & BEE_USER_ONLINE ) ) + if (bu->flags & BEE_USER_AWAY || !(bu->flags & BEE_USER_ONLINE)) { iu->flags |= IRC_USER_AWAY; - - if( ( bu->flags & BEE_USER_ONLINE ) != ( old->flags & BEE_USER_ONLINE ) ) - { - if( bu->flags & BEE_USER_ONLINE ) - { - if( g_hash_table_lookup( irc->watches, iu->key ) ) - irc_send_num( irc, 600, "%s %s %s %d :%s", iu->nick, iu->user, - iu->host, (int) time( NULL ), "logged online" ); - } - else - { - if( g_hash_table_lookup( irc->watches, iu->key ) ) - irc_send_num( irc, 601, "%s %s %s %d :%s", iu->nick, iu->user, - iu->host, (int) time( NULL ), "logged offline" ); - + } + + if ((bu->flags & BEE_USER_ONLINE) != (old->flags & BEE_USER_ONLINE)) { + if (bu->flags & BEE_USER_ONLINE) { + if (g_hash_table_lookup(irc->watches, iu->key)) { + irc_send_num(irc, 600, "%s %s %s %d :%s", iu->nick, iu->user, + iu->host, (int) time(NULL), "logged online"); + } + } else { + if (g_hash_table_lookup(irc->watches, iu->key)) { + irc_send_num(irc, 601, "%s %s %s %d :%s", iu->nick, iu->user, + iu->host, (int) time(NULL), "logged offline"); + } + /* Send a QUIT since those will also show up in any query windows the user may have, plus it's only one QUIT instead of possibly many (in case of multiple control chans). If there's a channel that shows offline people, a JOIN will follow. */ - if( set_getbool( &bee->set, "offline_user_quits" ) ) - irc_user_quit( iu, "Leaving..." ); + if (set_getbool(&bee->set, "offline_user_quits")) { + irc_user_quit(iu, "Leaving..."); + } } } - + /* Reset this one since the info may have changed. */ iu->away_reply_timeout = 0; - - bee_irc_channel_update( irc, NULL, iu ); - + + bee_irc_channel_update(irc, NULL, iu); + return TRUE; } -void bee_irc_channel_update( irc_t *irc, irc_channel_t *ic, irc_user_t *iu ) +void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu) { GSList *l; - - if( ic == NULL ) - { - for( l = irc->channels; l; l = l->next ) - { + + if (ic == NULL) { + for (l = irc->channels; l; l = l->next) { ic = l->data; /* TODO: Just add a type flag or so.. */ - if( ic->f == irc->default_channel->f && - ( ic->flags & IRC_CHANNEL_JOINED ) ) - bee_irc_channel_update( irc, ic, iu ); + if (ic->f == irc->default_channel->f && + (ic->flags & IRC_CHANNEL_JOINED)) { + bee_irc_channel_update(irc, ic, iu); + } } return; } - if( iu == NULL ) - { - for( l = irc->users; l; l = l->next ) - { + if (iu == NULL) { + for (l = irc->users; l; l = l->next) { iu = l->data; - if( iu->bu ) - bee_irc_channel_update( irc, ic, l->data ); + if (iu->bu) { + bee_irc_channel_update(irc, ic, l->data); + } } return; } - - if( !irc_channel_wants_user( ic, iu ) ) - { - irc_channel_del_user( ic, iu, IRC_CDU_PART, NULL ); - } - else - { + + if (!irc_channel_wants_user(ic, iu)) { + irc_channel_del_user(ic, iu, IRC_CDU_PART, NULL); + } else { struct irc_control_channel *icc = ic->data; int mode = 0; - - if( !( iu->bu->flags & BEE_USER_ONLINE ) ) + + if (!(iu->bu->flags & BEE_USER_ONLINE)) { mode = icc->modes[0]; - else if( iu->bu->flags & BEE_USER_AWAY ) + } else if (iu->bu->flags & BEE_USER_AWAY) { mode = icc->modes[1]; - else if( iu->bu->flags & BEE_USER_SPECIAL ) + } else if (iu->bu->flags & BEE_USER_SPECIAL) { mode = icc->modes[2]; - else + } else { mode = icc->modes[3]; - - if( !mode ) - irc_channel_del_user( ic, iu, IRC_CDU_PART, NULL ); - else - { - irc_channel_add_user( ic, iu ); - irc_channel_user_set_mode( ic, iu, mode ); + } + + if (!mode) { + irc_channel_del_user(ic, iu, IRC_CDU_PART, NULL); + } else { + irc_channel_add_user(ic, iu); + irc_channel_user_set_mode(ic, iu, mode); } } } -static gboolean bee_irc_user_msg( bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at ) +static gboolean bee_irc_user_msg(bee_t *bee, bee_user_t *bu, const char *msg_, time_t sent_at) { irc_t *irc = bee->ui_data; irc_user_t *iu = (irc_user_t *) bu->ui_data; const char *dst; char *prefix = NULL; char *wrapped, *ts = NULL; - char *msg = g_strdup( msg_ ); + char *msg = g_strdup(msg_); GSList *l; - - if( sent_at > 0 && set_getbool( &irc->b->set, "display_timestamps" ) ) - ts = irc_format_timestamp( irc, sent_at ); - - dst = irc_user_msgdest( iu ); - if( dst != irc->user->nick ) - { - /* if not messaging directly, call user by name */ - prefix = g_strdup_printf( "%s%s%s", irc->user->nick, set_getstr( &bee->set, "to_char" ), ts ? : "" ); + + if (sent_at > 0 && set_getbool(&irc->b->set, "display_timestamps")) { + ts = irc_format_timestamp(irc, sent_at); } - else - { + + dst = irc_user_msgdest(iu); + if (dst != irc->user->nick) { + /* if not messaging directly, call user by name */ + prefix = g_strdup_printf("%s%s%s", irc->user->nick, set_getstr(&bee->set, "to_char"), ts ? : ""); + } else { prefix = ts; ts = NULL; /* don't double-free */ } - - for( l = irc_plugins; l; l = l->next ) - { + + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->filter_msg_in ) - { - char *s = p->filter_msg_in( iu, msg, 0 ); - if( s ) - { - if( s != msg ) - g_free( msg ); + if (p->filter_msg_in) { + char *s = p->filter_msg_in(iu, msg, 0); + if (s) { + if (s != msg) { + g_free(msg); + } msg = s; - } - else - { + } else { /* Modules can swallow messages. */ return TRUE; } } } - - if( ( g_strcasecmp( set_getstr( &bee->set, "strip_html" ), "always" ) == 0 ) || - ( ( bu->ic->flags & OPT_DOES_HTML ) && set_getbool( &bee->set, "strip_html" ) ) ) - { - char *s = g_strdup( msg ); - strip_html( s ); - g_free( msg ); + + if ((g_strcasecmp(set_getstr(&bee->set, "strip_html"), "always") == 0) || + ((bu->ic->flags & OPT_DOES_HTML) && set_getbool(&bee->set, "strip_html"))) { + char *s = g_strdup(msg); + strip_html(s); + g_free(msg); msg = s; } - - wrapped = word_wrap( msg, 425 ); - irc_send_msg( iu, "PRIVMSG", dst, wrapped, prefix ); - - g_free( wrapped ); - g_free( prefix ); - g_free( msg ); - g_free( ts ); - + + wrapped = word_wrap(msg, 425); + irc_send_msg(iu, "PRIVMSG", dst, wrapped, prefix); + + g_free(wrapped); + g_free(prefix); + g_free(msg); + g_free(ts); + return TRUE; } -static gboolean bee_irc_user_typing( bee_t *bee, bee_user_t *bu, uint32_t flags ) +static gboolean bee_irc_user_typing(bee_t *bee, bee_user_t *bu, uint32_t flags) { irc_t *irc = (irc_t *) bee->ui_data; - - if( set_getbool( &bee->set, "typing_notice" ) ) - irc_send_msg_f( (irc_user_t *) bu->ui_data, "PRIVMSG", irc->user->nick, - "\001TYPING %d\001", ( flags >> 8 ) & 3 ); - else + + if (set_getbool(&bee->set, "typing_notice")) { + irc_send_msg_f((irc_user_t *) bu->ui_data, "PRIVMSG", irc->user->nick, + "\001TYPING %d\001", (flags >> 8) & 3); + } else { return FALSE; - + } + return TRUE; } -static gboolean bee_irc_user_action_response( bee_t *bee, bee_user_t *bu, const char *action, char * const args[], void *data ) +static gboolean bee_irc_user_action_response(bee_t *bee, bee_user_t *bu, const char *action, char * const args[], + void *data) { irc_t *irc = (irc_t *) bee->ui_data; - GString *msg = g_string_new( "\001" ); - - g_string_append( msg, action ); - while( *args ) - { - if( strchr( *args, ' ' ) ) - g_string_append_printf( msg, " \"%s\"", *args ); - else - g_string_append_printf( msg, " %s", *args ); - args ++; - } - g_string_append_c( msg, '\001' ); - - irc_send_msg( (irc_user_t *) bu->ui_data, "NOTICE", irc->user->nick, msg->str, NULL ); - + GString *msg = g_string_new("\001"); + + g_string_append(msg, action); + while (*args) { + if (strchr(*args, ' ')) { + g_string_append_printf(msg, " \"%s\"", *args); + } else { + g_string_append_printf(msg, " %s", *args); + } + args++; + } + g_string_append_c(msg, '\001'); + + irc_send_msg((irc_user_t *) bu->ui_data, "NOTICE", irc->user->nick, msg->str, NULL); + return TRUE; } -static gboolean bee_irc_user_nick_update( irc_user_t *iu ); +static gboolean bee_irc_user_nick_update(irc_user_t *iu); -static gboolean bee_irc_user_fullname( bee_t *bee, bee_user_t *bu ) +static gboolean bee_irc_user_fullname(bee_t *bee, bee_user_t *bu) { irc_user_t *iu = (irc_user_t *) bu->ui_data; char *s; - - if( iu->fullname != iu->nick ) - g_free( iu->fullname ); - iu->fullname = g_strdup( bu->fullname ); - + + if (iu->fullname != iu->nick) { + g_free(iu->fullname); + } + iu->fullname = g_strdup(bu->fullname); + /* Strip newlines (unlikely, but IRC-unfriendly so they must go) TODO(wilmer): Do the same with away msgs again! */ - for( s = iu->fullname; *s; s ++ ) - if( g_ascii_isspace( *s ) ) *s = ' '; - - if( ( bu->ic->flags & OPT_LOGGED_IN ) && set_getbool( &bee->set, "display_namechanges" ) ) - { + for (s = iu->fullname; *s; s++) { + if (g_ascii_isspace(*s)) { + *s = ' '; + } + } + + if ((bu->ic->flags & OPT_LOGGED_IN) && set_getbool(&bee->set, "display_namechanges")) { /* People don't like this /NOTICE. Meh, let's go back to the old one. char *msg = g_strdup_printf( "<< \002BitlBee\002 - Changed name to `%s' >>", iu->fullname ); irc_send_msg( iu, "NOTICE", irc->user->nick, msg, NULL ); */ - imcb_log( bu->ic, "User `%s' changed name to `%s'", iu->nick, iu->fullname ); + imcb_log(bu->ic, "User `%s' changed name to `%s'", iu->nick, iu->fullname); } - - bee_irc_user_nick_update( iu ); - + + bee_irc_user_nick_update(iu); + return TRUE; } -static gboolean bee_irc_user_nick_hint( bee_t *bee, bee_user_t *bu, const char *hint ) +static gboolean bee_irc_user_nick_hint(bee_t *bee, bee_user_t *bu, const char *hint) { - bee_irc_user_nick_update( (irc_user_t*) bu->ui_data ); - + bee_irc_user_nick_update((irc_user_t *) bu->ui_data); + return TRUE; } -static gboolean bee_irc_user_group( bee_t *bee, bee_user_t *bu ) +static gboolean bee_irc_user_group(bee_t *bee, bee_user_t *bu) { irc_user_t *iu = (irc_user_t *) bu->ui_data; irc_t *irc = (irc_t *) bee->ui_data; bee_user_flags_t online; - + /* Take the user offline temporarily so we can change the nick (if necessary). */ - if( ( online = bu->flags & BEE_USER_ONLINE ) ) + if ((online = bu->flags & BEE_USER_ONLINE)) { bu->flags &= ~BEE_USER_ONLINE; - - bee_irc_channel_update( irc, NULL, iu ); - bee_irc_user_nick_update( iu ); - - if( online ) - { + } + + bee_irc_channel_update(irc, NULL, iu); + bee_irc_user_nick_update(iu); + + if (online) { bu->flags |= online; - bee_irc_channel_update( irc, NULL, iu ); + bee_irc_channel_update(irc, NULL, iu); } - + return TRUE; } -static gboolean bee_irc_user_nick_update( irc_user_t *iu ) +static gboolean bee_irc_user_nick_update(irc_user_t *iu) { bee_user_t *bu = iu->bu; char *newnick; - - if( bu->flags & BEE_USER_ONLINE ) + + if (bu->flags & BEE_USER_ONLINE) { /* Ignore if the user is visible already. */ return TRUE; - - if( nick_saved( bu ) ) + } + + if (nick_saved(bu)) { /* The user already assigned a nickname to this person. */ return TRUE; - - newnick = nick_get( bu ); - - if( strcmp( iu->nick, newnick ) != 0 ) - { - nick_dedupe( bu, newnick ); - irc_user_set_nick( iu, newnick ); - } - + } + + newnick = nick_get(bu); + + if (strcmp(iu->nick, newnick) != 0) { + nick_dedupe(bu, newnick); + irc_user_set_nick(iu, newnick); + } + return TRUE; } -void bee_irc_user_nick_reset( irc_user_t *iu ) +void bee_irc_user_nick_reset(irc_user_t *iu) { bee_user_t *bu = iu->bu; bee_user_flags_t online; - - if( bu == FALSE ) + + if (bu == FALSE) { return; - + } + /* In this case, pretend the user is offline. */ - if( ( online = bu->flags & BEE_USER_ONLINE ) ) + if ((online = bu->flags & BEE_USER_ONLINE)) { bu->flags &= ~BEE_USER_ONLINE; - - nick_del( bu ); - bee_irc_user_nick_update( iu ); - + } + + nick_del(bu); + bee_irc_user_nick_update(iu); + bu->flags |= online; } /* IRC->IM calls */ -static gboolean bee_irc_user_privmsg_cb( gpointer data, gint fd, b_input_condition cond ); +static gboolean bee_irc_user_privmsg_cb(gpointer data, gint fd, b_input_condition cond); -static gboolean bee_irc_user_privmsg( irc_user_t *iu, const char *msg ) +static gboolean bee_irc_user_privmsg(irc_user_t *iu, const char *msg) { const char *away; - - if( iu->bu == NULL ) + + if (iu->bu == NULL) { return FALSE; - - if( ( away = irc_user_get_away( iu ) ) && - time( NULL ) >= iu->away_reply_timeout ) - { - irc_send_num( iu->irc, 301, "%s :%s", iu->nick, away ); - iu->away_reply_timeout = time( NULL ) + - set_getint( &iu->irc->b->set, "away_reply_timeout" ); - } - - if( iu->pastebuf == NULL ) - iu->pastebuf = g_string_new( msg ); - else - { - b_event_remove( iu->pastebuf_timer ); - g_string_append_printf( iu->pastebuf, "\n%s", msg ); - } - - if( set_getbool( &iu->irc->b->set, "paste_buffer" ) ) - { + } + + if ((away = irc_user_get_away(iu)) && + time(NULL) >= iu->away_reply_timeout) { + irc_send_num(iu->irc, 301, "%s :%s", iu->nick, away); + iu->away_reply_timeout = time(NULL) + + set_getint(&iu->irc->b->set, "away_reply_timeout"); + } + + if (iu->pastebuf == NULL) { + iu->pastebuf = g_string_new(msg); + } else { + b_event_remove(iu->pastebuf_timer); + g_string_append_printf(iu->pastebuf, "\n%s", msg); + } + + if (set_getbool(&iu->irc->b->set, "paste_buffer")) { int delay; - - if( ( delay = set_getint( &iu->irc->b->set, "paste_buffer_delay" ) ) <= 5 ) + + if ((delay = set_getint(&iu->irc->b->set, "paste_buffer_delay")) <= 5) { delay *= 1000; - - iu->pastebuf_timer = b_timeout_add( delay, bee_irc_user_privmsg_cb, iu ); - + } + + iu->pastebuf_timer = b_timeout_add(delay, bee_irc_user_privmsg_cb, iu); + return TRUE; - } - else - { - bee_irc_user_privmsg_cb( iu, 0, 0 ); - + } else { + bee_irc_user_privmsg_cb(iu, 0, 0); + return TRUE; } } -static gboolean bee_irc_user_privmsg_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean bee_irc_user_privmsg_cb(gpointer data, gint fd, b_input_condition cond) { irc_user_t *iu = data; char *msg; GSList *l; - - msg = g_string_free( iu->pastebuf, FALSE ); + + msg = g_string_free(iu->pastebuf, FALSE); iu->pastebuf = NULL; iu->pastebuf_timer = 0; - - for( l = irc_plugins; l; l = l->next ) - { + + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->filter_msg_out ) - { - char *s = p->filter_msg_out( iu, msg, 0 ); - if( s ) - { - if( s != msg ) - g_free( msg ); + if (p->filter_msg_out) { + char *s = p->filter_msg_out(iu, msg, 0); + if (s) { + if (s != msg) { + g_free(msg); + } msg = s; - } - else - { + } else { /* Modules can swallow messages. */ iu->pastebuf = NULL; - g_free( msg ); + g_free(msg); return FALSE; } } } - - bee_user_msg( iu->irc->b, iu->bu, msg, 0 ); - - g_free( msg ); - + + bee_user_msg(iu->irc->b, iu->bu, msg, 0); + + g_free(msg); + return FALSE; } -static gboolean bee_irc_user_ctcp( irc_user_t *iu, char *const *ctcp ) +static gboolean bee_irc_user_ctcp(irc_user_t *iu, char *const *ctcp) { - if( ctcp[1] && g_strcasecmp( ctcp[0], "DCC" ) == 0 - && g_strcasecmp( ctcp[1], "SEND" ) == 0 ) - { - if( iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->transfer_request ) - { - file_transfer_t *ft = dcc_request( iu->bu->ic, ctcp ); - if ( ft ) - iu->bu->ic->acc->prpl->transfer_request( iu->bu->ic, ft, iu->bu->handle ); - + if (ctcp[1] && g_strcasecmp(ctcp[0], "DCC") == 0 + && g_strcasecmp(ctcp[1], "SEND") == 0) { + if (iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->transfer_request) { + file_transfer_t *ft = dcc_request(iu->bu->ic, ctcp); + if (ft) { + iu->bu->ic->acc->prpl->transfer_request(iu->bu->ic, ft, iu->bu->handle); + } + return TRUE; } - } - else if( g_strcasecmp( ctcp[0], "TYPING" ) == 0 ) - { - if( iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->send_typing && ctcp[1] ) - { + } else if (g_strcasecmp(ctcp[0], "TYPING") == 0) { + if (iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->send_typing && ctcp[1]) { int st = ctcp[1][0]; - if( st >= '0' && st <= '2' ) - { + if (st >= '0' && st <= '2') { st <<= 8; - iu->bu->ic->acc->prpl->send_typing( iu->bu->ic, iu->bu->handle, st ); + iu->bu->ic->acc->prpl->send_typing(iu->bu->ic, iu->bu->handle, st); } - + return TRUE; } - } - else if( g_strcasecmp( ctcp[0], "HELP" ) == 0 && iu->bu ) - { - GString *supp = g_string_new( "Supported CTCPs:" ); + } else if (g_strcasecmp(ctcp[0], "HELP") == 0 && iu->bu) { + GString *supp = g_string_new("Supported CTCPs:"); GList *l; - - if( iu->bu->ic && iu->bu->ic->acc->prpl->transfer_request ) - g_string_append( supp, " DCC SEND," ); - if( iu->bu->ic && iu->bu->ic->acc->prpl->send_typing ) - g_string_append( supp, " TYPING," ); - if( iu->bu->ic->acc->prpl->buddy_action_list ) - for( l = iu->bu->ic->acc->prpl->buddy_action_list( iu->bu ); l; l = l->next ) - { + + if (iu->bu->ic && iu->bu->ic->acc->prpl->transfer_request) { + g_string_append(supp, " DCC SEND,"); + } + if (iu->bu->ic && iu->bu->ic->acc->prpl->send_typing) { + g_string_append(supp, " TYPING,"); + } + if (iu->bu->ic->acc->prpl->buddy_action_list) { + for (l = iu->bu->ic->acc->prpl->buddy_action_list(iu->bu); l; l = l->next) { struct buddy_action *ba = l->data; - g_string_append_printf( supp, " %s (%s),", - ba->name, ba->description ); + g_string_append_printf(supp, " %s (%s),", + ba->name, ba->description); } - g_string_truncate( supp, supp->len - 1 ); - irc_send_msg_f( iu, "NOTICE", iu->irc->user->nick, "\001HELP %s\001", supp->str ); - g_string_free( supp, TRUE ); - } - else if( iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->buddy_action ) - { - iu->bu->ic->acc->prpl->buddy_action( iu->bu, ctcp[0], ctcp + 1, NULL ); + } + g_string_truncate(supp, supp->len - 1); + irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001HELP %s\001", supp->str); + g_string_free(supp, TRUE); + } else if (iu->bu && iu->bu->ic && iu->bu->ic->acc->prpl->buddy_action) { + iu->bu->ic->acc->prpl->buddy_action(iu->bu, ctcp[0], ctcp + 1, NULL); } - + return FALSE; } @@ -554,515 +537,524 @@ static const struct irc_user_funcs irc_user_im_funcs = { /* IM->IRC: Groupchats */ const struct irc_channel_funcs irc_channel_im_chat_funcs; -static gboolean bee_irc_chat_new( bee_t *bee, struct groupchat *c ) +static gboolean bee_irc_chat_new(bee_t *bee, struct groupchat *c) { irc_t *irc = bee->ui_data; irc_channel_t *ic; char *topic; GSList *l; int i; - + /* Try to find a channel that expects to receive a groupchat. This flag is set earlier in our current call trace. */ - for( l = irc->channels; l; l = l->next ) - { + for (l = irc->channels; l; l = l->next) { ic = l->data; - if( ic->flags & IRC_CHANNEL_CHAT_PICKME ) + if (ic->flags & IRC_CHANNEL_CHAT_PICKME) { break; + } } - + /* If we found none, just generate some stupid name. */ - if( l == NULL ) for( i = 0; i <= 999; i ++ ) - { - char name[16]; - sprintf( name, "#chat_%03d", i ); - if( ( ic = irc_channel_new( irc, name ) ) ) - break; + if (l == NULL) { + for (i = 0; i <= 999; i++) { + char name[16]; + sprintf(name, "#chat_%03d", i); + if ((ic = irc_channel_new(irc, name))) { + break; + } + } } - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - + } + c->ui_data = ic; ic->data = c; - - topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); - irc_channel_set_topic( ic, topic, irc->root ); - g_free( topic ); - + + topic = g_strdup_printf( + "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", + c->title); + irc_channel_set_topic(ic, topic, irc->root); + g_free(topic); + return TRUE; } -static gboolean bee_irc_chat_free( bee_t *bee, struct groupchat *c ) +static gboolean bee_irc_chat_free(bee_t *bee, struct groupchat *c) { irc_channel_t *ic = c->ui_data; - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - - if( ic->flags & IRC_CHANNEL_JOINED ) - irc_channel_printf( ic, "Cleaning up channel, bye!" ); - + } + + if (ic->flags & IRC_CHANNEL_JOINED) { + irc_channel_printf(ic, "Cleaning up channel, bye!"); + } + ic->data = NULL; c->ui_data = NULL; - irc_channel_del_user( ic, ic->irc->user, IRC_CDU_KICK, "Chatroom closed by server" ); - + irc_channel_del_user(ic, ic->irc->user, IRC_CDU_KICK, "Chatroom closed by server"); + return TRUE; } -static gboolean bee_irc_chat_log( bee_t *bee, struct groupchat *c, const char *text ) +static gboolean bee_irc_chat_log(bee_t *bee, struct groupchat *c, const char *text) { irc_channel_t *ic = c->ui_data; - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - - irc_channel_printf( ic, "%s", text ); - + } + + irc_channel_printf(ic, "%s", text); + return TRUE; } -static gboolean bee_irc_chat_msg( bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at ) +static gboolean bee_irc_chat_msg(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at) { irc_t *irc = bee->ui_data; irc_user_t *iu = bu->ui_data; irc_channel_t *ic = c->ui_data; char *wrapped, *ts = NULL; - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - - if( sent_at > 0 && set_getbool( &bee->set, "display_timestamps" ) ) - ts = irc_format_timestamp( irc, sent_at ); - - wrapped = word_wrap( msg, 425 ); - irc_send_msg( iu, "PRIVMSG", ic->name, wrapped, ts ); - g_free( ts ); - g_free( wrapped ); - + } + + if (sent_at > 0 && set_getbool(&bee->set, "display_timestamps")) { + ts = irc_format_timestamp(irc, sent_at); + } + + wrapped = word_wrap(msg, 425); + irc_send_msg(iu, "PRIVMSG", ic->name, wrapped, ts); + g_free(ts); + g_free(wrapped); + return TRUE; } -static gboolean bee_irc_chat_add_user( bee_t *bee, struct groupchat *c, bee_user_t *bu ) +static gboolean bee_irc_chat_add_user(bee_t *bee, struct groupchat *c, bee_user_t *bu) { irc_t *irc = bee->ui_data; irc_channel_t *ic = c->ui_data; - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - - irc_channel_add_user( ic, bu == bee->user ? irc->user : bu->ui_data ); - + } + + irc_channel_add_user(ic, bu == bee->user ? irc->user : bu->ui_data); + return TRUE; } -static gboolean bee_irc_chat_remove_user( bee_t *bee, struct groupchat *c, bee_user_t *bu ) +static gboolean bee_irc_chat_remove_user(bee_t *bee, struct groupchat *c, bee_user_t *bu) { irc_t *irc = bee->ui_data; irc_channel_t *ic = c->ui_data; - - if( ic == NULL || bu == NULL ) + + if (ic == NULL || bu == NULL) { return FALSE; - + } + /* TODO: Possible bug here: If a module removes $user here instead of just using imcb_chat_free() and the channel was IRC_CHANNEL_TEMP, we get into a broken state around here. */ - irc_channel_del_user( ic, bu == bee->user ? irc->user : bu->ui_data, IRC_CDU_PART, NULL ); - + irc_channel_del_user(ic, bu == bee->user ? irc->user : bu->ui_data, IRC_CDU_PART, NULL); + return TRUE; } -static gboolean bee_irc_chat_topic( bee_t *bee, struct groupchat *c, const char *new, bee_user_t *bu ) +static gboolean bee_irc_chat_topic(bee_t *bee, struct groupchat *c, const char *new, bee_user_t *bu) { irc_channel_t *ic = c->ui_data; irc_t *irc = bee->ui_data; irc_user_t *iu; - - if( ic == NULL ) + + if (ic == NULL) { return FALSE; - - if( bu == NULL ) + } + + if (bu == NULL) { iu = irc->root; - else if( bu == bee->user ) + } else if (bu == bee->user) { iu = irc->user; - else + } else { iu = bu->ui_data; - - irc_channel_set_topic( ic, new, iu ); - + } + + irc_channel_set_topic(ic, new, iu); + return TRUE; } -static gboolean bee_irc_chat_name_hint( bee_t *bee, struct groupchat *c, const char *name ) +static gboolean bee_irc_chat_name_hint(bee_t *bee, struct groupchat *c, const char *name) { irc_t *irc = bee->ui_data; irc_channel_t *ic = c->ui_data, *oic; - char stripped[MAX_NICK_LENGTH+1], *full_name; - - if( ic == NULL ) + char stripped[MAX_NICK_LENGTH + 1], *full_name; + + if (ic == NULL) { return FALSE; - + } + /* Don't rename a channel if the user's in it already. */ - if( ic->flags & IRC_CHANNEL_JOINED ) + if (ic->flags & IRC_CHANNEL_JOINED) { return FALSE; - - strncpy( stripped, name, MAX_NICK_LENGTH ); + } + + strncpy(stripped, name, MAX_NICK_LENGTH); stripped[MAX_NICK_LENGTH] = '\0'; - irc_channel_name_strip( stripped ); - if( set_getbool( &bee->set, "lcnicks" ) ) - nick_lc( irc, stripped ); - - if( stripped[0] == '\0' ) + irc_channel_name_strip(stripped); + if (set_getbool(&bee->set, "lcnicks")) { + nick_lc(irc, stripped); + } + + if (stripped[0] == '\0') { return FALSE; - - full_name = g_strdup_printf( "#%s", stripped ); - if( ( oic = irc_channel_by_name( irc, full_name ) ) ) - { + } + + full_name = g_strdup_printf("#%s", stripped); + if ((oic = irc_channel_by_name(irc, full_name))) { char *type, *chat_type; - - type = set_getstr( &oic->set, "type" ); - chat_type = set_getstr( &oic->set, "chat_type" ); - - if( type && chat_type && oic->data == FALSE && - strcmp( type, "chat" ) == 0 && - strcmp( chat_type, "groupchat" ) == 0 ) - { + + type = set_getstr(&oic->set, "type"); + chat_type = set_getstr(&oic->set, "chat_type"); + + if (type && chat_type && oic->data == FALSE && + strcmp(type, "chat") == 0 && + strcmp(chat_type, "groupchat") == 0) { /* There's a channel with this name already, but it looks like it's not in use yet. Most likely the IRC client rejoined the channel after a reconnect. Remove it so we can reuse its name. */ - irc_channel_free( oic ); - } - else - { - g_free( full_name ); + irc_channel_free(oic); + } else { + g_free(full_name); return FALSE; } } - - g_free( ic->name ); + + g_free(ic->name); ic->name = full_name; - + return TRUE; } -static gboolean bee_irc_chat_invite( bee_t *bee, bee_user_t *bu, const char *name, const char *msg ) +static gboolean bee_irc_chat_invite(bee_t *bee, bee_user_t *bu, const char *name, const char *msg) { char *channel, *s; irc_t *irc = bee->ui_data; irc_user_t *iu = bu->ui_data; irc_channel_t *chan; - - if( strchr( CTYPES, name[0] ) ) - channel = g_strdup( name ); - else - channel = g_strdup_printf( "#%s", name ); - - if( ( s = strchr( channel, '@' ) ) ) + + if (strchr(CTYPES, name[0])) { + channel = g_strdup(name); + } else { + channel = g_strdup_printf("#%s", name); + } + + if ((s = strchr(channel, '@'))) { *s = '\0'; - - if( strlen( channel ) > MAX_NICK_LENGTH ) - { + } + + if (strlen(channel) > MAX_NICK_LENGTH) { /* If the channel name is very long (like those insane GTalk UUID names), try if we can use the inviter's nick. */ - s = g_strdup_printf( "#%s", iu->nick ); - if( irc_channel_by_name( irc, s ) == NULL ) - { - g_free( channel ); + s = g_strdup_printf("#%s", iu->nick); + if (irc_channel_by_name(irc, s) == NULL) { + g_free(channel); channel = s; } } - - if( ( chan = irc_channel_new( irc, channel ) ) && - set_setstr( &chan->set, "type", "chat" ) && - set_setstr( &chan->set, "chat_type", "room" ) && - set_setstr( &chan->set, "account", bu->ic->acc->tag ) && - set_setstr( &chan->set, "room", (char*) name ) ) - { + + if ((chan = irc_channel_new(irc, channel)) && + set_setstr(&chan->set, "type", "chat") && + set_setstr(&chan->set, "chat_type", "room") && + set_setstr(&chan->set, "account", bu->ic->acc->tag) && + set_setstr(&chan->set, "room", (char *) name)) { /* I'm assuming that if the user didn't "chat add" the room himself but got invited, it's temporary, so make this a temporary mapping that is removed as soon as we /PART. */ chan->flags |= IRC_CHANNEL_TEMP; - } - else - { - irc_channel_free( chan ); + } else { + irc_channel_free(chan); chan = NULL; } - g_free( channel ); - - irc_send_msg_f( iu, "PRIVMSG", irc->user->nick, "<< \002BitlBee\002 - Invitation to chatroom %s >>", name ); - if( msg ) - irc_send_msg( iu, "PRIVMSG", irc->user->nick, msg, NULL ); - if( chan ) - { - irc_send_msg_f( iu, "PRIVMSG", irc->user->nick, "To join the room, just /join %s", chan->name ); - irc_send_invite( iu, chan ); - } - + g_free(channel); + + irc_send_msg_f(iu, "PRIVMSG", irc->user->nick, "<< \002BitlBee\002 - Invitation to chatroom %s >>", name); + if (msg) { + irc_send_msg(iu, "PRIVMSG", irc->user->nick, msg, NULL); + } + if (chan) { + irc_send_msg_f(iu, "PRIVMSG", irc->user->nick, "To join the room, just /join %s", chan->name); + irc_send_invite(iu, chan); + } + return TRUE; } /* IRC->IM */ -static gboolean bee_irc_channel_chat_privmsg_cb( gpointer data, gint fd, b_input_condition cond ); +static gboolean bee_irc_channel_chat_privmsg_cb(gpointer data, gint fd, b_input_condition cond); -static gboolean bee_irc_channel_chat_privmsg( irc_channel_t *ic, const char *msg ) +static gboolean bee_irc_channel_chat_privmsg(irc_channel_t *ic, const char *msg) { struct groupchat *c = ic->data; char *trans = NULL, *s; - - if( c == NULL ) + + if (c == NULL) { return FALSE; - - if( set_getbool( &ic->set, "translate_to_nicks" ) ) - { - char nick[MAX_NICK_LENGTH+1]; + } + + if (set_getbool(&ic->set, "translate_to_nicks")) { + char nick[MAX_NICK_LENGTH + 1]; irc_user_t *iu; - - strncpy( nick, msg, MAX_NICK_LENGTH ); + + strncpy(nick, msg, MAX_NICK_LENGTH); nick[MAX_NICK_LENGTH] = '\0'; - if( ( s = strchr( nick, ':' ) ) || ( s = strchr( nick, ',' ) ) ) - { + if ((s = strchr(nick, ':')) || (s = strchr(nick, ','))) { *s = '\0'; - if( ( iu = irc_user_by_name( ic->irc, nick ) ) && iu->bu && - iu->bu->nick && irc_channel_has_user( ic, iu ) ) - { - trans = g_strconcat( iu->bu->nick, msg + ( s - nick ), NULL ); + if ((iu = irc_user_by_name(ic->irc, nick)) && iu->bu && + iu->bu->nick && irc_channel_has_user(ic, iu)) { + trans = g_strconcat(iu->bu->nick, msg + (s - nick), NULL); msg = trans; } } } - - if( set_getbool( &ic->irc->b->set, "paste_buffer" ) ) - { + + if (set_getbool(&ic->irc->b->set, "paste_buffer")) { int delay; - - if( ic->pastebuf == NULL ) - ic->pastebuf = g_string_new( msg ); - else - { - b_event_remove( ic->pastebuf_timer ); - g_string_append_printf( ic->pastebuf, "\n%s", msg ); + + if (ic->pastebuf == NULL) { + ic->pastebuf = g_string_new(msg); + } else { + b_event_remove(ic->pastebuf_timer); + g_string_append_printf(ic->pastebuf, "\n%s", msg); } - - if( ( delay = set_getint( &ic->irc->b->set, "paste_buffer_delay" ) ) <= 5 ) + + if ((delay = set_getint(&ic->irc->b->set, "paste_buffer_delay")) <= 5) { delay *= 1000; - - ic->pastebuf_timer = b_timeout_add( delay, bee_irc_channel_chat_privmsg_cb, ic ); - - g_free( trans ); + } + + ic->pastebuf_timer = b_timeout_add(delay, bee_irc_channel_chat_privmsg_cb, ic); + + g_free(trans); return TRUE; + } else { + bee_chat_msg(ic->irc->b, c, msg, 0); } - else - bee_chat_msg( ic->irc->b, c, msg, 0 ); - - g_free( trans ); + + g_free(trans); return TRUE; } -static gboolean bee_irc_channel_chat_privmsg_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean bee_irc_channel_chat_privmsg_cb(gpointer data, gint fd, b_input_condition cond) { irc_channel_t *ic = data; - - if( ic->data ) - bee_chat_msg( ic->irc->b, ic->data, ic->pastebuf->str, 0 ); - - g_string_free( ic->pastebuf, TRUE ); + + if (ic->data) { + bee_chat_msg(ic->irc->b, ic->data, ic->pastebuf->str, 0); + } + + g_string_free(ic->pastebuf, TRUE); ic->pastebuf = 0; ic->pastebuf_timer = 0; - + return FALSE; } -static gboolean bee_irc_channel_chat_join( irc_channel_t *ic ) +static gboolean bee_irc_channel_chat_join(irc_channel_t *ic) { char *acc_s, *room; account_t *acc; - - if( strcmp( set_getstr( &ic->set, "chat_type" ), "room" ) != 0 ) + + if (strcmp(set_getstr(&ic->set, "chat_type"), "room") != 0) { return TRUE; - - if( ( acc_s = set_getstr( &ic->set, "account" ) ) && - ( room = set_getstr( &ic->set, "room" ) ) && - ( acc = account_get( ic->irc->b, acc_s ) ) && - acc->ic && acc->prpl->chat_join ) - { + } + + if ((acc_s = set_getstr(&ic->set, "account")) && + (room = set_getstr(&ic->set, "room")) && + (acc = account_get(ic->irc->b, acc_s)) && + acc->ic && acc->prpl->chat_join) { char *nick; - - if( !( nick = set_getstr( &ic->set, "nick" ) ) ) + + if (!(nick = set_getstr(&ic->set, "nick"))) { nick = ic->irc->user->nick; - + } + ic->flags |= IRC_CHANNEL_CHAT_PICKME; - acc->prpl->chat_join( acc->ic, room, nick, NULL, &ic->set ); + acc->prpl->chat_join(acc->ic, room, nick, NULL, &ic->set); ic->flags &= ~IRC_CHANNEL_CHAT_PICKME; - + return FALSE; - } - else - { - irc_send_num( ic->irc, 403, "%s :Can't join channel, account offline?", ic->name ); + } else { + irc_send_num(ic->irc, 403, "%s :Can't join channel, account offline?", ic->name); return FALSE; } } -static gboolean bee_irc_channel_chat_part( irc_channel_t *ic, const char *msg ) +static gboolean bee_irc_channel_chat_part(irc_channel_t *ic, const char *msg) { struct groupchat *c = ic->data; - - if( c && c->ic->acc->prpl->chat_leave ) - c->ic->acc->prpl->chat_leave( c ); - + + if (c && c->ic->acc->prpl->chat_leave) { + c->ic->acc->prpl->chat_leave(c); + } + /* Remove the reference. We don't need it anymore. */ ic->data = NULL; - + return TRUE; } -static gboolean bee_irc_channel_chat_topic( irc_channel_t *ic, const char *new ) +static gboolean bee_irc_channel_chat_topic(irc_channel_t *ic, const char *new) { struct groupchat *c = ic->data; - - if( c == NULL ) + + if (c == NULL) { return FALSE; - - if( c->ic->acc->prpl->chat_topic == NULL ) - irc_send_num( ic->irc, 482, "%s :IM network does not support channel topics", ic->name ); - else - { + } + + if (c->ic->acc->prpl->chat_topic == NULL) { + irc_send_num(ic->irc, 482, "%s :IM network does not support channel topics", ic->name); + } else { /* TODO: Need more const goodness here, sigh */ - char *topic = g_strdup( new ); - c->ic->acc->prpl->chat_topic( c, topic ); - g_free( topic ); + char *topic = g_strdup(new); + c->ic->acc->prpl->chat_topic(c, topic); + g_free(topic); } - + /* Whatever happened, the IM module should ack the topic change. */ return FALSE; } -static gboolean bee_irc_channel_chat_invite( irc_channel_t *ic, irc_user_t *iu ) +static gboolean bee_irc_channel_chat_invite(irc_channel_t *ic, irc_user_t *iu) { struct groupchat *c = ic->data; bee_user_t *bu = iu->bu; - - if( bu == NULL ) + + if (bu == NULL) { return FALSE; - - if( c ) - { - if( iu->bu->ic != c->ic ) - irc_send_num( ic->irc, 482, "%s :Can't mix different IM networks in one groupchat", ic->name ); - else if( c->ic->acc->prpl->chat_invite ) - c->ic->acc->prpl->chat_invite( c, iu->bu->handle, NULL ); - else - irc_send_num( ic->irc, 482, "%s :IM protocol does not support room invitations", ic->name ); - } - else if( bu->ic->acc->prpl->chat_with && - strcmp( set_getstr( &ic->set, "chat_type" ), "groupchat" ) == 0 ) - { + } + + if (c) { + if (iu->bu->ic != c->ic) { + irc_send_num(ic->irc, 482, "%s :Can't mix different IM networks in one groupchat", ic->name); + } else if (c->ic->acc->prpl->chat_invite) { + c->ic->acc->prpl->chat_invite(c, iu->bu->handle, NULL); + } else { + irc_send_num(ic->irc, 482, "%s :IM protocol does not support room invitations", ic->name); + } + } else if (bu->ic->acc->prpl->chat_with && + strcmp(set_getstr(&ic->set, "chat_type"), "groupchat") == 0) { ic->flags |= IRC_CHANNEL_CHAT_PICKME; - iu->bu->ic->acc->prpl->chat_with( bu->ic, bu->handle ); + iu->bu->ic->acc->prpl->chat_with(bu->ic, bu->handle); ic->flags &= ~IRC_CHANNEL_CHAT_PICKME; + } else { + irc_send_num(ic->irc, 482, "%s :IM protocol does not support room invitations", ic->name); } - else - { - irc_send_num( ic->irc, 482, "%s :IM protocol does not support room invitations", ic->name ); - } - + return TRUE; } -static void bee_irc_channel_chat_kick( irc_channel_t *ic, irc_user_t *iu, const char *msg ) +static void bee_irc_channel_chat_kick(irc_channel_t *ic, irc_user_t *iu, const char *msg) { struct groupchat *c = ic->data; bee_user_t *bu = iu->bu; - - if( ( c == NULL ) || ( bu == NULL ) ) + + if ((c == NULL) || (bu == NULL)) { return; - - if( !c->ic->acc->prpl->chat_kick ) - { - irc_send_num( ic->irc, 482, "%s :IM protocol does not support room kicking", ic->name ); + } + + if (!c->ic->acc->prpl->chat_kick) { + irc_send_num(ic->irc, 482, "%s :IM protocol does not support room kicking", ic->name); return; } - - c->ic->acc->prpl->chat_kick( c, iu->bu->handle, msg ); + + c->ic->acc->prpl->chat_kick(c, iu->bu->handle, msg); } -static char *set_eval_room_account( set_t *set, char *value ); -static char *set_eval_chat_type( set_t *set, char *value ); +static char *set_eval_room_account(set_t *set, char *value); +static char *set_eval_chat_type(set_t *set, char *value); -static gboolean bee_irc_channel_init( irc_channel_t *ic ) +static gboolean bee_irc_channel_init(irc_channel_t *ic) { set_t *s; - set_add( &ic->set, "account", NULL, set_eval_room_account, ic ); - set_add( &ic->set, "chat_type", "groupchat", set_eval_chat_type, ic ); + set_add(&ic->set, "account", NULL, set_eval_room_account, ic); + set_add(&ic->set, "chat_type", "groupchat", set_eval_chat_type, ic); - s = set_add( &ic->set, "nick", NULL, NULL, ic ); + s = set_add(&ic->set, "nick", NULL, NULL, ic); s->flags |= SET_NULL_OK; - set_add( &ic->set, "room", NULL, NULL, ic ); - set_add( &ic->set, "translate_to_nicks", "true", set_eval_bool, ic ); - + set_add(&ic->set, "room", NULL, NULL, ic); + set_add(&ic->set, "translate_to_nicks", "true", set_eval_bool, ic); + /* chat_type == groupchat */ ic->flags |= IRC_CHANNEL_TEMP; - + return TRUE; } -static char *set_eval_room_account( set_t *set, char *value ) +static char *set_eval_room_account(set_t *set, char *value) { struct irc_channel *ic = set->data; account_t *acc, *oa; - - if( !( acc = account_get( ic->irc->b, value ) ) ) + + if (!(acc = account_get(ic->irc->b, value))) { return SET_INVALID; - else if( !acc->prpl->chat_join ) - { - irc_rootmsg( ic->irc, "Named chatrooms not supported on that account." ); + } else if (!acc->prpl->chat_join) { + irc_rootmsg(ic->irc, "Named chatrooms not supported on that account."); return SET_INVALID; } - - if( set->value && ( oa = account_get( ic->irc->b, set->value ) ) && - oa->prpl->chat_free_settings ) - oa->prpl->chat_free_settings( oa, &ic->set ); - - if( acc->prpl->chat_add_settings ) - acc->prpl->chat_add_settings( acc, &ic->set ); - - return g_strdup( acc->tag ); + + if (set->value && (oa = account_get(ic->irc->b, set->value)) && + oa->prpl->chat_free_settings) { + oa->prpl->chat_free_settings(oa, &ic->set); + } + + if (acc->prpl->chat_add_settings) { + acc->prpl->chat_add_settings(acc, &ic->set); + } + + return g_strdup(acc->tag); } -static char *set_eval_chat_type( set_t *set, char *value ) +static char *set_eval_chat_type(set_t *set, char *value) { struct irc_channel *ic = set->data; - - if( strcmp( value, "groupchat" ) == 0 ) + + if (strcmp(value, "groupchat") == 0) { ic->flags |= IRC_CHANNEL_TEMP; - else if( strcmp( value, "room" ) == 0 ) + } else if (strcmp(value, "room") == 0) { ic->flags &= ~IRC_CHANNEL_TEMP; - else + } else { return NULL; - + } + return value; } -static gboolean bee_irc_channel_free( irc_channel_t *ic ) +static gboolean bee_irc_channel_free(irc_channel_t *ic) { struct groupchat *c = ic->data; - - set_del( &ic->set, "account" ); - set_del( &ic->set, "chat_type" ); - set_del( &ic->set, "nick" ); - set_del( &ic->set, "room" ); - set_del( &ic->set, "translate_to_nicks" ); - + + set_del(&ic->set, "account"); + set_del(&ic->set, "chat_type"); + set_del(&ic->set, "nick"); + set_del(&ic->set, "room"); + set_del(&ic->set, "translate_to_nicks"); + ic->flags &= ~IRC_CHANNEL_TEMP; - + /* That one still points at this channel. Don't. */ - if( c ) + if (c) { c->ui_data = NULL; - + } + return TRUE; } @@ -1080,35 +1072,36 @@ const struct irc_channel_funcs irc_channel_im_chat_funcs = { /* IM->IRC: File transfers */ -static file_transfer_t *bee_irc_ft_in_start( bee_t *bee, bee_user_t *bu, const char *file_name, size_t file_size ) +static file_transfer_t *bee_irc_ft_in_start(bee_t *bee, bee_user_t *bu, const char *file_name, size_t file_size) { - return dccs_send_start( bu->ic, (irc_user_t *) bu->ui_data, file_name, file_size ); + return dccs_send_start(bu->ic, (irc_user_t *) bu->ui_data, file_name, file_size); } -static gboolean bee_irc_ft_out_start( struct im_connection *ic, file_transfer_t *ft ) +static gboolean bee_irc_ft_out_start(struct im_connection *ic, file_transfer_t *ft) { - return dccs_recv_start( ft ); + return dccs_recv_start(ft); } -static void bee_irc_ft_close( struct im_connection *ic, file_transfer_t *ft ) +static void bee_irc_ft_close(struct im_connection *ic, file_transfer_t *ft) { - return dcc_close( ft ); + return dcc_close(ft); } -static void bee_irc_ft_finished( struct im_connection *ic, file_transfer_t *file ) +static void bee_irc_ft_finished(struct im_connection *ic, file_transfer_t *file) { dcc_file_transfer_t *df = file->priv; - if( file->bytes_transferred >= file->file_size ) - dcc_finish( file ); - else + if (file->bytes_transferred >= file->file_size) { + dcc_finish(file); + } else { df->proto_finished = TRUE; + } } const struct bee_ui_funcs irc_ui_funcs = { bee_irc_imc_connected, bee_irc_imc_disconnected, - + bee_irc_user_new, bee_irc_user_free, bee_irc_user_fullname, @@ -1118,7 +1111,7 @@ const struct bee_ui_funcs irc_ui_funcs = { bee_irc_user_msg, bee_irc_user_typing, bee_irc_user_action_response, - + bee_irc_chat_new, bee_irc_chat_free, bee_irc_chat_log, @@ -1128,7 +1121,7 @@ const struct bee_ui_funcs irc_ui_funcs = { bee_irc_chat_topic, bee_irc_chat_name_hint, bee_irc_chat_invite, - + bee_irc_ft_in_start, bee_irc_ft_out_start, bee_irc_ft_close, @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -25,420 +25,406 @@ #include "bitlbee.h" -void irc_send_num( irc_t *irc, int code, char *format, ... ) +void irc_send_num(irc_t *irc, int code, char *format, ...) { char text[IRC_MAX_LINE]; va_list params; - - va_start( params, format ); - g_vsnprintf( text, IRC_MAX_LINE, format, params ); - va_end( params ); - - irc_write( irc, ":%s %03d %s %s", irc->root->host, code, irc->user->nick ? : "*", text ); + + va_start(params, format); + g_vsnprintf(text, IRC_MAX_LINE, format, params); + va_end(params); + + irc_write(irc, ":%s %03d %s %s", irc->root->host, code, irc->user->nick ? : "*", text); } -void irc_send_login( irc_t *irc ) +void irc_send_login(irc_t *irc) { - irc_send_num( irc, 1, ":Welcome to the %s gateway, %s", PACKAGE, irc->user->nick ); - irc_send_num( irc, 2, ":Host %s is running %s %s %s/%s.", irc->root->host, - PACKAGE, BITLBEE_VERSION, ARCH, CPU ); - irc_send_num( irc, 3, ":%s", IRCD_INFO ); - irc_send_num( irc, 4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES ); - irc_send_num( irc, 5, "PREFIX=(ohv)@%%+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d CHANNELLEN=%d " - "NETWORK=BitlBee SAFELIST CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 " - "FLOOD=0/9999 :are supported by this server", - CTYPES, CMODES, MAX_NICK_LENGTH - 1, MAX_NICK_LENGTH - 1 ); - irc_send_motd( irc ); + irc_send_num(irc, 1, ":Welcome to the %s gateway, %s", PACKAGE, irc->user->nick); + irc_send_num(irc, 2, ":Host %s is running %s %s %s/%s.", irc->root->host, + PACKAGE, BITLBEE_VERSION, ARCH, CPU); + irc_send_num(irc, 3, ":%s", IRCD_INFO); + irc_send_num(irc, 4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES); + irc_send_num(irc, 5, "PREFIX=(ohv)@%%+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d CHANNELLEN=%d " + "NETWORK=BitlBee SAFELIST CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 " + "FLOOD=0/9999 :are supported by this server", + CTYPES, CMODES, MAX_NICK_LENGTH - 1, MAX_NICK_LENGTH - 1); + irc_send_motd(irc); } -void irc_send_motd( irc_t *irc ) +void irc_send_motd(irc_t *irc) { char motd[2048]; size_t len; int fd; - - fd = open( global.conf->motdfile, O_RDONLY ); - if( fd == -1 || ( len = read( fd, motd, sizeof( motd ) - 1 ) ) <= 0 ) - { - irc_send_num( irc, 422, ":We don't need MOTDs." ); - } - else - { + + fd = open(global.conf->motdfile, O_RDONLY); + if (fd == -1 || (len = read(fd, motd, sizeof(motd) - 1)) <= 0) { + irc_send_num(irc, 422, ":We don't need MOTDs."); + } else { char linebuf[80]; char *add = "", max, *in; - + in = motd; motd[len] = '\0'; linebuf[79] = len = 0; - max = sizeof( linebuf ) - 1; - - irc_send_num( irc, 375, ":- %s Message Of The Day - ", irc->root->host ); - while( ( linebuf[len] = *(in++) ) ) - { - if( linebuf[len] == '\n' || len == max ) - { + max = sizeof(linebuf) - 1; + + irc_send_num(irc, 375, ":- %s Message Of The Day - ", irc->root->host); + while ((linebuf[len] = *(in++))) { + if (linebuf[len] == '\n' || len == max) { linebuf[len] = 0; - irc_send_num( irc, 372, ":- %s", linebuf ); + irc_send_num(irc, 372, ":- %s", linebuf); len = 0; - } - else if( linebuf[len] == '%' ) - { + } else if (linebuf[len] == '%') { linebuf[len] = *(in++); - if( linebuf[len] == 'h' ) + if (linebuf[len] == 'h') { add = irc->root->host; - else if( linebuf[len] == 'v' ) + } else if (linebuf[len] == 'v') { add = BITLBEE_VERSION; - else if( linebuf[len] == 'n' ) + } else if (linebuf[len] == 'n') { add = irc->user->nick; - else if( linebuf[len] == '\0' ) - in --; - else + } else if (linebuf[len] == '\0') { + in--; + } else { add = "%"; - - strncpy( linebuf + len, add, max - len ); - while( linebuf[++len] ); - } - else if( len < max ) - { - len ++; + } + + strncpy(linebuf + len, add, max - len); + while (linebuf[++len]) { + ; + } + } else if (len < max) { + len++; } } - irc_send_num( irc, 376, ":End of MOTD" ); + irc_send_num(irc, 376, ":End of MOTD"); + } + + if (fd != -1) { + close(fd); } - - if( fd != -1 ) - close( fd ); } /* Used by some funcs that generate PRIVMSGs to figure out if we're talking to this person in /query or in a control channel. WARNING: callers rely on this returning a pointer at irc->user_nick, not a copy of it. */ -const char *irc_user_msgdest( irc_user_t *iu ) +const char *irc_user_msgdest(irc_user_t *iu) { irc_t *irc = iu->irc; irc_channel_t *ic = NULL; - if( iu->last_channel ) - { - if( iu->last_channel->flags & IRC_CHANNEL_JOINED ) + if (iu->last_channel) { + if (iu->last_channel->flags & IRC_CHANNEL_JOINED) { ic = iu->last_channel; - else - ic = irc_channel_with_user( irc, iu ); + } else { + ic = irc_channel_with_user(irc, iu); + } } - - if( ic ) + + if (ic) { return ic->name; - else + } else { return irc->user->nick; + } } /* cmd = "PRIVMSG" or "NOTICE" */ -static void irc_usermsg_( const char *cmd, irc_user_t *iu, const char *format, va_list params ) +static void irc_usermsg_(const char *cmd, irc_user_t *iu, const char *format, va_list params) { char text[2048]; const char *dst; - - g_vsnprintf( text, sizeof( text ), format, params ); - - dst = irc_user_msgdest( iu ); - irc_send_msg( iu, cmd, dst, text, NULL ); + + g_vsnprintf(text, sizeof(text), format, params); + + dst = irc_user_msgdest(iu); + irc_send_msg(iu, cmd, dst, text, NULL); } -void irc_usermsg(irc_user_t *iu, char *format, ... ) +void irc_usermsg(irc_user_t *iu, char *format, ...) { va_list params; - va_start( params, format ); - irc_usermsg_( "PRIVMSG", iu, format, params ); - va_end( params ); + + va_start(params, format); + irc_usermsg_("PRIVMSG", iu, format, params); + va_end(params); } -void irc_usernotice(irc_user_t *iu, char *format, ... ) +void irc_usernotice(irc_user_t *iu, char *format, ...) { va_list params; - va_start( params, format ); - irc_usermsg_( "NOTICE", iu, format, params ); - va_end( params ); + + va_start(params, format); + irc_usermsg_("NOTICE", iu, format, params); + va_end(params); } -void irc_rootmsg( irc_t *irc, char *format, ... ) +void irc_rootmsg(irc_t *irc, char *format, ...) { va_list params; - va_start( params, format ); - irc_usermsg_( "PRIVMSG", irc->root, format, params ); - va_end( params ); + + va_start(params, format); + irc_usermsg_("PRIVMSG", irc->root, format, params); + va_end(params); } -void irc_send_join( irc_channel_t *ic, irc_user_t *iu ) +void irc_send_join(irc_channel_t *ic, irc_user_t *iu) { irc_t *irc = ic->irc; - - irc_write( irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name ); - - if( iu == irc->user ) - { - irc_write( irc, ":%s MODE %s +%s", irc->root->host, ic->name, ic->mode ); - irc_send_names( ic ); - if( ic->topic && *ic->topic ) - irc_send_topic( ic, FALSE ); + + irc_write(irc, ":%s!%s@%s JOIN :%s", iu->nick, iu->user, iu->host, ic->name); + + if (iu == irc->user) { + irc_write(irc, ":%s MODE %s +%s", irc->root->host, ic->name, ic->mode); + irc_send_names(ic); + if (ic->topic && *ic->topic) { + irc_send_topic(ic, FALSE); + } } } -void irc_send_part( irc_channel_t *ic, irc_user_t *iu, const char *reason ) +void irc_send_part(irc_channel_t *ic, irc_user_t *iu, const char *reason) { - irc_write( ic->irc, ":%s!%s@%s PART %s :%s", iu->nick, iu->user, iu->host, ic->name, reason ? : "" ); + irc_write(ic->irc, ":%s!%s@%s PART %s :%s", iu->nick, iu->user, iu->host, ic->name, reason ? : ""); } -void irc_send_quit( irc_user_t *iu, const char *reason ) +void irc_send_quit(irc_user_t *iu, const char *reason) { - irc_write( iu->irc, ":%s!%s@%s QUIT :%s", iu->nick, iu->user, iu->host, reason ? : "" ); + irc_write(iu->irc, ":%s!%s@%s QUIT :%s", iu->nick, iu->user, iu->host, reason ? : ""); } -void irc_send_kick( irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const char *reason ) +void irc_send_kick(irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const char *reason) { - irc_write( ic->irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, - kicker->host, ic->name, iu->nick, reason ? : "" ); + irc_write(ic->irc, ":%s!%s@%s KICK %s %s :%s", kicker->nick, kicker->user, + kicker->host, ic->name, iu->nick, reason ? : ""); } -void irc_send_names( irc_channel_t *ic ) +void irc_send_names(irc_channel_t *ic) { GSList *l; char namelist[385] = ""; - + /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ - for( l = ic->users; l; l = l->next ) - { + for (l = ic->users; l; l = l->next) { irc_channel_user_t *icu = l->data; irc_user_t *iu = icu->iu; - - if( strlen( namelist ) + strlen( iu->nick ) > sizeof( namelist ) - 4 ) - { - irc_send_num( ic->irc, 353, "= %s :%s", ic->name, namelist ); + + if (strlen(namelist) + strlen(iu->nick) > sizeof(namelist) - 4) { + irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist); *namelist = 0; } - - if( icu->flags & IRC_CHANNEL_USER_OP ) - strcat( namelist, "@" ); - else if( icu->flags & IRC_CHANNEL_USER_HALFOP ) - strcat( namelist, "%" ); - else if( icu->flags & IRC_CHANNEL_USER_VOICE ) - strcat( namelist, "+" ); - - strcat( namelist, iu->nick ); - strcat( namelist, " " ); + + if (icu->flags & IRC_CHANNEL_USER_OP) { + strcat(namelist, "@"); + } else if (icu->flags & IRC_CHANNEL_USER_HALFOP) { + strcat(namelist, "%"); + } else if (icu->flags & IRC_CHANNEL_USER_VOICE) { + strcat(namelist, "+"); + } + + strcat(namelist, iu->nick); + strcat(namelist, " "); } - - if( *namelist ) - irc_send_num( ic->irc, 353, "= %s :%s", ic->name, namelist ); - - irc_send_num( ic->irc, 366, "%s :End of /NAMES list", ic->name ); + + if (*namelist) { + irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist); + } + + irc_send_num(ic->irc, 366, "%s :End of /NAMES list", ic->name); } -void irc_send_topic( irc_channel_t *ic, gboolean topic_change ) +void irc_send_topic(irc_channel_t *ic, gboolean topic_change) { - if( topic_change && ic->topic_who ) - { - irc_write( ic->irc, ":%s TOPIC %s :%s", ic->topic_who, - ic->name, ic->topic && *ic->topic ? ic->topic : "" ); - } - else if( ic->topic ) - { - irc_send_num( ic->irc, 332, "%s :%s", ic->name, ic->topic ); - if( ic->topic_who ) - irc_send_num( ic->irc, 333, "%s %s %d", - ic->name, ic->topic_who, (int) ic->topic_time ); + if (topic_change && ic->topic_who) { + irc_write(ic->irc, ":%s TOPIC %s :%s", ic->topic_who, + ic->name, ic->topic && *ic->topic ? ic->topic : ""); + } else if (ic->topic) { + irc_send_num(ic->irc, 332, "%s :%s", ic->name, ic->topic); + if (ic->topic_who) { + irc_send_num(ic->irc, 333, "%s %s %d", + ic->name, ic->topic_who, (int) ic->topic_time); + } + } else { + irc_send_num(ic->irc, 331, "%s :No topic for this channel", ic->name); } - else - irc_send_num( ic->irc, 331, "%s :No topic for this channel", ic->name ); } -void irc_send_whois( irc_user_t *iu ) +void irc_send_whois(irc_user_t *iu) { irc_t *irc = iu->irc; - - irc_send_num( irc, 311, "%s %s %s * :%s", - iu->nick, iu->user, iu->host, iu->fullname ); - - if( iu->bu ) - { + + irc_send_num(irc, 311, "%s %s %s * :%s", + iu->nick, iu->user, iu->host, iu->fullname); + + if (iu->bu) { bee_user_t *bu = iu->bu; - - irc_send_num( irc, 312, "%s %s.%s :%s network", iu->nick, bu->ic->acc->user, - bu->ic->acc->server && *bu->ic->acc->server ? bu->ic->acc->server : "", - bu->ic->acc->prpl->name ); - - if( ( bu->status && *bu->status ) || - ( bu->status_msg && *bu->status_msg ) ) - { + + irc_send_num(irc, 312, "%s %s.%s :%s network", iu->nick, bu->ic->acc->user, + bu->ic->acc->server && *bu->ic->acc->server ? bu->ic->acc->server : "", + bu->ic->acc->prpl->name); + + if ((bu->status && *bu->status) || + (bu->status_msg && *bu->status_msg)) { int num = bu->flags & BEE_USER_AWAY ? 301 : 320; - - if( bu->status && bu->status_msg ) - irc_send_num( irc, num, "%s :%s (%s)", iu->nick, bu->status, bu->status_msg ); - else - irc_send_num( irc, num, "%s :%s", iu->nick, bu->status ? : bu->status_msg ); - } - else if( !( bu->flags & BEE_USER_ONLINE ) ) - { - irc_send_num( irc, 301, "%s :%s", iu->nick, "User is offline" ); + + if (bu->status && bu->status_msg) { + irc_send_num(irc, num, "%s :%s (%s)", iu->nick, bu->status, bu->status_msg); + } else { + irc_send_num(irc, num, "%s :%s", iu->nick, bu->status ? : bu->status_msg); + } + } else if (!(bu->flags & BEE_USER_ONLINE)) { + irc_send_num(irc, 301, "%s :%s", iu->nick, "User is offline"); } - - if( bu->idle_time || bu->login_time ) - { - irc_send_num( irc, 317, "%s %d %d :seconds idle, signon time", - iu->nick, - bu->idle_time ? (int) ( time( NULL ) - bu->idle_time ) : 0, - (int) bu->login_time ); + + if (bu->idle_time || bu->login_time) { + irc_send_num(irc, 317, "%s %d %d :seconds idle, signon time", + iu->nick, + bu->idle_time ? (int) (time(NULL) - bu->idle_time) : 0, + (int) bu->login_time); } + } else { + irc_send_num(irc, 312, "%s %s :%s", iu->nick, irc->root->host, IRCD_INFO); } - else - { - irc_send_num( irc, 312, "%s %s :%s", iu->nick, irc->root->host, IRCD_INFO ); - } - - irc_send_num( irc, 318, "%s :End of /WHOIS list", iu->nick ); + + irc_send_num(irc, 318, "%s :End of /WHOIS list", iu->nick); } -void irc_send_who( irc_t *irc, GSList *l, const char *channel ) +void irc_send_who(irc_t *irc, GSList *l, const char *channel) { - gboolean is_channel = strchr( CTYPES, channel[0] ) != NULL; - - while( l ) - { + gboolean is_channel = strchr(CTYPES, channel[0]) != NULL; + + while (l) { irc_user_t *iu = l->data; - if( is_channel ) - iu = ((irc_channel_user_t*)iu)->iu; + if (is_channel) { + iu = ((irc_channel_user_t *) iu)->iu; + } /* TODO(wilmer): Restore away/channel information here */ - irc_send_num( irc, 352, "%s %s %s %s %s %c :0 %s", - is_channel ? channel : "*", iu->user, iu->host, irc->root->host, - iu->nick, iu->flags & IRC_USER_AWAY ? 'G' : 'H', - iu->fullname ); + irc_send_num(irc, 352, "%s %s %s %s %s %c :0 %s", + is_channel ? channel : "*", iu->user, iu->host, irc->root->host, + iu->nick, iu->flags & IRC_USER_AWAY ? 'G' : 'H', + iu->fullname); l = l->next; } - - irc_send_num( irc, 315, "%s :End of /WHO list", channel ); + + irc_send_num(irc, 315, "%s :End of /WHO list", channel); } -void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix ) +void irc_send_msg(irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix) { char last = 0; const char *s = msg, *line = msg; - char raw_msg[strlen(msg)+1024]; - - while( !last ) - { - if( *s == '\r' && *(s+1) == '\n' ) + char raw_msg[strlen(msg) + 1024]; + + while (!last) { + if (*s == '\r' && *(s + 1) == '\n') { s++; - if( *s == '\n' ) - { - last = s[1] == 0; } - else - { + if (*s == '\n') { + last = s[1] == 0; + } else { last = s[0] == 0; } - if( *s == 0 || *s == '\n' ) - { - if( g_strncasecmp( line, "/me ", 4 ) == 0 && ( !prefix || !*prefix ) && - g_strcasecmp( type, "PRIVMSG" ) == 0 ) - { - strcpy( raw_msg, "\001ACTION " ); - strncat( raw_msg, line + 4, s - line - 4 ); - strcat( raw_msg, "\001" ); - irc_send_msg_raw( iu, type, dst, raw_msg ); - } - else - { + if (*s == 0 || *s == '\n') { + if (g_strncasecmp(line, "/me ", 4) == 0 && (!prefix || !*prefix) && + g_strcasecmp(type, "PRIVMSG") == 0) { + strcpy(raw_msg, "\001ACTION "); + strncat(raw_msg, line + 4, s - line - 4); + strcat(raw_msg, "\001"); + irc_send_msg_raw(iu, type, dst, raw_msg); + } else { *raw_msg = '\0'; - if( prefix && *prefix ) - strcpy( raw_msg, prefix ); - strncat( raw_msg, line, s - line ); - irc_send_msg_raw( iu, type, dst, raw_msg ); + if (prefix && *prefix) { + strcpy(raw_msg, prefix); + } + strncat(raw_msg, line, s - line); + irc_send_msg_raw(iu, type, dst, raw_msg); } line = s + 1; } - s ++; + s++; } } -void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg ) +void irc_send_msg_raw(irc_user_t *iu, const char *type, const char *dst, const char *msg) { - irc_write( iu->irc, ":%s!%s@%s %s %s :%s", - iu->nick, iu->user, iu->host, type, dst, msg && *msg ? msg : " " ); + irc_write(iu->irc, ":%s!%s@%s %s %s :%s", + iu->nick, iu->user, iu->host, type, dst, msg && *msg ? msg : " "); } -void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) +void irc_send_msg_f(irc_user_t *iu, const char *type, const char *dst, const char *format, ...) { char text[IRC_MAX_LINE]; va_list params; - - va_start( params, format ); - g_vsnprintf( text, IRC_MAX_LINE, format, params ); - va_end( params ); - - irc_write( iu->irc, ":%s!%s@%s %s %s :%s", - iu->nick, iu->user, iu->host, type, dst, text ); + + va_start(params, format); + g_vsnprintf(text, IRC_MAX_LINE, format, params); + va_end(params); + + irc_write(iu->irc, ":%s!%s@%s %s %s :%s", + iu->nick, iu->user, iu->host, type, dst, text); } -void irc_send_nick( irc_user_t *iu, const char *new ) +void irc_send_nick(irc_user_t *iu, const char *new) { - irc_write( iu->irc, ":%s!%s@%s NICK %s", - iu->nick, iu->user, iu->host, new ); + irc_write(iu->irc, ":%s!%s@%s NICK %s", + iu->nick, iu->user, iu->host, new); } /* Send an update of a user's mode inside a channel, compared to what it was. */ -void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu, - irc_channel_user_flags_t old, irc_channel_user_flags_t new ) +void irc_send_channel_user_mode_diff(irc_channel_t *ic, irc_user_t *iu, + irc_channel_user_flags_t old, irc_channel_user_flags_t new) { - char changes[3*(5+strlen(iu->nick))]; - char from[strlen(ic->irc->root->nick)+strlen(ic->irc->root->user)+strlen(ic->irc->root->host)+3]; + char changes[3 * (5 + strlen(iu->nick))]; + char from[strlen(ic->irc->root->nick) + strlen(ic->irc->root->user) + strlen(ic->irc->root->host) + 3]; int n; - + *changes = '\0'; n = 0; - if( ( old & IRC_CHANNEL_USER_OP ) != ( new & IRC_CHANNEL_USER_OP ) ) - { - n ++; - if( new & IRC_CHANNEL_USER_OP ) - strcat( changes, "+o" ); - else - strcat( changes, "-o" ); + if ((old & IRC_CHANNEL_USER_OP) != (new & IRC_CHANNEL_USER_OP)) { + n++; + if (new & IRC_CHANNEL_USER_OP) { + strcat(changes, "+o"); + } else { + strcat(changes, "-o"); + } } - if( ( old & IRC_CHANNEL_USER_HALFOP ) != ( new & IRC_CHANNEL_USER_HALFOP ) ) - { - n ++; - if( new & IRC_CHANNEL_USER_HALFOP ) - strcat( changes, "+h" ); - else - strcat( changes, "-h" ); + if ((old & IRC_CHANNEL_USER_HALFOP) != (new & IRC_CHANNEL_USER_HALFOP)) { + n++; + if (new & IRC_CHANNEL_USER_HALFOP) { + strcat(changes, "+h"); + } else { + strcat(changes, "-h"); + } + } + if ((old & IRC_CHANNEL_USER_VOICE) != (new & IRC_CHANNEL_USER_VOICE)) { + n++; + if (new & IRC_CHANNEL_USER_VOICE) { + strcat(changes, "+v"); + } else { + strcat(changes, "-v"); + } } - if( ( old & IRC_CHANNEL_USER_VOICE ) != ( new & IRC_CHANNEL_USER_VOICE ) ) - { - n ++; - if( new & IRC_CHANNEL_USER_VOICE ) - strcat( changes, "+v" ); - else - strcat( changes, "-v" ); + while (n) { + strcat(changes, " "); + strcat(changes, iu->nick); + n--; } - while( n ) - { - strcat( changes, " " ); - strcat( changes, iu->nick ); - n --; + + if (set_getbool(&ic->irc->b->set, "simulate_netsplit")) { + g_snprintf(from, sizeof(from), "%s", ic->irc->root->host); + } else { + g_snprintf(from, sizeof(from), "%s!%s@%s", ic->irc->root->nick, + ic->irc->root->user, ic->irc->root->host); + } + + if (*changes) { + irc_write(ic->irc, ":%s MODE %s %s", from, ic->name, changes); } - - if( set_getbool( &ic->irc->b->set, "simulate_netsplit" ) ) - g_snprintf( from, sizeof( from ), "%s", ic->irc->root->host ); - else - g_snprintf( from, sizeof( from ), "%s!%s@%s", ic->irc->root->nick, - ic->irc->root->user, ic->irc->root->host ); - - if( *changes ) - irc_write( ic->irc, ":%s MODE %s %s", from, ic->name, changes ); } -void irc_send_invite( irc_user_t *iu, irc_channel_t *ic ) +void irc_send_invite(irc_user_t *iu, irc_channel_t *ic) { irc_t *irc = iu->irc; - - irc_write( iu->irc, ":%s!%s@%s INVITE %s :%s", - iu->nick, iu->user, iu->host, irc->user->nick, ic->name ); + + irc_write(iu->irc, ":%s!%s@%s INVITE %s :%s", + iu->nick, iu->user, iu->host, irc->user->nick, ic->name); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -26,220 +26,236 @@ #include "bitlbee.h" #include "ipc.h" -irc_user_t *irc_user_new( irc_t *irc, const char *nick ) +irc_user_t *irc_user_new(irc_t *irc, const char *nick) { - irc_user_t *iu = g_new0( irc_user_t, 1 ); - + irc_user_t *iu = g_new0(irc_user_t, 1); + iu->irc = irc; - iu->nick = g_strdup( nick ); + iu->nick = g_strdup(nick); iu->user = iu->host = iu->fullname = iu->nick; - - iu->key = g_strdup( nick ); - nick_lc( irc, iu->key ); + + iu->key = g_strdup(nick); + nick_lc(irc, iu->key); /* Using the hash table for speed and irc->users for easy iteration through the list (since the GLib API doesn't have anything sane for that.) */ - g_hash_table_insert( irc->nick_user_hash, iu->key, iu ); - irc->users = g_slist_insert_sorted( irc->users, iu, irc_user_cmp ); - + g_hash_table_insert(irc->nick_user_hash, iu->key, iu); + irc->users = g_slist_insert_sorted(irc->users, iu, irc_user_cmp); + return iu; } -int irc_user_free( irc_t *irc, irc_user_t *iu ) +int irc_user_free(irc_t *irc, irc_user_t *iu) { static struct im_connection *last_ic; static char *msg; - - if( !iu ) + + if (!iu) { return 0; - - if( iu->bu && - ( iu->bu->ic->flags & OPT_LOGGING_OUT ) && - iu->bu->ic != last_ic ) - { + } + + if (iu->bu && + (iu->bu->ic->flags & OPT_LOGGING_OUT) && + iu->bu->ic != last_ic) { char host_prefix[] = "bitlbee."; char *s; - + /* Irssi recognises netsplits by quitmsgs with two hostnames, where a hostname is a "word" with one of more dots. Mangle no-dot hostnames a bit. */ - if( strchr( irc->root->host, '.' ) ) + if (strchr(irc->root->host, '.')) { *host_prefix = '\0'; - + } + last_ic = iu->bu->ic; - g_free( msg ); - if( !set_getbool( &irc->b->set, "simulate_netsplit" ) ) - msg = g_strdup( "Account off-line" ); - else if( ( s = strchr( iu->bu->ic->acc->user, '@' ) ) ) - msg = g_strdup_printf( "%s%s %s", host_prefix, - irc->root->host, s + 1 ); - else - msg = g_strdup_printf( "%s%s %s.%s", - host_prefix, irc->root->host, - iu->bu->ic->acc->prpl->name, irc->root->host ); - } - else if( !iu->bu || !( iu->bu->ic->flags & OPT_LOGGING_OUT ) ) - { - g_free( msg ); - msg = g_strdup( "Removed" ); + g_free(msg); + if (!set_getbool(&irc->b->set, "simulate_netsplit")) { + msg = g_strdup("Account off-line"); + } else if ((s = strchr(iu->bu->ic->acc->user, '@'))) { + msg = g_strdup_printf("%s%s %s", host_prefix, + irc->root->host, s + 1); + } else { + msg = g_strdup_printf("%s%s %s.%s", + host_prefix, irc->root->host, + iu->bu->ic->acc->prpl->name, irc->root->host); + } + } else if (!iu->bu || !(iu->bu->ic->flags & OPT_LOGGING_OUT)) { + g_free(msg); + msg = g_strdup("Removed"); last_ic = NULL; } - irc_user_quit( iu, msg ); - - irc->users = g_slist_remove( irc->users, iu ); - g_hash_table_remove( irc->nick_user_hash, iu->key ); - - g_free( iu->nick ); - if( iu->nick != iu->user ) g_free( iu->user ); - if( iu->nick != iu->host ) g_free( iu->host ); - if( iu->nick != iu->fullname ) g_free( iu->fullname ); - g_free( iu->pastebuf ); - if( iu->pastebuf_timer ) b_event_remove( iu->pastebuf_timer ); - g_free( iu->key ); - g_free( iu ); - + irc_user_quit(iu, msg); + + irc->users = g_slist_remove(irc->users, iu); + g_hash_table_remove(irc->nick_user_hash, iu->key); + + g_free(iu->nick); + if (iu->nick != iu->user) { + g_free(iu->user); + } + if (iu->nick != iu->host) { + g_free(iu->host); + } + if (iu->nick != iu->fullname) { + g_free(iu->fullname); + } + g_free(iu->pastebuf); + if (iu->pastebuf_timer) { + b_event_remove(iu->pastebuf_timer); + } + g_free(iu->key); + g_free(iu); + return 1; } -irc_user_t *irc_user_by_name( irc_t *irc, const char *nick ) +irc_user_t *irc_user_by_name(irc_t *irc, const char *nick) { - char key[strlen(nick)+1]; - - strcpy( key, nick ); - if( nick_lc( irc, key ) ) - return g_hash_table_lookup( irc->nick_user_hash, key ); - else + char key[strlen(nick) + 1]; + + strcpy(key, nick); + if (nick_lc(irc, key)) { + return g_hash_table_lookup(irc->nick_user_hash, key); + } else { return NULL; + } } -int irc_user_set_nick( irc_user_t *iu, const char *new ) +int irc_user_set_nick(irc_user_t *iu, const char *new) { irc_t *irc = iu->irc; irc_user_t *new_iu; - char key[strlen(new)+1]; + char key[strlen(new) + 1]; GSList *cl; - - strcpy( key, new ); - if( iu == NULL || !nick_lc( irc, key ) || - ( ( new_iu = irc_user_by_name( irc, new ) ) && new_iu != iu ) ) + + strcpy(key, new); + if (iu == NULL || !nick_lc(irc, key) || + ((new_iu = irc_user_by_name(irc, new)) && new_iu != iu)) { return 0; - - for( cl = irc->channels; cl; cl = cl->next ) - { + } + + for (cl = irc->channels; cl; cl = cl->next) { irc_channel_t *ic = cl->data; - + /* Send a NICK update if we're renaming our user, or someone who's in the same channel like our user. */ - if( iu == irc->user || - ( ( ic->flags & IRC_CHANNEL_JOINED ) && - irc_channel_has_user( ic, iu ) ) ) - { - irc_send_nick( iu, new ); + if (iu == irc->user || + ((ic->flags & IRC_CHANNEL_JOINED) && + irc_channel_has_user(ic, iu))) { + irc_send_nick(iu, new); break; } } - - irc->users = g_slist_remove( irc->users, iu ); - g_hash_table_remove( irc->nick_user_hash, iu->key ); - - if( iu->nick == iu->user ) iu->user = NULL; - if( iu->nick == iu->host ) iu->host = NULL; - if( iu->nick == iu->fullname ) iu->fullname = NULL; - g_free( iu->nick ); - iu->nick = g_strdup( new ); - if( iu->user == NULL ) iu->user = g_strdup( iu->nick ); - if( iu->host == NULL ) iu->host = g_strdup( iu->nick ); - if( iu->fullname == NULL ) iu->fullname = g_strdup( iu->nick ); - - g_free( iu->key ); - iu->key = g_strdup( key ); - g_hash_table_insert( irc->nick_user_hash, iu->key, iu ); - irc->users = g_slist_insert_sorted( irc->users, iu, irc_user_cmp ); - - if( iu == irc->user ) - ipc_to_master_str( "NICK :%s\r\n", new ); - + + irc->users = g_slist_remove(irc->users, iu); + g_hash_table_remove(irc->nick_user_hash, iu->key); + + if (iu->nick == iu->user) { + iu->user = NULL; + } + if (iu->nick == iu->host) { + iu->host = NULL; + } + if (iu->nick == iu->fullname) { + iu->fullname = NULL; + } + g_free(iu->nick); + iu->nick = g_strdup(new); + if (iu->user == NULL) { + iu->user = g_strdup(iu->nick); + } + if (iu->host == NULL) { + iu->host = g_strdup(iu->nick); + } + if (iu->fullname == NULL) { + iu->fullname = g_strdup(iu->nick); + } + + g_free(iu->key); + iu->key = g_strdup(key); + g_hash_table_insert(irc->nick_user_hash, iu->key, iu); + irc->users = g_slist_insert_sorted(irc->users, iu, irc_user_cmp); + + if (iu == irc->user) { + ipc_to_master_str("NICK :%s\r\n", new); + } + return 1; } -gint irc_user_cmp( gconstpointer a_, gconstpointer b_ ) +gint irc_user_cmp(gconstpointer a_, gconstpointer b_) { const irc_user_t *a = a_, *b = b_; - - return strcmp( a->key, b->key ); + + return strcmp(a->key, b->key); } -const char *irc_user_get_away( irc_user_t *iu ) +const char *irc_user_get_away(irc_user_t *iu) { irc_t *irc = iu->irc; bee_user_t *bu = iu->bu; - - if( iu == irc->user ) - return set_getstr( &irc->b->set, "away" ); - else if( bu ) - { - if( !bu->flags & BEE_USER_ONLINE ) + + if (iu == irc->user) { + return set_getstr(&irc->b->set, "away"); + } else if (bu) { + if (!bu->flags & BEE_USER_ONLINE) { return "Offline"; - else if( bu->flags & BEE_USER_AWAY ) - { - if( bu->status_msg ) - { + } else if (bu->flags & BEE_USER_AWAY) { + if (bu->status_msg) { static char ret[MAX_STRING]; - g_snprintf( ret, MAX_STRING - 1, "%s (%s)", - bu->status ? : "Away", bu->status_msg ); + g_snprintf(ret, MAX_STRING - 1, "%s (%s)", + bu->status ? : "Away", bu->status_msg); return ret; - } - else + } else { return bu->status ? : "Away"; + } } } - + return NULL; } -void irc_user_quit( irc_user_t *iu, const char *msg ) +void irc_user_quit(irc_user_t *iu, const char *msg) { GSList *l; gboolean send_quit = FALSE; - - if( !iu ) + + if (!iu) { return; - - for( l = iu->irc->channels; l; l = l->next ) - { + } + + for (l = iu->irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - send_quit |= irc_channel_del_user( ic, iu, IRC_CDU_SILENT, NULL ) && - ( ic->flags & IRC_CHANNEL_JOINED ); + send_quit |= irc_channel_del_user(ic, iu, IRC_CDU_SILENT, NULL) && + (ic->flags & IRC_CHANNEL_JOINED); + } + + if (send_quit) { + irc_send_quit(iu, msg); } - - if( send_quit ) - irc_send_quit( iu, msg ); } /* User-type dependent functions, for root/NickServ: */ -static gboolean root_privmsg( irc_user_t *iu, const char *msg ) +static gboolean root_privmsg(irc_user_t *iu, const char *msg) { - char cmd[strlen(msg)+1]; - - strcpy( cmd, msg ); - root_command_string( iu->irc, cmd ); - + char cmd[strlen(msg) + 1]; + + strcpy(cmd, msg); + root_command_string(iu->irc, cmd); + return TRUE; } -static gboolean root_ctcp( irc_user_t *iu, char * const *ctcp ) +static gboolean root_ctcp(irc_user_t *iu, char * const *ctcp) { - if( g_strcasecmp( ctcp[0], "VERSION" ) == 0 ) - { - irc_send_msg_f( iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001", - ctcp[0], PACKAGE " " BITLBEE_VERSION " " ARCH "/" CPU ); + if (g_strcasecmp(ctcp[0], "VERSION") == 0) { + irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001", + ctcp[0], PACKAGE " " BITLBEE_VERSION " " ARCH "/" CPU); + } else if (g_strcasecmp(ctcp[0], "PING") == 0) { + irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001", + ctcp[0], ctcp[1] ? : ""); } - else if( g_strcasecmp( ctcp[0], "PING" ) == 0 ) - { - irc_send_msg_f( iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001", - ctcp[0], ctcp[1] ? : "" ); - } - + return TRUE; } @@ -249,10 +265,10 @@ const struct irc_user_funcs irc_user_root_funcs = { }; /* Echo to yourself: */ -static gboolean self_privmsg( irc_user_t *iu, const char *msg ) +static gboolean self_privmsg(irc_user_t *iu, const char *msg) { - irc_send_msg( iu, "PRIVMSG", iu->nick, msg, NULL ); - + irc_send_msg(iu, "PRIVMSG", iu->nick, msg, NULL); + return TRUE; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -25,91 +25,96 @@ #include "bitlbee.h" -char *set_eval_timezone( set_t *set, char *value ) +char *set_eval_timezone(set_t *set, char *value) { char *s; - - if( strcmp( value, "local" ) == 0 || - strcmp( value, "gmt" ) == 0 || strcmp( value, "utc" ) == 0 ) + + if (strcmp(value, "local") == 0 || + strcmp(value, "gmt") == 0 || strcmp(value, "utc") == 0) { return value; - + } + /* Otherwise: +/- at the beginning optional, then one or more numbers, possibly followed by a colon and more numbers. Don't bother bound- checking them since users are free to shoot themselves in the foot. */ s = value; - if( *s == '+' || *s == '-' ) - s ++; - + if (*s == '+' || *s == '-') { + s++; + } + /* \d+ */ - if( !g_ascii_isdigit( *s ) ) + if (!g_ascii_isdigit(*s)) { return SET_INVALID; - while( *s && g_ascii_isdigit( *s ) ) s ++; - + } + while (*s && g_ascii_isdigit(*s)) { + s++; + } + /* EOS? */ - if( *s == '\0' ) + if (*s == '\0') { return value; - + } + /* Otherwise, colon */ - if( *s != ':' ) + if (*s != ':') { return SET_INVALID; - s ++; - + } + s++; + /* \d+ */ - if( !g_ascii_isdigit( *s ) ) + if (!g_ascii_isdigit(*s)) { return SET_INVALID; - while( *s && g_ascii_isdigit( *s ) ) s ++; - + } + while (*s && g_ascii_isdigit(*s)) { + s++; + } + /* EOS */ return *s == '\0' ? value : SET_INVALID; } -char *irc_format_timestamp( irc_t *irc, time_t msg_ts ) +char *irc_format_timestamp(irc_t *irc, time_t msg_ts) { - time_t now_ts = time( NULL ); + time_t now_ts = time(NULL); struct tm now, msg; char *set; - + /* If the timestamp is <= 0 or less than a minute ago, discard it as it doesn't seem to add to much useful info and/or might be noise. */ - if( msg_ts <= 0 || msg_ts > now_ts - 60 ) + if (msg_ts <= 0 || msg_ts > now_ts - 60) { return NULL; - - set = set_getstr( &irc->b->set, "timezone" ); - if( strcmp( set, "local" ) == 0 ) - { - localtime_r( &now_ts, &now ); - localtime_r( &msg_ts, &msg ); } - else - { + + set = set_getstr(&irc->b->set, "timezone"); + if (strcmp(set, "local") == 0) { + localtime_r(&now_ts, &now); + localtime_r(&msg_ts, &msg); + } else { int hr, min = 0, sign = 60; - - if( set[0] == '-' ) - { + + if (set[0] == '-') { sign *= -1; - set ++; + set++; + } else if (set[0] == '+') { + set++; } - else if( set[0] == '+' ) - { - set ++; - } - - if( sscanf( set, "%d:%d", &hr, &min ) >= 1 ) - { - msg_ts += sign * ( hr * 60 + min ); - now_ts += sign * ( hr * 60 + min ); + + if (sscanf(set, "%d:%d", &hr, &min) >= 1) { + msg_ts += sign * (hr * 60 + min); + now_ts += sign * (hr * 60 + min); } - - gmtime_r( &now_ts, &now ); - gmtime_r( &msg_ts, &msg ); + + gmtime_r(&now_ts, &now); + gmtime_r(&msg_ts, &msg); + } + + if (msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday) { + return g_strdup_printf("\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ", + msg.tm_hour, msg.tm_min, msg.tm_sec); + } else { + return g_strdup_printf("\x02[\x02\x02\x02%04d-%02d-%02d " + "%02d:%02d:%02d\x02]\x02 ", + msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday, + msg.tm_hour, msg.tm_min, msg.tm_sec); } - - if( msg.tm_year == now.tm_year && msg.tm_yday == now.tm_yday ) - return g_strdup_printf( "\x02[\x02\x02\x02%02d:%02d:%02d\x02]\x02 ", - msg.tm_hour, msg.tm_min, msg.tm_sec ); - else - return g_strdup_printf( "\x02[\x02\x02\x02%04d-%02d-%02d " - "%02d:%02d:%02d\x02]\x02 ", - msg.tm_year + 1900, msg.tm_mon + 1, msg.tm_mday, - msg.tm_hour, msg.tm_min, msg.tm_sec ); } @@ -21,20 +21,20 @@ * * \***************************************************************************/ -/* +/* This file implements ArcFour-encryption, which will mainly be used to save IM passwords safely in the new XML-format. Possibly other uses will come up later. It's supposed to be quite reliable (thanks to the use of a 6-byte IV/seed), certainly compared to the old format. The only realistic way to crack BitlBee passwords now is to use a sniffer to get your hands on the user's password. - + If you see that something's wrong in this implementation (I asked a couple of people to look at it already, but who knows), please tell me. - + The reason I picked ArcFour is because it's pretty simple but effective, so it will work without adding several KBs or an extra library dependency. - + (ArcFour is an RC4-compatible cipher. See for details: http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt) */ @@ -56,37 +56,37 @@ many bytes we'll request before we'll really use them for encryption. */ #define ARC_CYCLES 1024 -struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) +struct arc_state *arc_keymaker(unsigned char *key, int kl, int cycles) { struct arc_state *st; int i, j, tmp; unsigned char S2[256]; - - st = g_malloc( sizeof( struct arc_state ) ); + + st = g_malloc(sizeof(struct arc_state)); st->i = st->j = 0; - if( kl <= 0 ) - kl = strlen( (char*) key ); - - for( i = 0; i < 256; i ++ ) - { + if (kl <= 0) { + kl = strlen((char *) key); + } + + for (i = 0; i < 256; i++) { st->S[i] = i; - S2[i] = key[i%kl]; + S2[i] = key[i % kl]; } - - for( i = j = 0; i < 256; i ++ ) - { - j = ( j + st->S[i] + S2[i] ) & 0xff; + + for (i = j = 0; i < 256; i++) { + j = (j + st->S[i] + S2[i]) & 0xff; tmp = st->S[i]; st->S[i] = st->S[j]; st->S[j] = tmp; } - - memset( S2, 0, 256 ); + + memset(S2, 0, 256); i = j = 0; - - for( i = 0; i < cycles; i ++ ) - arc_getbyte( st ); - + + for (i = 0; i < cycles; i++) { + arc_getbyte(st); + } + return st; } @@ -95,23 +95,23 @@ struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) a stream of bytes after you give it a key. Just get a byte from it and xor it with your cleartext. To decrypt, just give it the same key again and start xorring. - + The function above initializes the byte generator, the next function can be used to get bytes from the generator (and shuffle things a bit). */ -unsigned char arc_getbyte( struct arc_state *st ) +unsigned char arc_getbyte(struct arc_state *st) { unsigned char tmp; - + /* Unfortunately the st-> stuff doesn't really improve readability here... */ - st->i ++; + st->i++; st->j += st->S[st->i]; tmp = st->S[st->i]; st->S[st->i] = st->S[st->j]; st->S[st->j] = tmp; tmp = (st->S[st->i] + st->S[st->j]) & 0xff; - + return st->S[tmp]; } @@ -121,103 +121,105 @@ unsigned char arc_getbyte( struct arc_state *st ) by default) random bytes to the password before setting up the state structures. These 6 bytes are also saved in the results, because of course we'll need them in arc_decode(). - + Because the length of the resulting string is unknown to the caller, it should pass a char**. Since the encode/decode functions allocate memory for the string, make sure the char** points at a NULL-pointer (or at least to something you already free()d), or you'll leak memory. And of course, don't forget to free() the result when you don't need it anymore. - + Both functions return the number of bytes in the result string. - + Note that if you use the pad_to argument, you will need zero-termi- nation to find back the original string length after decryption. So it shouldn't be used if your string contains \0s by itself! */ -int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ) +int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to) { struct arc_state *st; unsigned char *key; char *padded = NULL; int key_len, i, padded_len; - - key_len = strlen( password ) + ARC_IV_LEN; - if( clear_len <= 0 ) - clear_len = strlen( clear ); - + + key_len = strlen(password) + ARC_IV_LEN; + if (clear_len <= 0) { + clear_len = strlen(clear); + } + /* Pad the string to the closest multiple of pad_to. This makes it impossible to see the exact length of the password. */ - if( pad_to > 0 && ( clear_len % pad_to ) > 0 ) - { - padded_len = clear_len + pad_to - ( clear_len % pad_to ); - padded = g_malloc( padded_len ); - memcpy( padded, clear, clear_len ); - + if (pad_to > 0 && (clear_len % pad_to) > 0) { + padded_len = clear_len + pad_to - (clear_len % pad_to); + padded = g_malloc(padded_len); + memcpy(padded, clear, clear_len); + /* First a \0 and then random data, so we don't have to do anything special when decrypting. */ padded[clear_len] = 0; - random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 ); - + random_bytes((unsigned char *) padded + clear_len + 1, padded_len - clear_len - 1); + clear = padded; clear_len = padded_len; } - + /* Prepare buffers and the key + IV */ - *crypt = g_malloc( clear_len + ARC_IV_LEN ); - key = g_malloc( key_len ); - strcpy( (char*) key, password ); - + *crypt = g_malloc(clear_len + ARC_IV_LEN); + key = g_malloc(key_len); + strcpy((char *) key, password); + /* Add the salt. Save it for later (when decrypting) and, of course, add it to the encryption key. */ - random_bytes( crypt[0], ARC_IV_LEN ); - memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN ); - + random_bytes(crypt[0], ARC_IV_LEN); + memcpy(key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN); + /* Generate the initial S[] from the IVed key. */ - st = arc_keymaker( key, key_len, ARC_CYCLES ); - g_free( key ); - - for( i = 0; i < clear_len; i ++ ) - crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st ); - - g_free( st ); - g_free( padded ); - + st = arc_keymaker(key, key_len, ARC_CYCLES); + g_free(key); + + for (i = 0; i < clear_len; i++) { + crypt[0][i + ARC_IV_LEN] = clear[i] ^ arc_getbyte(st); + } + + g_free(st); + g_free(padded); + return clear_len + ARC_IV_LEN; } -int arc_decode( unsigned char *crypt, int crypt_len, char **clear, const char *password ) +int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password) { struct arc_state *st; unsigned char *key; int key_len, clear_len, i; - - key_len = strlen( password ) + ARC_IV_LEN; + + key_len = strlen(password) + ARC_IV_LEN; clear_len = crypt_len - ARC_IV_LEN; - - if( clear_len < 0 ) - { - *clear = g_strdup( "" ); + + if (clear_len < 0) { + *clear = g_strdup(""); return -1; } - + /* Prepare buffers and the key + IV */ - *clear = g_malloc( clear_len + 1 ); - key = g_malloc( key_len ); - strcpy( (char*) key, password ); - for( i = 0; i < ARC_IV_LEN; i ++ ) - key[key_len-ARC_IV_LEN+i] = crypt[i]; - + *clear = g_malloc(clear_len + 1); + key = g_malloc(key_len); + strcpy((char *) key, password); + for (i = 0; i < ARC_IV_LEN; i++) { + key[key_len - ARC_IV_LEN + i] = crypt[i]; + } + /* Generate the initial S[] from the IVed key. */ - st = arc_keymaker( key, key_len, ARC_CYCLES ); - g_free( key ); - - for( i = 0; i < clear_len; i ++ ) - clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st ); + st = arc_keymaker(key, key_len, ARC_CYCLES); + g_free(key); + + for (i = 0; i < clear_len; i++) { + clear[0][i] = crypt[i + ARC_IV_LEN] ^ arc_getbyte(st); + } clear[0][i] = 0; /* Nice to have for plaintexts. */ - - g_free( st ); - + + g_free(st); + return clear_len; } @@ -24,8 +24,7 @@ /* See arc.c for more information. */ -struct arc_state -{ +struct arc_state { unsigned char S[256]; unsigned char i, j; }; @@ -34,7 +33,7 @@ struct arc_state #define G_GNUC_MALLOC #endif -G_GNUC_MALLOC struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ); -unsigned char arc_getbyte( struct arc_state *st ); -int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ); -int arc_decode( unsigned char *crypt, int crypt_len, char **clear, const char *password ); +G_GNUC_MALLOC struct arc_state *arc_keymaker(unsigned char *key, int kl, int cycles); +unsigned char arc_getbyte(struct arc_state *st); +int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to); +int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password); diff --git a/lib/base64.c b/lib/base64.c index 884f00c0..0c36153f 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -28,7 +28,7 @@ char *tobase64(const char *text) { - return base64_encode((const unsigned char *)text, strlen(text)); + return base64_encode((const unsigned char *) text, strlen(text)); } char *base64_encode(const unsigned char *in, int len) @@ -41,13 +41,15 @@ char *base64_encode(const unsigned char *in, int len) char *frombase64(const char *in) { unsigned char *out; + base64_decode(in, &out); - return (char*) out; + return (char *) out; } int base64_decode(const char *in, unsigned char **out) { gsize len; + *out = g_base64_decode(in, &len); /* Some silly functions expect it to be zero terminated */ diff --git a/lib/base64.h b/lib/base64.h index dc199c55..233e07b9 100644 --- a/lib/base64.h +++ b/lib/base64.h @@ -25,7 +25,7 @@ #include <glib.h> #include <gmodule.h> -G_MODULE_EXPORT char *tobase64( const char *text ); -G_MODULE_EXPORT char *base64_encode( const unsigned char *in, int len ); -G_MODULE_EXPORT char *frombase64( const char *in ); -G_MODULE_EXPORT int base64_decode( const char *in, unsigned char **out ); +G_MODULE_EXPORT char *tobase64(const char *text); +G_MODULE_EXPORT char *base64_encode(const unsigned char *in, int len); +G_MODULE_EXPORT char *frombase64(const char *in); +G_MODULE_EXPORT int base64_decode(const char *in, unsigned char **out); diff --git a/lib/events.h b/lib/events.h index 0446aa0f..193065f9 100644 --- a/lib/events.h +++ b/lib/events.h @@ -25,7 +25,7 @@ ground and calls a callback function once the connection is ready to use. This function (proxy_connect()) can be found in proxy.c. (It also transparently handles HTTP/SOCKS proxies, when necessary.) - + This file offers some extra event handling toys, which will be handled by GLib or libevent. The advantage of using libevent is that it can use more advanced I/O polling functions like epoll() in recent Linux @@ -46,9 +46,9 @@ the given callback function. */ typedef enum { B_EV_IO_READ = 1 << 0, - B_EV_IO_WRITE = 1 << 1, - B_EV_FLAG_FORCE_ONCE = 1 << 16, - B_EV_FLAG_FORCE_REPEAT = 1 << 17, + B_EV_IO_WRITE = 1 << 1, + B_EV_FLAG_FORCE_ONCE = 1 << 16, + B_EV_FLAG_FORCE_REPEAT = 1 << 17, } b_input_condition; typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition cond); @@ -58,7 +58,7 @@ typedef gboolean (*b_event_handler)(gpointer data, gint fd, b_input_condition co #define GAIM_ERR_COND (G_IO_HUP | G_IO_ERR | G_IO_NVAL) /* #define event_debug( x... ) printf( x ) */ -#define event_debug( x... ) +#define event_debug(x ...) /* Call this once when the program starts. It'll initialize the event handler library (if necessary) and then return immediately. */ diff --git a/lib/events_glib.c b/lib/events_glib.c index c6bb3d9e..404031e8 100644 --- a/lib/events_glib.c +++ b/lib/events_glib.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2006 Wilmer van der Gaast and others * @@ -49,18 +49,19 @@ static GMainLoop *loop = NULL; void b_main_init() { - if( loop == NULL ) - loop = g_main_new( FALSE ); + if (loop == NULL) { + loop = g_main_new(FALSE); + } } void b_main_run() { - g_main_run( loop ); + g_main_run(loop); } void b_main_quit() { - g_main_quit( loop ); + g_main_quit(loop); } static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) @@ -68,33 +69,38 @@ static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpoin GaimIOClosure *closure = data; b_input_condition gaim_cond = 0; gboolean st; - - if (condition & G_IO_NVAL) + + if (condition & G_IO_NVAL) { return FALSE; + } - if (condition & GAIM_READ_COND) + if (condition & GAIM_READ_COND) { gaim_cond |= B_EV_IO_READ; - if (condition & GAIM_WRITE_COND) + } + if (condition & GAIM_WRITE_COND) { gaim_cond |= B_EV_IO_WRITE; - - event_debug( "gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data ); + } + + event_debug("gaim_io_invoke( %d, %d, 0x%x )\n", g_io_channel_unix_get_fd(source), condition, data); st = closure->function(closure->data, g_io_channel_unix_get_fd(source), gaim_cond); - - if( !st ) - event_debug( "Returned FALSE, cancelling.\n" ); - - if (closure->flags & B_EV_FLAG_FORCE_ONCE) + + if (!st) { + event_debug("Returned FALSE, cancelling.\n"); + } + + if (closure->flags & B_EV_FLAG_FORCE_ONCE) { return FALSE; - else if (closure->flags & B_EV_FLAG_FORCE_REPEAT) + } else if (closure->flags & B_EV_FLAG_FORCE_REPEAT) { return TRUE; - else + } else { return st; + } } static void gaim_io_destroy(gpointer data) { - event_debug( "gaim_io_destroy( 0x%x )\n", data ); + event_debug("gaim_io_destroy( 0x%x )\n", data); g_free(data); } @@ -104,22 +110,24 @@ gint b_input_add(gint source, b_input_condition condition, b_event_handler funct GIOChannel *channel; GIOCondition cond = 0; int st; - + closure->function = function; closure->data = data; closure->flags = condition; - - if (condition & B_EV_IO_READ) + + if (condition & B_EV_IO_READ) { cond |= GAIM_READ_COND; - if (condition & B_EV_IO_WRITE) + } + if (condition & B_EV_IO_WRITE) { cond |= GAIM_WRITE_COND; - + } + channel = g_io_channel_unix_new(source); st = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, gaim_io_invoke, closure, gaim_io_destroy); - - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) = %d (%p)\n", source, condition, function, data, st, closure ); - + + event_debug("b_input_add( %d, %d, 0x%x, 0x%x ) = %d (%p)\n", source, condition, function, data, st, closure); + g_io_channel_unref(channel); return st; } @@ -130,21 +138,22 @@ gint b_timeout_add(gint timeout, b_event_handler func, gpointer data) really the same, but they're "compatible". ;-) It will do for now, BitlBee only looks at the "data" argument. */ gint st = g_timeout_add(timeout, (GSourceFunc) func, data); - - event_debug( "b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st ); - + + event_debug("b_timeout_add( %d, %d, %d ) = %d\n", timeout, func, data, st); + return st; } void b_event_remove(gint tag) { - event_debug( "b_event_remove( %d )\n", tag ); - - if (tag > 0) + event_debug("b_event_remove( %d )\n", tag); + + if (tag > 0) { g_source_remove(tag); + } } -void closesocket( int fd ) +void closesocket(int fd) { - close( fd ); + close(fd); } diff --git a/lib/events_libevent.c b/lib/events_libevent.c index cf4eee8f..854af010 100644 --- a/lib/events_libevent.c +++ b/lib/events_libevent.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2006 Wilmer van der Gaast and others * @@ -52,8 +52,7 @@ static GHashTable *write_hash; struct event_base *leh; struct event_base *old_leh; -struct b_event_data -{ +struct b_event_data { guint id; struct event evinfo; gint timeout; @@ -64,47 +63,44 @@ struct b_event_data void b_main_init() { - if( leh != NULL ) - { + if (leh != NULL) { /* Clean up the hash tables? */ - + b_main_restart(); old_leh = leh; } - + leh = event_init(); - - id_hash = g_hash_table_new( g_int_hash, g_int_equal ); - read_hash = g_hash_table_new( g_int_hash, g_int_equal ); - write_hash = g_hash_table_new( g_int_hash, g_int_equal ); + + id_hash = g_hash_table_new(g_int_hash, g_int_equal); + read_hash = g_hash_table_new(g_int_hash, g_int_equal); + write_hash = g_hash_table_new(g_int_hash, g_int_equal); } void b_main_run() { /* This while loop is necessary to exit the event loop and start a different one (necessary for ForkDaemon mode). */ - while( event_base_dispatch( leh ) == 0 && !quitting ) - { - if( old_leh != NULL ) - { + while (event_base_dispatch(leh) == 0 && !quitting) { + if (old_leh != NULL) { /* For some reason this just isn't allowed... Possibly a bug in older versions, will see later. event_base_free( old_leh ); */ old_leh = NULL; } - - event_debug( "New event loop.\n" ); + + event_debug("New event loop.\n"); } } static void b_main_restart() { struct timeval tv; - - memset( &tv, 0, sizeof( struct timeval ) ); - event_base_loopexit( leh, &tv ); - - event_debug( "b_main_restart()\n" ); + + memset(&tv, 0, sizeof(struct timeval)); + event_base_loopexit(leh, &tv); + + event_debug("b_main_restart()\n"); } void b_main_quit() @@ -113,182 +109,175 @@ void b_main_quit() libevent sometimes generates events before really quitting, we want to stop them. */ quitting = 1; - + b_main_restart(); } -static void b_event_passthrough( int fd, short event, void *data ) +static void b_event_passthrough(int fd, short event, void *data) { struct b_event_data *b_ev = data; b_input_condition cond = 0; gboolean st; - - if( fd >= 0 ) - { - if( event & EV_READ ) + + if (fd >= 0) { + if (event & EV_READ) { cond |= B_EV_IO_READ; - if( event & EV_WRITE ) + } + if (event & EV_WRITE) { cond |= B_EV_IO_WRITE; + } } - - event_debug( "b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id ); - + + event_debug("b_event_passthrough( %d, %d, 0x%x ) (%d)\n", fd, event, (int) data, b_ev->id); + /* Since the called function might cancel this handler already (which free()s b_ev), we have to remember the ID here. */ id_cur = b_ev->id; id_dead = 0; - - if( quitting ) - { - b_event_remove( id_cur ); + + if (quitting) { + b_event_remove(id_cur); return; } - - st = b_ev->function( b_ev->data, fd, cond ); - if( id_dead ) - { + + st = b_ev->function(b_ev->data, fd, cond); + if (id_dead) { /* This event was killed already, don't touch it! */ return; - } - else if( !st && !( b_ev->flags & B_EV_FLAG_FORCE_REPEAT ) ) - { - event_debug( "Handler returned FALSE: " ); - b_event_remove( id_cur ); - } - else if( fd == -1 ) - { + } else if (!st && !(b_ev->flags & B_EV_FLAG_FORCE_REPEAT)) { + event_debug("Handler returned FALSE: "); + b_event_remove(id_cur); + } else if (fd == -1) { /* fd == -1 means it was a timer. These can't be auto-repeated so it has to be recreated every time. */ struct timeval tv; - + tv.tv_sec = b_ev->timeout / 1000; - tv.tv_usec = ( b_ev->timeout % 1000 ) * 1000; - - evtimer_add( &b_ev->evinfo, &tv ); + tv.tv_usec = (b_ev->timeout % 1000) * 1000; + + evtimer_add(&b_ev->evinfo, &tv); } } -gint b_input_add( gint fd, b_input_condition condition, b_event_handler function, gpointer data ) +gint b_input_add(gint fd, b_input_condition condition, b_event_handler function, gpointer data) { struct b_event_data *b_ev; - - event_debug( "b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data ); - - if( ( condition & B_EV_IO_READ && ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) || - ( condition & B_EV_IO_WRITE && ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) ) - { + + event_debug("b_input_add( %d, %d, 0x%x, 0x%x ) ", fd, condition, function, data); + + if ((condition & B_EV_IO_READ && (b_ev = g_hash_table_lookup(read_hash, &fd))) || + (condition & B_EV_IO_WRITE && (b_ev = g_hash_table_lookup(write_hash, &fd)))) { /* We'll stick with this libevent entry, but give it a new BitlBee id. */ - g_hash_table_remove( id_hash, &b_ev->id ); - - event_debug( "(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next ); - + g_hash_table_remove(id_hash, &b_ev->id); + + event_debug("(replacing old handler (id = %d)) = %d\n", b_ev->id, id_next); + b_ev->id = id_next++; b_ev->function = function; b_ev->data = data; - } - else - { + } else { GIOCondition out_cond; - - event_debug( "(new) = %d\n", id_next ); - - b_ev = g_new0( struct b_event_data, 1 ); + + event_debug("(new) = %d\n", id_next); + + b_ev = g_new0(struct b_event_data, 1); b_ev->id = id_next++; b_ev->function = function; b_ev->data = data; - + out_cond = EV_PERSIST; - if( condition & B_EV_IO_READ ) + if (condition & B_EV_IO_READ) { out_cond |= EV_READ; - if( condition & B_EV_IO_WRITE ) + } + if (condition & B_EV_IO_WRITE) { out_cond |= EV_WRITE; - - event_set( &b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev ); - event_add( &b_ev->evinfo, NULL ); - - if( out_cond & EV_READ ) - g_hash_table_insert( read_hash, &b_ev->evinfo.ev_fd, b_ev ); - if( out_cond & EV_WRITE ) - g_hash_table_insert( write_hash, &b_ev->evinfo.ev_fd, b_ev ); + } + + event_set(&b_ev->evinfo, fd, out_cond, b_event_passthrough, b_ev); + event_add(&b_ev->evinfo, NULL); + + if (out_cond & EV_READ) { + g_hash_table_insert(read_hash, &b_ev->evinfo.ev_fd, b_ev); + } + if (out_cond & EV_WRITE) { + g_hash_table_insert(write_hash, &b_ev->evinfo.ev_fd, b_ev); + } } - + b_ev->flags = condition; - g_hash_table_insert( id_hash, &b_ev->id, b_ev ); + g_hash_table_insert(id_hash, &b_ev->id, b_ev); return b_ev->id; } /* TODO: Persistence for timers! */ -gint b_timeout_add( gint timeout, b_event_handler function, gpointer data ) +gint b_timeout_add(gint timeout, b_event_handler function, gpointer data) { - struct b_event_data *b_ev = g_new0( struct b_event_data, 1 ); + struct b_event_data *b_ev = g_new0(struct b_event_data, 1); struct timeval tv; - + b_ev->id = id_next++; b_ev->timeout = timeout; b_ev->function = function; b_ev->data = data; - + tv.tv_sec = timeout / 1000; - tv.tv_usec = ( timeout % 1000 ) * 1000; - - evtimer_set( &b_ev->evinfo, b_event_passthrough, b_ev ); - evtimer_add( &b_ev->evinfo, &tv ); - - event_debug( "b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id ); - - g_hash_table_insert( id_hash, &b_ev->id, b_ev ); - + tv.tv_usec = (timeout % 1000) * 1000; + + evtimer_set(&b_ev->evinfo, b_event_passthrough, b_ev); + evtimer_add(&b_ev->evinfo, &tv); + + event_debug("b_timeout_add( %d, 0x%x, 0x%x ) = %d\n", timeout, function, data, b_ev->id); + + g_hash_table_insert(id_hash, &b_ev->id, b_ev); + return b_ev->id; } -void b_event_remove( gint id ) +void b_event_remove(gint id) { - struct b_event_data *b_ev = g_hash_table_lookup( id_hash, &id ); - - event_debug( "b_event_remove( %d )\n", id ); - if( b_ev ) - { - if( id == id_cur ) + struct b_event_data *b_ev = g_hash_table_lookup(id_hash, &id); + + event_debug("b_event_remove( %d )\n", id); + if (b_ev) { + if (id == id_cur) { id_dead = TRUE; - - g_hash_table_remove( id_hash, &b_ev->id ); - if( b_ev->evinfo.ev_fd >= 0 ) - { - if( b_ev->evinfo.ev_events & EV_READ ) - g_hash_table_remove( read_hash, &b_ev->evinfo.ev_fd ); - if( b_ev->evinfo.ev_events & EV_WRITE ) - g_hash_table_remove( write_hash, &b_ev->evinfo.ev_fd ); } - - event_del( &b_ev->evinfo ); - g_free( b_ev ); - } - else - { - event_debug( "Already removed?\n" ); + + g_hash_table_remove(id_hash, &b_ev->id); + if (b_ev->evinfo.ev_fd >= 0) { + if (b_ev->evinfo.ev_events & EV_READ) { + g_hash_table_remove(read_hash, &b_ev->evinfo.ev_fd); + } + if (b_ev->evinfo.ev_events & EV_WRITE) { + g_hash_table_remove(write_hash, &b_ev->evinfo.ev_fd); + } + } + + event_del(&b_ev->evinfo); + g_free(b_ev); + } else { + event_debug("Already removed?\n"); } } -void closesocket( int fd ) +void closesocket(int fd) { struct b_event_data *b_ev; - + /* Since epoll() (the main reason we use libevent) automatically removes sockets from the epoll() list when a socket gets closed and some modules have a habit of closing sockets before removing event handlers, our and libevent's administration get a little bit messed up. So this little function will remove the handlers properly before closing a socket. */ - - if( ( b_ev = g_hash_table_lookup( read_hash, &fd ) ) ) - { - event_debug( "Warning: fd %d still had a read event handler when shutting down.\n", fd ); - b_event_remove( b_ev->id ); + + if ((b_ev = g_hash_table_lookup(read_hash, &fd))) { + event_debug("Warning: fd %d still had a read event handler when shutting down.\n", fd); + b_event_remove(b_ev->id); } - if( ( b_ev = g_hash_table_lookup( write_hash, &fd ) ) ) - { - event_debug( "Warning: fd %d still had a write event handler when shutting down.\n", fd ); - b_event_remove( b_ev->id ); + if ((b_ev = g_hash_table_lookup(write_hash, &fd))) { + event_debug("Warning: fd %d still had a write event handler when shutting down.\n", fd); + b_event_remove(b_ev->id); } - - close( fd ); + + close(fd); } diff --git a/lib/ftutil.c b/lib/ftutil.c index 3b29d2f4..7606890f 100644 --- a/lib/ftutil.c +++ b/lib/ftutil.c @@ -28,117 +28,107 @@ #include "lib/ftutil.h" #define ASSERTSOCKOP(op, msg) \ - if( (op) == -1 ) {\ - g_snprintf( errmsg, sizeof( errmsg ), msg ": %s", strerror( errno ) ); \ + if ((op) == -1) { \ + g_snprintf(errmsg, sizeof(errmsg), msg ": %s", strerror(errno)); \ return -1; } /* * Creates a listening socket and returns it in saddr_ptr. */ -int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr ) +int ft_listen(struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, + char **errptr) { int fd, gret, saddrlen; struct addrinfo hints, *rp; - socklen_t ssize = sizeof( struct sockaddr_storage ); + socklen_t ssize = sizeof(struct sockaddr_storage); struct sockaddr_storage saddrs, *saddr = &saddrs; static char errmsg[1024]; char *ftlisten = global.conf->ft_listen; - if( errptr ) + if (errptr) { *errptr = errmsg; + } - strcpy( port, "0" ); + strcpy(port, "0"); /* Format is <IP-A>[:<Port-A>];<IP-B>[:<Port-B>] where * A is for connections with the bitlbee client (DCC) * and B is for connections with IM peers. */ - if( ftlisten ) - { - char *scolon = strchr( ftlisten, ';' ); + if (ftlisten) { + char *scolon = strchr(ftlisten, ';'); char *colon; - if( scolon ) - { - if( for_bitlbee_client ) - { + if (scolon) { + if (for_bitlbee_client) { *scolon = '\0'; - strncpy( host, ftlisten, HOST_NAME_MAX ); + strncpy(host, ftlisten, HOST_NAME_MAX); *scolon = ';'; + } else { + strncpy(host, scolon + 1, HOST_NAME_MAX); } - else - { - strncpy( host, scolon + 1, HOST_NAME_MAX ); - } - } - else - { - strncpy( host, ftlisten, HOST_NAME_MAX ); + } else { + strncpy(host, ftlisten, HOST_NAME_MAX); } - if( ( colon = strchr( host, ':' ) ) ) - { + if ((colon = strchr(host, ':'))) { *colon = '\0'; - strncpy( port, colon + 1, 5 ); + strncpy(port, colon + 1, 5); } - } - else if( copy_fd >= 0 && getsockname( copy_fd, (struct sockaddr*) &saddrs, &ssize ) == 0 && - ( saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6 ) && - getnameinfo( (struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX, - NULL, 0, NI_NUMERICHOST ) == 0 ) - { + } else if (copy_fd >= 0 && getsockname(copy_fd, (struct sockaddr*) &saddrs, &ssize) == 0 && + (saddrs.ss_family == AF_INET || saddrs.ss_family == AF_INET6) && + getnameinfo((struct sockaddr*) &saddrs, ssize, host, HOST_NAME_MAX, + NULL, 0, NI_NUMERICHOST) == 0) { /* We just took our local address on copy_fd, which is likely to be a sensible address from which we can do a file transfer now - the most sensible we can get easily. */ - } - else - { - ASSERTSOCKOP( gethostname( host, HOST_NAME_MAX + 1 ), "gethostname()" ); + } else { + ASSERTSOCKOP(gethostname(host, HOST_NAME_MAX + 1), "gethostname()"); } - memset( &hints, 0, sizeof( struct addrinfo ) ); + memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICSERV; - if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) != 0 ) - { - sprintf( errmsg, "getaddrinfo() failed: %s", gai_strerror( gret ) ); + if ((gret = getaddrinfo(host, port, &hints, &rp)) != 0) { + sprintf(errmsg, "getaddrinfo() failed: %s", gai_strerror(gret)); return -1; } saddrlen = rp->ai_addrlen; - memcpy( saddr, rp->ai_addr, saddrlen ); + memcpy(saddr, rp->ai_addr, saddrlen); - freeaddrinfo( rp ); + freeaddrinfo(rp); - ASSERTSOCKOP( fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" ); - ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, saddrlen ), "Binding socket" ); - ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" ); + ASSERTSOCKOP(fd = socket(saddr->ss_family, SOCK_STREAM, 0), "Opening socket"); + ASSERTSOCKOP(bind(fd, ( struct sockaddr *) saddr, saddrlen), "Binding socket"); + ASSERTSOCKOP(listen(fd, 1), "Making socket listen"); - if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ? - ( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr : - ( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr, - host, HOST_NAME_MAX ) ) - { - strcpy( errmsg, "inet_ntop failed on listening socket" ); + if (!inet_ntop(saddr->ss_family, saddr->ss_family == AF_INET ? + ( void * ) &(( struct sockaddr_in * ) saddr)->sin_addr.s_addr : + ( void * ) &(( struct sockaddr_in6 * ) saddr)->sin6_addr.s6_addr, + host, HOST_NAME_MAX)) { + strcpy(errmsg, "inet_ntop failed on listening socket"); return -1; } - ssize = sizeof( struct sockaddr_storage ); - ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" ); + ssize = sizeof(struct sockaddr_storage); + ASSERTSOCKOP(getsockname(fd, ( struct sockaddr *) saddr, &ssize), "Getting socket name"); - if( saddr->ss_family == AF_INET ) - g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in *) saddr )->sin_port ) ); - else - g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in6 *) saddr )->sin6_port ) ); + if (saddr->ss_family == AF_INET) { + g_snprintf(port, 6, "%d", ntohs(((struct sockaddr_in *) saddr)->sin_port)); + } else { + g_snprintf(port, 6, "%d", ntohs(((struct sockaddr_in6 *) saddr)->sin6_port)); + } - if( saddr_ptr ) - memcpy( saddr_ptr, saddr, saddrlen ); + if (saddr_ptr) { + memcpy(saddr_ptr, saddr, saddrlen); + } /* I hate static-length strings.. */ - host[HOST_NAME_MAX-1] = '\0'; + host[HOST_NAME_MAX - 1] = '\0'; port[5] = '\0'; - + return fd; } diff --git a/lib/ftutil.h b/lib/ftutil.h index 09c1104e..d8317b2f 100644 --- a/lib/ftutil.h +++ b/lib/ftutil.h @@ -37,4 +37,5 @@ /* This function should be used with care. host should be AT LEAST a char[HOST_NAME_MAX+1] and port AT LEAST a char[6]. */ -int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, char **errptr ); +int ft_listen(struct sockaddr_storage *saddr_ptr, char *host, char *port, int copy_fd, int for_bitlbee_client, + char **errptr); diff --git a/lib/http_client.c b/lib/http_client.c index 2481997a..1dc5947a 100644 --- a/lib/http_client.c +++ b/lib/http_client.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -31,165 +31,159 @@ #include "sock.h" -static gboolean http_connected( gpointer data, int source, b_input_condition cond ); -static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ); -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ); -static void http_free( struct http_request *req ); +static gboolean http_connected(gpointer data, int source, b_input_condition cond); +static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond); +static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond); +static void http_free(struct http_request *req); -struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ) +struct http_request *http_dorequest(char *host, int port, int ssl, char *request, http_input_function func, + gpointer data) { struct http_request *req; int error = 0; - - req = g_new0( struct http_request, 1 ); - - if( ssl ) - { - req->ssl = ssl_connect( host, port, TRUE, http_ssl_connected, req ); - if( req->ssl == NULL ) + + req = g_new0(struct http_request, 1); + + if (ssl) { + req->ssl = ssl_connect(host, port, TRUE, http_ssl_connected, req); + if (req->ssl == NULL) { error = 1; - } - else - { - req->fd = proxy_connect( host, port, http_connected, req ); - if( req->fd < 0 ) + } + } else { + req->fd = proxy_connect(host, port, http_connected, req); + if (req->fd < 0) { error = 1; + } } - - if( error ) - { - http_free( req ); + + if (error) { + http_free(req); return NULL; } - + req->func = func; req->data = data; - req->request = g_strdup( request ); - req->request_length = strlen( request ); + req->request = g_strdup(request); + req->request_length = strlen(request); req->redir_ttl = 3; req->content_length = -1; - - if( getenv( "BITLBEE_DEBUG" ) ) - printf( "About to send HTTP request:\n%s\n", req->request ); - + + if (getenv("BITLBEE_DEBUG")) { + printf("About to send HTTP request:\n%s\n", req->request); + } + return req; } -struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data ) +struct http_request *http_dorequest_url(char *url_string, http_input_function func, gpointer data) { - url_t *url = g_new0( url_t, 1 ); + url_t *url = g_new0(url_t, 1); char *request; void *ret; - - if( !url_set( url, url_string ) ) - { - g_free( url ); + + if (!url_set(url, url_string)) { + g_free(url); return NULL; } - - if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS ) - { - g_free( url ); + + if (url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS) { + g_free(url); return NULL; } - - request = g_strdup_printf( "GET %s HTTP/1.0\r\n" - "Host: %s\r\n" - "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" - "\r\n", url->file, url->host ); - - ret = http_dorequest( url->host, url->port, - url->proto == PROTO_HTTPS, request, func, data ); - - g_free( url ); - g_free( request ); + + request = g_strdup_printf("GET %s HTTP/1.0\r\n" + "Host: %s\r\n" + "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n" + "\r\n", url->file, url->host); + + ret = http_dorequest(url->host, url->port, + url->proto == PROTO_HTTPS, request, func, data); + + g_free(url); + g_free(request); return ret; } -/* This one is actually pretty simple... Might get more calls if we can't write +/* This one is actually pretty simple... Might get more calls if we can't write the whole request at once. */ -static gboolean http_connected( gpointer data, int source, b_input_condition cond ) +static gboolean http_connected(gpointer data, int source, b_input_condition cond) { struct http_request *req = data; int st; - - if( source < 0 ) + + if (source < 0) { goto error; - - if( req->inpa > 0 ) - b_event_remove( req->inpa ); - - sock_make_nonblocking( req->fd ); - - if( req->ssl ) - { - st = ssl_write( req->ssl, req->request + req->bytes_written, - req->request_length - req->bytes_written ); - if( st < 0 ) - { - if( ssl_errno != SSL_AGAIN ) - { - ssl_disconnect( req->ssl ); + } + + if (req->inpa > 0) { + b_event_remove(req->inpa); + } + + sock_make_nonblocking(req->fd); + + if (req->ssl) { + st = ssl_write(req->ssl, req->request + req->bytes_written, + req->request_length - req->bytes_written); + if (st < 0) { + if (ssl_errno != SSL_AGAIN) { + ssl_disconnect(req->ssl); goto error; } } - } - else - { - st = write( source, req->request + req->bytes_written, - req->request_length - req->bytes_written ); - if( st < 0 ) - { - if( !sockerr_again() ) - { - closesocket( req->fd ); + } else { + st = write(source, req->request + req->bytes_written, + req->request_length - req->bytes_written); + if (st < 0) { + if (!sockerr_again()) { + closesocket(req->fd); goto error; } } } - - if( st > 0 ) + + if (st > 0) { req->bytes_written += st; - - if( req->bytes_written < req->request_length ) - req->inpa = b_input_add( source, - req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE, - http_connected, req ); - else - req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req ); - + } + + if (req->bytes_written < req->request_length) { + req->inpa = b_input_add(source, + req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_WRITE, + http_connected, req); + } else { + req->inpa = b_input_add(source, B_EV_IO_READ, http_incoming_data, req); + } + return FALSE; - + error: - if( req->status_string == NULL ) - req->status_string = g_strdup( "Error while writing HTTP request" ); - - req->func( req ); - http_free( req ); + if (req->status_string == NULL) { + req->status_string = g_strdup("Error while writing HTTP request"); + } + + req->func(req); + http_free(req); return FALSE; } -static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond ) +static gboolean http_ssl_connected(gpointer data, int returncode, void *source, b_input_condition cond) { struct http_request *req = data; - - if( source == NULL ) - { - if( returncode != 0 ) - { - char *err = ssl_verify_strerror( returncode ); + + if (source == NULL) { + if (returncode != 0) { + char *err = ssl_verify_strerror(returncode); req->status_string = g_strdup_printf( - "Certificate verification problem 0x%x: %s", - returncode, err ? err : "Unknown" ); - g_free( err ); + "Certificate verification problem 0x%x: %s", + returncode, err ? err : "Unknown"); + g_free(err); } - return http_connected( data, -1, cond ); + return http_connected(data, -1, cond); } - - req->fd = ssl_getfd( source ); - - return http_connected( data, req->fd, cond ); + + req->fd = ssl_getfd(source); + + return http_connected(data, req->fd, cond); } typedef enum { @@ -199,97 +193,87 @@ typedef enum { CR_ABORT, } http_ret_t; -static gboolean http_handle_headers( struct http_request *req ); -static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len ); -static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len ); +static gboolean http_handle_headers(struct http_request *req); +static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len); +static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len); -static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) +static gboolean http_incoming_data(gpointer data, int source, b_input_condition cond) { struct http_request *req = data; char buffer[4096]; int st; - - if( req->inpa > 0 ) - { - b_event_remove( req->inpa ); + + if (req->inpa > 0) { + b_event_remove(req->inpa); req->inpa = 0; } - - if( req->ssl ) - { - st = ssl_read( req->ssl, buffer, sizeof( buffer ) ); - if( st < 0 ) - { - if( ssl_errno != SSL_AGAIN ) - { + + if (req->ssl) { + st = ssl_read(req->ssl, buffer, sizeof(buffer)); + if (st < 0) { + if (ssl_errno != SSL_AGAIN) { /* goto cleanup; */ - + /* YAY! We have to deal with crappy Microsoft servers that LOVE to send invalid TLS packets that abort connections! \o/ */ - + goto eof; } - } - else if( st == 0 ) - { + } else if (st == 0) { goto eof; } - } - else - { - st = read( req->fd, buffer, sizeof( buffer ) ); - if( st < 0 ) - { - if( !sockerr_again() ) - { - req->status_string = g_strdup( strerror( errno ) ); + } else { + st = read(req->fd, buffer, sizeof(buffer)); + if (st < 0) { + if (!sockerr_again()) { + req->status_string = g_strdup(strerror(errno)); goto cleanup; } - } - else if( st == 0 ) - { + } else if (st == 0) { goto eof; } } - - if( st > 0 ) - { + + if (st > 0) { http_ret_t c; - - if( req->flags & HTTPC_CHUNKED ) - c = http_process_chunked_data( req, buffer, st ); - else - c = http_process_data( req, buffer, st ); - - if( c == CR_EOF ) + + if (req->flags & HTTPC_CHUNKED) { + c = http_process_chunked_data(req, buffer, st); + } else { + c = http_process_data(req, buffer, st); + } + + if (c == CR_EOF) { goto eof; - else if( c == CR_ERROR || c == CR_ABORT ) + } else if (c == CR_ERROR || c == CR_ABORT) { return FALSE; + } } - - if( req->content_length != -1 && - req->body_size >= req->content_length ) + + if (req->content_length != -1 && + req->body_size >= req->content_length) { goto eof; - - if( ssl_pending( req->ssl ) ) - return http_incoming_data( data, source, cond ); - + } + + if (ssl_pending(req->ssl)) { + return http_incoming_data(data, source, cond); + } + /* There will be more! */ - req->inpa = b_input_add( req->fd, - req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ, - http_incoming_data, req ); - + req->inpa = b_input_add(req->fd, + req->ssl ? ssl_getdirection(req->ssl) : B_EV_IO_READ, + http_incoming_data, req); + return FALSE; eof: req->flags |= HTTPC_EOF; - + /* Maybe if the webserver is overloaded, or when there's bad SSL support... */ - if( req->bytes_read == 0 ) - { - req->status_string = g_strdup( "Empty HTTP reply" ); + if (req->bytes_read == 0) { + req->status_string = g_strdup("Empty HTTP reply"); goto cleanup; } @@ -297,433 +281,432 @@ cleanup: /* Avoid g_source_remove warnings */ req->inpa = 0; - if( req->ssl ) - ssl_disconnect( req->ssl ); - else - closesocket( req->fd ); - - if( req->body_size < req->content_length ) - { + if (req->ssl) { + ssl_disconnect(req->ssl); + } else { + closesocket(req->fd); + } + + if (req->body_size < req->content_length) { req->status_code = -1; - g_free( req->status_string ); - req->status_string = g_strdup( "Response truncated" ); - } - - if( getenv( "BITLBEE_DEBUG" ) && req ) - printf( "Finishing HTTP request with status: %s\n", - req->status_string ? req->status_string : "NULL" ); - - req->func( req ); - http_free( req ); + g_free(req->status_string); + req->status_string = g_strdup("Response truncated"); + } + + if (getenv("BITLBEE_DEBUG") && req) { + printf("Finishing HTTP request with status: %s\n", + req->status_string ? req->status_string : "NULL"); + } + + req->func(req); + http_free(req); return FALSE; } -static http_ret_t http_process_chunked_data( struct http_request *req, const char *buffer, int len ) +static http_ret_t http_process_chunked_data(struct http_request *req, const char *buffer, int len) { char *chunk, *eos, *s; - - if( len < 0 ) + + if (len < 0) { return TRUE; - - if( len > 0 ) - { - req->cbuf = g_realloc( req->cbuf, req->cblen + len + 1 ); - memcpy( req->cbuf + req->cblen, buffer, len ); + } + + if (len > 0) { + req->cbuf = g_realloc(req->cbuf, req->cblen + len + 1); + memcpy(req->cbuf + req->cblen, buffer, len); req->cblen += len; req->cbuf[req->cblen] = '\0'; } - + /* Turns out writing a proper chunked-encoding state machine is not that simple. :-( I've tested this one feeding it byte by byte so I hope it's solid now. */ chunk = req->cbuf; eos = req->cbuf + req->cblen; - while( TRUE ) - { + while (TRUE) { int clen = 0; - + /* Might be a \r\n from the last chunk. */ s = chunk; - while( g_ascii_isspace( *s ) ) - s ++; + while (g_ascii_isspace(*s)) { + s++; + } /* Chunk length. Might be incomplete. */ - if( s < eos && sscanf( s, "%x", &clen ) != 1 ) + if (s < eos && sscanf(s, "%x", &clen) != 1) { return CR_ERROR; - while( g_ascii_isxdigit( *s ) ) - s ++; - + } + while (g_ascii_isxdigit(*s)) { + s++; + } + /* If we read anything here, it *must* be \r\n. */ - if( strncmp( s, "\r\n", MIN( 2, eos - s ) ) != 0 ) + if (strncmp(s, "\r\n", MIN(2, eos - s)) != 0) { return CR_ERROR; + } s += 2; - - if( s >= eos ) + + if (s >= eos) { break; - - /* 0-length chunk means end of response. */ - if( clen == 0 ) + } + + /* 0-length chunk means end of response. */ + if (clen == 0) { return CR_EOF; - + } + /* Wait for the whole chunk to arrive. */ - if( s + clen > eos ) + if (s + clen > eos) { break; - if( http_process_data( req, s, clen ) != CR_OK ) + } + if (http_process_data(req, s, clen) != CR_OK) { return CR_ABORT; - + } + chunk = s + clen; } - - if( chunk != req->cbuf ) - { + + if (chunk != req->cbuf) { req->cblen = eos - chunk; - s = g_memdup( chunk, req->cblen + 1 ); - g_free( req->cbuf ); + s = g_memdup(chunk, req->cblen + 1); + g_free(req->cbuf); req->cbuf = s; } - + return CR_OK; } -static http_ret_t http_process_data( struct http_request *req, const char *buffer, int len ) +static http_ret_t http_process_data(struct http_request *req, const char *buffer, int len) { - if( len <= 0 ) + if (len <= 0) { return CR_OK; - - if( !req->reply_body ) - { - req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + len + 1 ); - memcpy( req->reply_headers + req->bytes_read, buffer, len ); + } + + if (!req->reply_body) { + req->reply_headers = g_realloc(req->reply_headers, req->bytes_read + len + 1); + memcpy(req->reply_headers + req->bytes_read, buffer, len); req->bytes_read += len; req->reply_headers[req->bytes_read] = '\0'; - - if( strstr( req->reply_headers, "\r\n\r\n" ) || - strstr( req->reply_headers, "\n\n" ) ) - { + + if (strstr(req->reply_headers, "\r\n\r\n") || + strstr(req->reply_headers, "\n\n")) { /* We've now received all headers. Look for something interesting. */ - if( !http_handle_headers( req ) ) + if (!http_handle_headers(req)) { return CR_ABORT; - + } + /* Start parsing the body as chunked if required. */ - if( req->flags & HTTPC_CHUNKED ) - return http_process_chunked_data( req, NULL, 0 ); + if (req->flags & HTTPC_CHUNKED) { + return http_process_chunked_data(req, NULL, 0); + } } - } - else - { + } else { int pos = req->reply_body - req->sbuf; - req->sbuf = g_realloc( req->sbuf, req->sblen + len + 1 ); - memcpy( req->sbuf + req->sblen, buffer, len ); + req->sbuf = g_realloc(req->sbuf, req->sblen + len + 1); + memcpy(req->sbuf + req->sblen, buffer, len); req->bytes_read += len; req->sblen += len; req->sbuf[req->sblen] = '\0'; req->reply_body = req->sbuf + pos; req->body_size = req->sblen - pos; } - - if( ( req->flags & HTTPC_STREAMING ) && req->reply_body ) - req->func( req ); - + + if ((req->flags & HTTPC_STREAMING) && req->reply_body) { + req->func(req); + } + return CR_OK; } /* Splits headers and body. Checks result code, in case of 300s it'll handle redirects. If this returns FALSE, don't call any callbacks! */ -static gboolean http_handle_headers( struct http_request *req ) +static gboolean http_handle_headers(struct http_request *req) { char *end1, *end2, *s; int evil_server = 0; - + /* Zero termination is very convenient. */ req->reply_headers[req->bytes_read] = '\0'; - + /* Find the separation between headers and body, and keep stupid webservers in mind. */ - end1 = strstr( req->reply_headers, "\r\n\r\n" ); - end2 = strstr( req->reply_headers, "\n\n" ); - - if( end2 && end2 < end1 ) - { + end1 = strstr(req->reply_headers, "\r\n\r\n"); + end2 = strstr(req->reply_headers, "\n\n"); + + if (end2 && end2 < end1) { end1 = end2 + 1; evil_server = 1; - } - else if( end1 ) - { + } else if (end1) { end1 += 2; - } - else - { - req->status_string = g_strdup( "Malformed HTTP reply" ); + } else { + req->status_string = g_strdup("Malformed HTTP reply"); return TRUE; } - + *end1 = '\0'; - - if( getenv( "BITLBEE_DEBUG" ) ) - printf( "HTTP response headers:\n%s\n", req->reply_headers ); - - if( evil_server ) + + if (getenv("BITLBEE_DEBUG")) { + printf("HTTP response headers:\n%s\n", req->reply_headers); + } + + if (evil_server) { req->reply_body = end1 + 1; - else + } else { req->reply_body = end1 + 2; - + } + /* Separately allocated space for headers and body. */ req->sblen = req->body_size = req->reply_headers + req->bytes_read - req->reply_body; - req->sbuf = req->reply_body = g_memdup( req->reply_body, req->body_size + 1 ); - req->reply_headers = g_realloc( req->reply_headers, end1 - req->reply_headers + 1 ); - - if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) - { - if( sscanf( end1 + 1, "%hd", &req->status_code ) != 1 ) - { - req->status_string = g_strdup( "Can't parse status code" ); + req->sbuf = req->reply_body = g_memdup(req->reply_body, req->body_size + 1); + req->reply_headers = g_realloc(req->reply_headers, end1 - req->reply_headers + 1); + + if ((end1 = strchr(req->reply_headers, ' ')) != NULL) { + if (sscanf(end1 + 1, "%hd", &req->status_code) != 1) { + req->status_string = g_strdup("Can't parse status code"); req->status_code = -1; - } - else - { + } else { char *eol; - - if( evil_server ) - eol = strchr( end1, '\n' ); - else - eol = strchr( end1, '\r' ); - - req->status_string = g_strndup( end1 + 1, eol - end1 - 1 ); - + + if (evil_server) { + eol = strchr(end1, '\n'); + } else { + eol = strchr(end1, '\r'); + } + + req->status_string = g_strndup(end1 + 1, eol - end1 - 1); + /* Just to be sure... */ - if( ( eol = strchr( req->status_string, '\r' ) ) ) + if ((eol = strchr(req->status_string, '\r'))) { *eol = 0; - if( ( eol = strchr( req->status_string, '\n' ) ) ) + } + if ((eol = strchr(req->status_string, '\n'))) { *eol = 0; + } } - } - else - { - req->status_string = g_strdup( "Can't locate status code" ); + } else { + req->status_string = g_strdup("Can't locate status code"); req->status_code = -1; } - - if( ( ( req->status_code >= 301 && req->status_code <= 303 ) || - req->status_code == 307 ) && req->redir_ttl-- > 0 ) - { + + if (((req->status_code >= 301 && req->status_code <= 303) || + req->status_code == 307) && req->redir_ttl-- > 0) { char *loc, *new_request, *new_host; int error = 0, new_port, new_proto; - + /* We might fill it again, so let's not leak any memory. */ - g_free( req->status_string ); + g_free(req->status_string); req->status_string = NULL; - - loc = strstr( req->reply_headers, "\nLocation: " ); - if( loc == NULL ) /* We can't handle this redirect... */ - { - req->status_string = g_strdup( "Can't locate Location: header" ); + + loc = strstr(req->reply_headers, "\nLocation: "); + if (loc == NULL) { /* We can't handle this redirect... */ + req->status_string = g_strdup("Can't locate Location: header"); return TRUE; } - + loc += 11; - while( *loc == ' ' ) - loc ++; - + while (*loc == ' ') { + loc++; + } + /* TODO/FIXME: Possibly have to handle relative redirections, and rewrite Host: headers. Not necessary for now, it's enough for passport authentication like this. */ - - if( *loc == '/' ) - { + + if (*loc == '/') { /* Just a different pathname... */ - + /* Since we don't cache the servername, and since we don't need this yet anyway, I won't implement it. */ - - req->status_string = g_strdup( "Can't handle relative redirects" ); - + + req->status_string = g_strdup("Can't handle relative redirects"); + return TRUE; - } - else - { + } else { /* A whole URL */ url_t *url; char *s, *version, *headers; const char *new_method; - - s = strstr( loc, "\r\n" ); - if( s == NULL ) + + s = strstr(loc, "\r\n"); + if (s == NULL) { return TRUE; - - url = g_new0( url_t, 1 ); + } + + url = g_new0(url_t, 1); *s = 0; - - if( !url_set( url, loc ) ) - { - req->status_string = g_strdup( "Malformed redirect URL" ); - g_free( url ); + + if (!url_set(url, loc)) { + req->status_string = g_strdup("Malformed redirect URL"); + g_free(url); return TRUE; } - + /* Find all headers and, if necessary, the POST request contents. Skip the old Host: header though. This crappy code here means anything using this http_client MUST put the Host: header at the top. */ - if( !( ( s = strstr( req->request, "\r\nHost: " ) ) && - ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) ) - { - req->status_string = g_strdup( "Error while rebuilding request string" ); - g_free( url ); + if (!((s = strstr(req->request, "\r\nHost: ")) && + (s = strstr(s + strlen("\r\nHost: "), "\r\n")))) { + req->status_string = g_strdup("Error while rebuilding request string"); + g_free(url); return TRUE; } headers = s; - + /* More or less HTTP/1.0 compliant, from my reading of RFC 2616. Always perform a GET request unless we received a 301. 303 was meant for this but it's HTTP/1.1-only and we're specifically speaking HTTP/1.0. ... - + Well except someone at identi.ca's didn't bother reading any RFCs and just return HTTP/1.1-specific status codes to HTTP/1.0 requests. Fuckers. So here we are, handle 301..303,307. */ - if( strncmp( req->request, "GET", 3 ) == 0 ) + if (strncmp(req->request, "GET", 3) == 0) { /* GETs never become POSTs. */ new_method = "GET"; - else if( req->status_code == 302 || req->status_code == 303 ) + } else if (req->status_code == 302 || req->status_code == 303) { /* 302 de-facto becomes GET, 303 as specified by RFC 2616#10.3.3 */ new_method = "GET"; - else + } else { /* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */ new_method = "POST"; - - if( ( version = strstr( req->request, " HTTP/" ) ) && - ( s = strstr( version, "\r\n" ) ) ) - { - version ++; - version = g_strndup( version, s - version ); } - else - version = g_strdup( "HTTP/1.0" ); - + + if ((version = strstr(req->request, " HTTP/")) && + (s = strstr(version, "\r\n"))) { + version++; + version = g_strndup(version, s - version); + } else { + version = g_strdup("HTTP/1.0"); + } + /* Okay, this isn't fun! We have to rebuild the request... :-( */ - new_request = g_strdup_printf( "%s %s %s\r\nHost: %s%s", - new_method, url->file, version, - url->host, headers ); - - new_host = g_strdup( url->host ); + new_request = g_strdup_printf("%s %s %s\r\nHost: %s%s", + new_method, url->file, version, + url->host, headers); + + new_host = g_strdup(url->host); new_port = url->port; new_proto = url->proto; - + /* If we went from POST to GET, truncate the request content. */ - if( new_request[0] != req->request[0] && new_request[0] == 'G' && - ( s = strstr( new_request, "\r\n\r\n" ) ) ) + if (new_request[0] != req->request[0] && new_request[0] == 'G' && + (s = strstr(new_request, "\r\n\r\n"))) { s[4] = '\0'; - - g_free( url ); - g_free( version ); + } + + g_free(url); + g_free(version); + } + + if (req->ssl) { + ssl_disconnect(req->ssl); + } else { + closesocket(req->fd); } - - if( req->ssl ) - ssl_disconnect( req->ssl ); - else - closesocket( req->fd ); - + req->fd = -1; req->ssl = NULL; - - if( getenv( "BITLBEE_DEBUG" ) ) - printf( "New headers for redirected HTTP request:\n%s\n", new_request ); - - if( new_proto == PROTO_HTTPS ) - { - req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req ); - if( req->ssl == NULL ) - error = 1; + + if (getenv("BITLBEE_DEBUG")) { + printf("New headers for redirected HTTP request:\n%s\n", new_request); } - else - { - req->fd = proxy_connect( new_host, new_port, http_connected, req ); - if( req->fd < 0 ) + + if (new_proto == PROTO_HTTPS) { + req->ssl = ssl_connect(new_host, new_port, TRUE, http_ssl_connected, req); + if (req->ssl == NULL) { error = 1; + } + } else { + req->fd = proxy_connect(new_host, new_port, http_connected, req); + if (req->fd < 0) { + error = 1; + } } - g_free( new_host ); - - if( error ) - { - req->status_string = g_strdup( "Connection problem during redirect" ); - g_free( new_request ); + g_free(new_host); + + if (error) { + req->status_string = g_strdup("Connection problem during redirect"); + g_free(new_request); return TRUE; } - - g_free( req->request ); - g_free( req->reply_headers ); - g_free( req->sbuf ); + + g_free(req->request); + g_free(req->reply_headers); + g_free(req->sbuf); req->request = new_request; - req->request_length = strlen( new_request ); + req->request_length = strlen(new_request); req->bytes_read = req->bytes_written = req->inpa = 0; req->reply_headers = req->reply_body = NULL; req->sbuf = req->cbuf = NULL; req->sblen = req->cblen = 0; - + return FALSE; } - if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) && - sscanf( s, "%d", &req->content_length ) != 1 ) + if ((s = get_rfc822_header(req->reply_headers, "Content-Length", 0)) && + sscanf(s, "%d", &req->content_length) != 1) { req->content_length = -1; - g_free( s ); - - if( ( s = get_rfc822_header( req->reply_headers, "Transfer-Encoding", 0 ) ) ) - { - if( strcasestr( s, "chunked" ) ) - { + } + g_free(s); + + if ((s = get_rfc822_header(req->reply_headers, "Transfer-Encoding", 0))) { + if (strcasestr(s, "chunked")) { req->flags |= HTTPC_CHUNKED; req->cbuf = req->sbuf; req->cblen = req->sblen; - - req->reply_body = req->sbuf = g_strdup( "" ); + + req->reply_body = req->sbuf = g_strdup(""); req->body_size = req->sblen = 0; } - g_free( s ); + g_free(s); } - + return TRUE; } -void http_flush_bytes( struct http_request *req, size_t len ) +void http_flush_bytes(struct http_request *req, size_t len) { - if( len <= 0 || len > req->body_size || !( req->flags & HTTPC_STREAMING ) ) + if (len <= 0 || len > req->body_size || !(req->flags & HTTPC_STREAMING)) { return; - + } + req->reply_body += len; req->body_size -= len; - - if( req->reply_body - req->sbuf >= 512 ) - { - char *new = g_memdup( req->reply_body, req->body_size + 1 ); - g_free( req->sbuf ); + + if (req->reply_body - req->sbuf >= 512) { + char *new = g_memdup(req->reply_body, req->body_size + 1); + g_free(req->sbuf); req->reply_body = req->sbuf = new; req->sblen = req->body_size; } } -void http_close( struct http_request *req ) +void http_close(struct http_request *req) { - if( !req ) + if (!req) { return; - - if( req->inpa > 0 ) - b_event_remove( req->inpa ); - - if( req->ssl ) - ssl_disconnect( req->ssl ); - else - closesocket( req->fd ); - - http_free( req ); + } + + if (req->inpa > 0) { + b_event_remove(req->inpa); + } + + if (req->ssl) { + ssl_disconnect(req->ssl); + } else { + closesocket(req->fd); + } + + http_free(req); } -static void http_free( struct http_request *req ) +static void http_free(struct http_request *req) { - g_free( req->request ); - g_free( req->reply_headers ); - g_free( req->status_string ); - g_free( req->sbuf ); - g_free( req->cbuf ); - g_free( req ); + g_free(req->request); + g_free(req->reply_headers); + g_free(req->status_string); + g_free(req->sbuf); + g_free(req->cbuf); + g_free(req); } diff --git a/lib/http_client.h b/lib/http_client.h index 99add28f..899b3ccd 100644 --- a/lib/http_client.h +++ b/lib/http_client.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -27,7 +27,7 @@ In the "background" it will send the whole query and wait for a complete response to come back. Initially written for MS Passport authentication, but used for many other things now like OAuth and Twitter. - + It's very useful for doing quick requests without blocking the whole program. Unfortunately it doesn't support fancy stuff like HTTP keep- alives. */ @@ -37,23 +37,21 @@ struct http_request; -typedef enum http_client_flags -{ +typedef enum http_client_flags { HTTPC_STREAMING = 1, HTTPC_EOF = 2, HTTPC_CHUNKED = 4, - + /* Let's reserve 0x1000000+ for lib users. */ } http_client_flags_t; /* Your callback function should look like this: */ -typedef void (*http_input_function)( struct http_request * ); +typedef void (*http_input_function)(struct http_request *); /* This structure will be filled in by the http_dorequest* functions, and it will be passed to the callback function. Use the data field to add your own data. */ -struct http_request -{ +struct http_request { char *request; /* The request to send to the server. */ int request_length; /* Its size. */ short status_code; /* The numeric HTTP status code. (Or -1 @@ -64,25 +62,25 @@ struct http_request int body_size; /* The number of bytes in reply_body. */ short redir_ttl; /* You can set it to 0 if you don't want http_client to follow them. */ - + http_client_flags_t flags; - + http_input_function func; gpointer data; - + /* Please don't touch the things down here, you shouldn't need them. */ void *ssl; int fd; - + int inpa; int bytes_written; int bytes_read; int content_length; /* "Content-Length:" header or -1 */ - + /* Used in streaming mode. Caller should read from reply_body. */ char *sbuf; size_t sblen; - + /* Chunked encoding only. Raw chunked stream is decoded from here. */ char *cbuf; size_t cblen; @@ -92,9 +90,10 @@ struct http_request version is probably only useful if you want to do POST requests or if you want to add some extra headers. As you can see, HTTPS connections are also supported (using ssl_client). */ -struct http_request *http_dorequest( char *host, int port, int ssl, char *request, http_input_function func, gpointer data ); -struct http_request *http_dorequest_url( char *url_string, http_input_function func, gpointer data ); +struct http_request *http_dorequest(char *host, int port, int ssl, char *request, http_input_function func, + gpointer data); +struct http_request *http_dorequest_url(char *url_string, http_input_function func, gpointer data); /* For streaming connections only; flushes len bytes at the start of the buffer. */ -void http_flush_bytes( struct http_request *req, size_t len ); -void http_close( struct http_request *req ); +void http_flush_bytes(struct http_request *req, size_t len); +void http_close(struct http_request *req); @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2008 Wilmer van der Gaast and others * @@ -25,109 +25,101 @@ #define BITLBEE_CORE #include "bitlbee.h" -ini_t *ini_open( char *file ) +ini_t *ini_open(char *file) { int fd; ini_t *ini = NULL; struct stat fi; - - if( ( fd = open( file, O_RDONLY ) ) != -1 && - fstat( fd, &fi ) == 0 && + + if ((fd = open(file, O_RDONLY)) != -1 && + fstat(fd, &fi) == 0 && fi.st_size <= 16384 && - ( ini = g_malloc( sizeof( ini_t ) + fi.st_size + 1 ) ) && - read( fd, ini->file, fi.st_size ) == fi.st_size ) - { - memset( ini, 0, sizeof( ini_t ) ); + (ini = g_malloc(sizeof(ini_t) + fi.st_size + 1)) && + read(fd, ini->file, fi.st_size) == fi.st_size) { + memset(ini, 0, sizeof(ini_t)); ini->size = fi.st_size; ini->file[ini->size] = 0; ini->cur = ini->file; ini->c_section = ""; - - close( fd ); - + + close(fd); + return ini; } - if( fd >= 0 ) - close( fd ); - - ini_close( ini ); + if (fd >= 0) { + close(fd); + } + + ini_close(ini); return NULL; } /* Strips leading and trailing whitespace and returns a pointer to the first non-ws character of the given string. */ -static char *ini_strip_whitespace( char *in ) +static char *ini_strip_whitespace(char *in) { char *e; - while( g_ascii_isspace( *in ) ) + while (g_ascii_isspace(*in)) { in++; + } - e = in + strlen( in ) - 1; - while( e > in && g_ascii_isspace( *e ) ) + e = in + strlen(in) - 1; + while (e > in && g_ascii_isspace(*e)) { e--; + } e[1] = 0; - + return in; } -int ini_read( ini_t *file ) +int ini_read(ini_t *file) { char *s; - - while( file->cur && file->cur < file->file + file->size ) - { + + while (file->cur && file->cur < file->file + file->size) { char *e, *next; - + file->line++; /* Find the end of line */ - if( ( e = strchr( file->cur, '\n' ) ) != NULL ) - { + if ((e = strchr(file->cur, '\n')) != NULL) { *e = 0; next = e + 1; - } - else - { + } else { /* No more lines. */ - e = file->cur + strlen( file->cur ); + e = file->cur + strlen(file->cur); next = NULL; } - + /* Comment? */ - if( ( s = strchr( file->cur, '#' ) ) != NULL ) + if ((s = strchr(file->cur, '#')) != NULL) { *s = 0; - - file->cur = ini_strip_whitespace( file->cur ); - - if( *file->cur == '[' ) - { + } + + file->cur = ini_strip_whitespace(file->cur); + + if (*file->cur == '[') { file->cur++; - if( ( s = strchr( file->cur, ']' ) ) != NULL ) - { + if ((s = strchr(file->cur, ']')) != NULL) { *s = 0; file->c_section = file->cur; } - } - else if( ( s = strchr( file->cur, '=' ) ) != NULL ) - { + } else if ((s = strchr(file->cur, '=')) != NULL) { *s = 0; - file->key = ini_strip_whitespace( file->cur ); - file->value = ini_strip_whitespace( s + 1 ); - - if( ( s = strchr( file->key, '.' ) ) != NULL ) - { + file->key = ini_strip_whitespace(file->cur); + file->value = ini_strip_whitespace(s + 1); + + if ((s = strchr(file->key, '.')) != NULL) { *s = 0; file->section = file->key; file->key = s + 1; - } - else - { + } else { file->section = file->c_section; } - + file->cur = next; return 1; } @@ -135,11 +127,11 @@ int ini_read( ini_t *file ) file->cur = next; } - + return 0; } -void ini_close( ini_t *file ) +void ini_close(ini_t *file) { - g_free( file ); + g_free(file); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -26,8 +26,7 @@ #ifndef _INI_H #define _INI_H -typedef struct -{ +typedef struct { int line; char *c_section; char *section; @@ -38,8 +37,8 @@ typedef struct char file[]; } ini_t; -ini_t *ini_open( char *file ); -int ini_read( ini_t *file ); -void ini_close( ini_t *file ); +ini_t *ini_open(char *file); +int ini_read(ini_t *file); +void ini_close(ini_t *file); #endif @@ -38,9 +38,9 @@ #endif #ifdef __cplusplus - const struct _json_value json_value_none; /* zero-d by ctor */ +const struct _json_value json_value_none; /* zero-d by ctor */ #else - const struct _json_value json_value_none = { 0 }; +const struct _json_value json_value_none = { 0 }; #endif #include <stdio.h> @@ -50,933 +50,923 @@ typedef unsigned int json_uchar; -static unsigned char hex_value (json_char c) +static unsigned char hex_value(json_char c) { - if (g_ascii_isdigit(c)) - return c - '0'; - - switch (c) { - case 'a': case 'A': return 0x0A; - case 'b': case 'B': return 0x0B; - case 'c': case 'C': return 0x0C; - case 'd': case 'D': return 0x0D; - case 'e': case 'E': return 0x0E; - case 'f': case 'F': return 0x0F; - default: return 0xFF; - } + if (g_ascii_isdigit(c)) { + return c - '0'; + } + + switch (c) { + case 'a': case 'A': return 0x0A; + case 'b': case 'B': return 0x0B; + case 'c': case 'C': return 0x0C; + case 'd': case 'D': return 0x0D; + case 'e': case 'E': return 0x0E; + case 'f': case 'F': return 0x0F; + default: return 0xFF; + } } -typedef struct -{ - unsigned long used_memory; +typedef struct { + unsigned long used_memory; - unsigned int uint_max; - unsigned long ulong_max; + unsigned int uint_max; + unsigned long ulong_max; - json_settings settings; - int first_pass; + json_settings settings; + int first_pass; } json_state; -static void * default_alloc (size_t size, int zero, void * user_data) +static void * default_alloc(size_t size, int zero, void * user_data) { - return zero ? calloc (1, size) : malloc (size); + return zero ? calloc(1, size) : malloc(size); } -static void default_free (void * ptr, void * user_data) +static void default_free(void * ptr, void * user_data) { - free (ptr); + free(ptr); } -static void * json_alloc (json_state * state, unsigned long size, int zero) +static void * json_alloc(json_state * state, unsigned long size, int zero) { - if ((state->ulong_max - state->used_memory) < size) - return 0; + if ((state->ulong_max - state->used_memory) < size) { + return 0; + } - if (state->settings.max_memory - && (state->used_memory += size) > state->settings.max_memory) - { - return 0; - } + if (state->settings.max_memory + && (state->used_memory += size) > state->settings.max_memory) { + return 0; + } - return state->settings.mem_alloc (size, zero, state->settings.user_data); + return state->settings.mem_alloc(size, zero, state->settings.user_data); } static int new_value - (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type) + (json_state * state, json_value ** top, json_value ** root, json_value ** alloc, json_type type) { - json_value * value; - int values_size; + json_value * value; + int values_size; - if (!state->first_pass) - { - value = *top = *alloc; - *alloc = (*alloc)->_reserved.next_alloc; + if (!state->first_pass) { + value = *top = *alloc; + *alloc = (*alloc)->_reserved.next_alloc; - if (!*root) - *root = value; + if (!*root) { + *root = value; + } - switch (value->type) - { - case json_array: + switch (value->type) { + case json_array: - if (! (value->u.array.values = (json_value **) json_alloc - (state, value->u.array.length * sizeof (json_value *), 0)) ) - { - return 0; - } + if (!(value->u.array.values = (json_value **) json_alloc + (state, value->u.array.length * sizeof(json_value *), + 0))) { + return 0; + } - value->u.array.length = 0; - break; + value->u.array.length = 0; + break; - case json_object: + case json_object: - values_size = sizeof (*value->u.object.values) * value->u.object.length; + values_size = sizeof(*value->u.object.values) * value->u.object.length; - if (! ((*(void **) &value->u.object.values) = json_alloc - (state, values_size + ((unsigned long) value->u.object.values), 0)) ) - { - return 0; - } + if (!((*(void **) &value->u.object.values) = json_alloc + (state, values_size + + ((unsigned long) value->u.object.values), + 0))) { + return 0; + } - value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size; + value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size; - value->u.object.length = 0; - break; + value->u.object.length = 0; + break; - case json_string: + case json_string: - if (! (value->u.string.ptr = (json_char *) json_alloc - (state, (value->u.string.length + 1) * sizeof (json_char), 0)) ) - { - return 0; - } + if (!(value->u.string.ptr = (json_char *) json_alloc + (state, (value->u.string.length + 1) * sizeof(json_char), + 0))) { + return 0; + } - value->u.string.length = 0; - break; + value->u.string.length = 0; + break; - default: - break; - }; + default: + break; + } + ; - return 1; - } + return 1; + } - value = (json_value *) json_alloc (state, sizeof (json_value), 1); + value = (json_value *) json_alloc(state, sizeof(json_value), 1); - if (!value) - return 0; + if (!value) { + return 0; + } - if (!*root) - *root = value; + if (!*root) { + *root = value; + } - value->type = type; - value->parent = *top; + value->type = type; + value->parent = *top; - if (*alloc) - (*alloc)->_reserved.next_alloc = value; + if (*alloc) { + (*alloc)->_reserved.next_alloc = value; + } - *alloc = *top = value; + *alloc = *top = value; - return 1; + return 1; } #define e_off \ - ((int) (i - cur_line_begin)) + ((int) (i - cur_line_begin)) #define whitespace \ - case '\n': ++ cur_line; cur_line_begin = i; \ - case ' ': case '\t': case '\r' +case '\n': ++cur_line; cur_line_begin = i; \ +case ' ': case '\t': case '\r' #define string_add(b) \ - do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0); + do { if (!state.first_pass) { string [string_length] = b; } ++string_length; } while (0); static const long - flag_next = 1 << 0, - flag_reproc = 1 << 1, - flag_need_comma = 1 << 2, - flag_seek_value = 1 << 3, - flag_escaped = 1 << 4, - flag_string = 1 << 5, - flag_need_colon = 1 << 6, - flag_done = 1 << 7, - flag_num_negative = 1 << 8, - flag_num_zero = 1 << 9, - flag_num_e = 1 << 10, - flag_num_e_got_sign = 1 << 11, - flag_num_e_negative = 1 << 12, - flag_line_comment = 1 << 13, - flag_block_comment = 1 << 14; - -json_value * json_parse_ex (json_settings * settings, - const json_char * json, - size_t length, - char * error_buf) + flag_next = 1 << 0, + flag_reproc = 1 << 1, + flag_need_comma = 1 << 2, + flag_seek_value = 1 << 3, + flag_escaped = 1 << 4, + flag_string = 1 << 5, + flag_need_colon = 1 << 6, + flag_done = 1 << 7, + flag_num_negative = 1 << 8, + flag_num_zero = 1 << 9, + flag_num_e = 1 << 10, + flag_num_e_got_sign = 1 << 11, + flag_num_e_negative = 1 << 12, + flag_line_comment = 1 << 13, + flag_block_comment = 1 << 14; + +json_value * json_parse_ex(json_settings * settings, + const json_char * json, + size_t length, + char * error_buf) { - json_char error [json_error_max]; - unsigned int cur_line; - const json_char * cur_line_begin, * i, * end; - json_value * top, * root, * alloc = 0; - json_state state = { 0 }; - long flags; - long num_digits = 0, num_e = 0; - json_int_t num_fraction = 0; - - /* Skip UTF-8 BOM - */ - if (length >= 3 && ((unsigned char) json [0]) == 0xEF - && ((unsigned char) json [1]) == 0xBB - && ((unsigned char) json [2]) == 0xBF) - { - json += 3; - length -= 3; - } - - error[0] = '\0'; - end = (json + length); - - memcpy (&state.settings, settings, sizeof (json_settings)); - - if (!state.settings.mem_alloc) - state.settings.mem_alloc = default_alloc; - - if (!state.settings.mem_free) - state.settings.mem_free = default_free; - - memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); - memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); - - state.uint_max -= 8; /* limit of how much can be added before next check */ - state.ulong_max -= 8; - - for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass) - { - json_uchar uchar; - unsigned char uc_b1, uc_b2, uc_b3, uc_b4; - json_char * string = 0; - unsigned int string_length = 0; - - top = root = 0; - flags = flag_seek_value; - - cur_line = 1; - cur_line_begin = json; - - for (i = json ;; ++ i) - { - json_char b = (i == end ? 0 : *i); - - if (flags & flag_string) - { - if (!b) - { sprintf (error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off); - goto e_failed; - } - - if (string_length > state.uint_max) - goto e_overflow; - - if (flags & flag_escaped) - { - flags &= ~ flag_escaped; - - switch (b) - { - case 'b': string_add ('\b'); break; - case 'f': string_add ('\f'); break; - case 'n': string_add ('\n'); break; - case 'r': string_add ('\r'); break; - case 't': string_add ('\t'); break; - case 'u': - - if (end - i < 4 || - (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF - || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF) - { - sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off); - goto e_failed; - } - - uc_b1 = (uc_b1 << 4) | uc_b2; - uc_b2 = (uc_b3 << 4) | uc_b4; - uchar = (uc_b1 << 8) | uc_b2; - - if ((uchar & 0xF800) == 0xD800) { - json_uchar uchar2; - - if (end - i < 6 || (*++ i) != '\\' || (*++ i) != 'u' || - (uc_b1 = hex_value (*++ i)) == 0xFF || (uc_b2 = hex_value (*++ i)) == 0xFF - || (uc_b3 = hex_value (*++ i)) == 0xFF || (uc_b4 = hex_value (*++ i)) == 0xFF) - { - sprintf (error, "Invalid character value `%c` (at %d:%d)", b, cur_line, e_off); - goto e_failed; - } - - uc_b1 = (uc_b1 << 4) | uc_b2; - uc_b2 = (uc_b3 << 4) | uc_b4; - uchar2 = (uc_b1 << 8) | uc_b2; - - uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF); - } - - if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F)) - { - string_add ((json_char) uchar); - break; - } - - if (uchar <= 0x7FF) - { - if (state.first_pass) - string_length += 2; - else - { string [string_length ++] = 0xC0 | (uchar >> 6); - string [string_length ++] = 0x80 | (uchar & 0x3F); - } - - break; - } - - if (uchar <= 0xFFFF) { - if (state.first_pass) - string_length += 3; - else - { string [string_length ++] = 0xE0 | (uchar >> 12); - string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); - string [string_length ++] = 0x80 | (uchar & 0x3F); - } - - break; - } - - if (state.first_pass) - string_length += 4; - else - { string [string_length ++] = 0xF0 | (uchar >> 18); - string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F); - string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F); - string [string_length ++] = 0x80 | (uchar & 0x3F); - } - - break; - - default: - string_add (b); - }; - - continue; - } - - if (b == '\\') - { - flags |= flag_escaped; - continue; - } - - if (b == '"') - { - if (!state.first_pass) - string [string_length] = 0; - - flags &= ~ flag_string; - string = 0; - - switch (top->type) - { - case json_string: - - top->u.string.length = string_length; - flags |= flag_next; - - break; - - case json_object: - - if (state.first_pass) - (*(json_char **) &top->u.object.values) += string_length + 1; - else - { - top->u.object.values [top->u.object.length].name - = (json_char *) top->_reserved.object_mem; - - top->u.object.values [top->u.object.length].name_length - = string_length; - - (*(json_char **) &top->_reserved.object_mem) += string_length + 1; - } - - flags |= flag_seek_value | flag_need_colon; - continue; - - default: - break; - }; - } - else - { - string_add (b); - continue; - } - } - - if (state.settings.settings & json_enable_comments) - { - if (flags & (flag_line_comment | flag_block_comment)) - { - if (flags & flag_line_comment) - { - if (b == '\r' || b == '\n' || !b) - { - flags &= ~ flag_line_comment; - -- i; /* so null can be reproc'd */ - } - - continue; - } - - if (flags & flag_block_comment) - { - if (!b) - { sprintf (error, "%d:%d: Unexpected EOF in block comment", cur_line, e_off); - goto e_failed; - } - - if (b == '*' && i < (end - 1) && i [1] == '/') - { - flags &= ~ flag_block_comment; - ++ i; /* skip closing sequence */ - } - - continue; - } - } - else if (b == '/') - { - if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object) - { - sprintf (error, "%d:%d: Comment not allowed here", cur_line, e_off); - goto e_failed; - } - - if (++ i == end) - { sprintf (error, "%d:%d: EOF unexpected", cur_line, e_off); - goto e_failed; - } - - switch (b = *i) - { - case '/': - flags |= flag_line_comment; - continue; - - case '*': - flags |= flag_block_comment; - continue; - - default: - sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, b); - goto e_failed; - }; - } - } - - if (flags & flag_done) - { - if (!b) - break; - - switch (b) - { - whitespace: - continue; - - default: - sprintf (error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b); - goto e_failed; - }; - } - - if (flags & flag_seek_value) - { - switch (b) - { - whitespace: - continue; - - case ']': - - if (top->type == json_array) - flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next; - else - { sprintf (error, "%d:%d: Unexpected ]", cur_line, e_off); - goto e_failed; - } - - break; - - default: - - if (flags & flag_need_comma) - { - if (b == ',') - { flags &= ~ flag_need_comma; - continue; - } - else - { sprintf (error, "%d:%d: Expected , before %c", cur_line, e_off, b); - goto e_failed; - } - } - - if (flags & flag_need_colon) - { - if (b == ':') - { flags &= ~ flag_need_colon; - continue; - } - else - { sprintf (error, "%d:%d: Expected : before %c", cur_line, e_off, b); - goto e_failed; - } - } - - flags &= ~ flag_seek_value; - - switch (b) - { - case '{': - - if (!new_value (&state, &top, &root, &alloc, json_object)) - goto e_alloc_failure; - - continue; - - case '[': - - if (!new_value (&state, &top, &root, &alloc, json_array)) - goto e_alloc_failure; - - flags |= flag_seek_value; - continue; - - case '"': - - if (!new_value (&state, &top, &root, &alloc, json_string)) - goto e_alloc_failure; - - flags |= flag_string; - - string = top->u.string.ptr; - string_length = 0; - - continue; - - case 't': - - if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e') - goto e_unknown_value; - - if (!new_value (&state, &top, &root, &alloc, json_boolean)) - goto e_alloc_failure; - - top->u.boolean = 1; - - flags |= flag_next; - break; - - case 'f': - - if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e') - goto e_unknown_value; + json_char error [json_error_max]; + unsigned int cur_line; + const json_char * cur_line_begin, * i, * end; + json_value * top, * root, * alloc = 0; + json_state state = { 0 }; + long flags; + long num_digits = 0, num_e = 0; + json_int_t num_fraction = 0; + + /* Skip UTF-8 BOM + */ + if (length >= 3 && ((unsigned char) json [0]) == 0xEF + && ((unsigned char) json [1]) == 0xBB + && ((unsigned char) json [2]) == 0xBF) { + json += 3; + length -= 3; + } + + error[0] = '\0'; + end = (json + length); + + memcpy(&state.settings, settings, sizeof(json_settings)); + + if (!state.settings.mem_alloc) { + state.settings.mem_alloc = default_alloc; + } + + if (!state.settings.mem_free) { + state.settings.mem_free = default_free; + } + + memset(&state.uint_max, 0xFF, sizeof(state.uint_max)); + memset(&state.ulong_max, 0xFF, sizeof(state.ulong_max)); + + state.uint_max -= 8; /* limit of how much can be added before next check */ + state.ulong_max -= 8; + + for (state.first_pass = 1; state.first_pass >= 0; --state.first_pass) { + json_uchar uchar; + unsigned char uc_b1, uc_b2, uc_b3, uc_b4; + json_char * string = 0; + unsigned int string_length = 0; + + top = root = 0; + flags = flag_seek_value; + + cur_line = 1; + cur_line_begin = json; + + for (i = json;; ++i) { + json_char b = (i == end ? 0 : *i); + + if (flags & flag_string) { + if (!b) { + sprintf(error, "Unexpected EOF in string (at %d:%d)", cur_line, e_off); + goto e_failed; + } + + if (string_length > state.uint_max) { + goto e_overflow; + } + + if (flags & flag_escaped) { + flags &= ~flag_escaped; + + switch (b) { + case 'b': string_add('\b'); break; + case 'f': string_add('\f'); break; + case 'n': string_add('\n'); break; + case 'r': string_add('\r'); break; + case 't': string_add('\t'); break; + case 'u': + + if (end - i < 4 || + (uc_b1 = hex_value(*++i)) == 0xFF || (uc_b2 = hex_value(*++i)) == + 0xFF + || (uc_b3 = hex_value(*++i)) == 0xFF || (uc_b4 = hex_value(*++i)) == + 0xFF) { + sprintf(error, "Invalid character value `%c` (at %d:%d)", b, + cur_line, e_off); + goto e_failed; + } + + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar = (uc_b1 << 8) | uc_b2; + + if ((uchar & 0xF800) == 0xD800) { + json_uchar uchar2; + + if (end - i < 6 || (*++i) != '\\' || (*++i) != 'u' || + (uc_b1 = hex_value(*++i)) == 0xFF || + (uc_b2 = hex_value(*++i)) == 0xFF + || (uc_b3 = hex_value(*++i)) == 0xFF || + (uc_b4 = hex_value(*++i)) == 0xFF) { + sprintf(error, + "Invalid character value `%c` (at %d:%d)", b, + cur_line, e_off); + goto e_failed; + } + + uc_b1 = (uc_b1 << 4) | uc_b2; + uc_b2 = (uc_b3 << 4) | uc_b4; + uchar2 = (uc_b1 << 8) | uc_b2; + + uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF); + } + + if (sizeof(json_char) >= sizeof(json_uchar) || (uchar <= 0x7F)) { + string_add((json_char) uchar); + break; + } + + if (uchar <= 0x7FF) { + if (state.first_pass) { + string_length += 2; + } else { string [string_length++] = 0xC0 | + (uchar >> + 6); + string [string_length++] = 0x80 | + (uchar & + 0x3F); } + + break; + } + + if (uchar <= 0xFFFF) { + if (state.first_pass) { + string_length += 3; + } else { string [string_length++] = 0xE0 | + (uchar >> + 12); + string [string_length++] = 0x80 | + ((uchar + >> 6) & + 0x3F); + string [string_length++] = 0x80 | + (uchar & + 0x3F); } + + break; + } + + if (state.first_pass) { + string_length += 4; + } else { string [string_length++] = 0xF0 | (uchar >> 18); + string [string_length++] = 0x80 | + ((uchar >> + 12) & 0x3F); + string [string_length++] = 0x80 | + ((uchar >> + 6) & 0x3F); + string [string_length++] = 0x80 | + (uchar & 0x3F); } + + break; + + default: + string_add(b); + } + ; + + continue; + } + + if (b == '\\') { + flags |= flag_escaped; + continue; + } + + if (b == '"') { + if (!state.first_pass) { + string [string_length] = 0; + } + + flags &= ~flag_string; + string = 0; + + switch (top->type) { + case json_string: + + top->u.string.length = string_length; + flags |= flag_next; + + break; + + case json_object: + + if (state.first_pass) { + (*(json_char **) &top->u.object.values) += string_length + 1; + } else { + top->u.object.values [top->u.object.length].name + = (json_char *) top->_reserved.object_mem; + + top->u.object.values [top->u.object.length].name_length + = string_length; + + (*(json_char **) &top->_reserved.object_mem) += string_length + + 1; + } + + flags |= flag_seek_value | flag_need_colon; + continue; + + default: + break; + } + ; + } else { + string_add(b); + continue; + } + } + + if (state.settings.settings & json_enable_comments) { + if (flags & (flag_line_comment | flag_block_comment)) { + if (flags & flag_line_comment) { + if (b == '\r' || b == '\n' || !b) { + flags &= ~flag_line_comment; + --i; /* so null can be reproc'd */ + } + + continue; + } + + if (flags & flag_block_comment) { + if (!b) { + sprintf(error, "%d:%d: Unexpected EOF in block comment", + cur_line, e_off); + goto e_failed; + } + + if (b == '*' && i < (end - 1) && i [1] == '/') { + flags &= ~flag_block_comment; + ++i; /* skip closing sequence */ + } + + continue; + } + } else if (b == '/') { + if (!(flags & (flag_seek_value | flag_done)) && top->type != json_object) { + sprintf(error, "%d:%d: Comment not allowed here", cur_line, e_off); + goto e_failed; + } + + if (++i == end) { + sprintf(error, "%d:%d: EOF unexpected", cur_line, e_off); + goto e_failed; + } + + switch (b = *i) { + case '/': + flags |= flag_line_comment; + continue; + + case '*': + flags |= flag_block_comment; + continue; + + default: + sprintf(error, "%d:%d: Unexpected `%c` in comment opening sequence", + cur_line, e_off, b); + goto e_failed; + } + ; + } + } + + if (flags & flag_done) { + if (!b) { + break; + } + + switch (b) { +whitespace: + continue; + + default: + sprintf(error, "%d:%d: Trailing garbage: `%c`", cur_line, e_off, b); + goto e_failed; + } + ; + } + + if (flags & flag_seek_value) { + switch (b) { +whitespace: + continue; + + case ']': + + if (top->type == json_array) { + flags = (flags & ~(flag_need_comma | flag_seek_value)) | flag_next; + } else { sprintf(error, "%d:%d: Unexpected ]", cur_line, e_off); + goto e_failed; } + + break; + + default: + + if (flags & flag_need_comma) { + if (b == ',') { + flags &= ~flag_need_comma; + continue; + } else { sprintf(error, "%d:%d: Expected , before %c", cur_line, e_off, + b); + goto e_failed; } + } + + if (flags & flag_need_colon) { + if (b == ':') { + flags &= ~flag_need_colon; + continue; + } else { sprintf(error, "%d:%d: Expected : before %c", cur_line, e_off, + b); + goto e_failed; } + } + + flags &= ~flag_seek_value; - if (!new_value (&state, &top, &root, &alloc, json_boolean)) - goto e_alloc_failure; - - flags |= flag_next; - break; + switch (b) { + case '{': - case 'n': + if (!new_value(&state, &top, &root, &alloc, json_object)) { + goto e_alloc_failure; + } + + continue; - if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l') - goto e_unknown_value; + case '[': - if (!new_value (&state, &top, &root, &alloc, json_null)) - goto e_alloc_failure; + if (!new_value(&state, &top, &root, &alloc, json_array)) { + goto e_alloc_failure; + } + + flags |= flag_seek_value; + continue; + + case '"': + + if (!new_value(&state, &top, &root, &alloc, json_string)) { + goto e_alloc_failure; + } + + flags |= flag_string; + + string = top->u.string.ptr; + string_length = 0; - flags |= flag_next; - break; + continue; + + case 't': - default: + if ((end - i) < 3 || *(++i) != 'r' || *(++i) != 'u' || *(++i) != 'e') { + goto e_unknown_value; + } - if (g_ascii_isdigit (b) || b == '-') - { - if (!new_value (&state, &top, &root, &alloc, json_integer)) - goto e_alloc_failure; + if (!new_value(&state, &top, &root, &alloc, json_boolean)) { + goto e_alloc_failure; + } - if (!state.first_pass) - { - while (g_ascii_isdigit (b) || b == '+' || b == '-' - || b == 'e' || b == 'E' || b == '.') - { - if ( (++ i) == end) - { - b = 0; - break; - } + top->u.boolean = 1; - b = *i; - } + flags |= flag_next; + break; - flags |= flag_next | flag_reproc; - break; - } + case 'f': - flags &= ~ (flag_num_negative | flag_num_e | - flag_num_e_got_sign | flag_num_e_negative | - flag_num_zero); + if ((end - i) < 4 || *(++i) != 'a' || *(++i) != 'l' || *(++i) != 's' || + *(++i) != 'e') { + goto e_unknown_value; + } - num_digits = 0; - num_fraction = 0; - num_e = 0; + if (!new_value(&state, &top, &root, &alloc, json_boolean)) { + goto e_alloc_failure; + } - if (b != '-') - { - flags |= flag_reproc; - break; - } + flags |= flag_next; + break; - flags |= flag_num_negative; - continue; - } - else - { sprintf (error, "%d:%d: Unexpected %c when seeking value", cur_line, e_off, b); - goto e_failed; - } - }; - }; - } - else - { - switch (top->type) - { - case json_object: - - switch (b) - { - whitespace: - continue; - - case '"': - - if (flags & flag_need_comma) - { - sprintf (error, "%d:%d: Expected , before \"", cur_line, e_off); - goto e_failed; - } - - flags |= flag_string; - - string = (json_char *) top->_reserved.object_mem; - string_length = 0; - - break; - - case '}': - - flags = (flags & ~ flag_need_comma) | flag_next; - break; - - case ',': - - if (flags & flag_need_comma) - { - flags &= ~ flag_need_comma; - break; - } - - default: - - sprintf (error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b); - goto e_failed; - }; - - break; - - case json_integer: - case json_double: - - if (g_ascii_isdigit (b)) - { - ++ num_digits; - - if (top->type == json_integer || flags & flag_num_e) - { - if (! (flags & flag_num_e)) - { - if (flags & flag_num_zero) - { sprintf (error, "%d:%d: Unexpected `0` before `%c`", cur_line, e_off, b); - goto e_failed; - } - - if (num_digits == 1 && b == '0') - flags |= flag_num_zero; - } - else - { - flags |= flag_num_e_got_sign; - num_e = (num_e * 10) + (b - '0'); - continue; - } - - top->u.integer = (top->u.integer * 10) + (b - '0'); - continue; - } - - num_fraction = (num_fraction * 10) + (b - '0'); - continue; - } - - if (b == '+' || b == '-') - { - if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign)) - { - flags |= flag_num_e_got_sign; - - if (b == '-') - flags |= flag_num_e_negative; - - continue; - } - } - else if (b == '.' && top->type == json_integer) - { - if (!num_digits) - { sprintf (error, "%d:%d: Expected digit before `.`", cur_line, e_off); - goto e_failed; - } - - top->type = json_double; - top->u.dbl = (double) top->u.integer; - - num_digits = 0; - continue; - } - - if (! (flags & flag_num_e)) - { - if (top->type == json_double) - { - if (!num_digits) - { sprintf (error, "%d:%d: Expected digit after `.`", cur_line, e_off); - goto e_failed; - } - - top->u.dbl += ((double) num_fraction) / (pow (10, (double) num_digits)); - } - - if (b == 'e' || b == 'E') - { - flags |= flag_num_e; - - if (top->type == json_integer) - { - top->type = json_double; - top->u.dbl = (double) top->u.integer; - } - - num_digits = 0; - flags &= ~ flag_num_zero; - - continue; - } - } - else - { - if (!num_digits) - { sprintf (error, "%d:%d: Expected digit after `e`", cur_line, e_off); - goto e_failed; - } - - top->u.dbl *= pow (10, (double) (flags & flag_num_e_negative ? - num_e : num_e)); - } - - if (flags & flag_num_negative) - { - if (top->type == json_integer) - top->u.integer = - top->u.integer; - else - top->u.dbl = - top->u.dbl; - } - - flags |= flag_next | flag_reproc; - break; - - default: - break; - }; - } - - if (flags & flag_reproc) - { - flags &= ~ flag_reproc; - -- i; - } - - if (flags & flag_next) - { - flags = (flags & ~ flag_next) | flag_need_comma; - - if (!top->parent) - { - /* root value done */ - - flags |= flag_done; - continue; - } - - if (top->parent->type == json_array) - flags |= flag_seek_value; - - if (!state.first_pass) - { - json_value * parent = top->parent; - - switch (parent->type) - { - case json_object: - - parent->u.object.values - [parent->u.object.length].value = top; - - break; - - case json_array: - - parent->u.array.values - [parent->u.array.length] = top; + case 'n': - break; - - default: - break; - }; - } + if ((end - i) < 3 || *(++i) != 'u' || *(++i) != 'l' || *(++i) != 'l') { + goto e_unknown_value; + } - if ( (++ top->parent->u.array.length) > state.uint_max) - goto e_overflow; - - top = top->parent; + if (!new_value(&state, &top, &root, &alloc, json_null)) { + goto e_alloc_failure; + } - continue; - } - } + flags |= flag_next; + break; - alloc = root; - } + default: - return root; + if (g_ascii_isdigit(b) || b == '-') { + if (!new_value(&state, &top, &root, &alloc, json_integer)) { + goto e_alloc_failure; + } -e_unknown_value: + if (!state.first_pass) { + while (g_ascii_isdigit(b) || b == '+' || b == '-' + || b == 'e' || b == 'E' || b == '.') { + if ((++i) == end) { + b = 0; + break; + } - sprintf (error, "%d:%d: Unknown value", cur_line, e_off); - goto e_failed; + b = *i; + } -e_alloc_failure: + flags |= flag_next | flag_reproc; + break; + } - strcpy (error, "Memory allocation failure"); - goto e_failed; + flags &= ~(flag_num_negative | flag_num_e | + flag_num_e_got_sign | flag_num_e_negative | + flag_num_zero); -e_overflow: + num_digits = 0; + num_fraction = 0; + num_e = 0; - sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off); - goto e_failed; + if (b != '-') { + flags |= flag_reproc; + break; + } -e_failed: + flags |= flag_num_negative; + continue; + } else { sprintf(error, "%d:%d: Unexpected %c when seeking value", + cur_line, e_off, b); + goto e_failed; } + } + ; + } + ; + } else { + switch (top->type) { + case json_object: + + switch (b) { +whitespace: + continue; + + case '"': + + if (flags & flag_need_comma) { + sprintf(error, "%d:%d: Expected , before \"", cur_line, e_off); + goto e_failed; + } + + flags |= flag_string; + + string = (json_char *) top->_reserved.object_mem; + string_length = 0; + + break; + + case '}': + + flags = (flags & ~flag_need_comma) | flag_next; + break; + + case ',': + + if (flags & flag_need_comma) { + flags &= ~flag_need_comma; + break; + } + + default: + + sprintf(error, "%d:%d: Unexpected `%c` in object", cur_line, e_off, b); + goto e_failed; + } + ; + + break; + + case json_integer: + case json_double: + + if (g_ascii_isdigit(b)) { + ++num_digits; + + if (top->type == json_integer || flags & flag_num_e) { + if (!(flags & flag_num_e)) { + if (flags & flag_num_zero) { + sprintf(error, + "%d:%d: Unexpected `0` before `%c`", + cur_line, e_off, b); + goto e_failed; + } + + if (num_digits == 1 && b == '0') { + flags |= flag_num_zero; + } + } else { + flags |= flag_num_e_got_sign; + num_e = (num_e * 10) + (b - '0'); + continue; + } + + top->u.integer = (top->u.integer * 10) + (b - '0'); + continue; + } + + num_fraction = (num_fraction * 10) + (b - '0'); + continue; + } + + if (b == '+' || b == '-') { + if ((flags & flag_num_e) && !(flags & flag_num_e_got_sign)) { + flags |= flag_num_e_got_sign; + + if (b == '-') { + flags |= flag_num_e_negative; + } + + continue; + } + } else if (b == '.' && top->type == json_integer) { + if (!num_digits) { + sprintf(error, "%d:%d: Expected digit before `.`", cur_line, + e_off); + goto e_failed; + } + + top->type = json_double; + top->u.dbl = (double) top->u.integer; + + num_digits = 0; + continue; + } + + if (!(flags & flag_num_e)) { + if (top->type == json_double) { + if (!num_digits) { + sprintf(error, "%d:%d: Expected digit after `.`", + cur_line, e_off); + goto e_failed; + } + + top->u.dbl += ((double) num_fraction) / + (pow(10, (double) num_digits)); + } + + if (b == 'e' || b == 'E') { + flags |= flag_num_e; + + if (top->type == json_integer) { + top->type = json_double; + top->u.dbl = (double) top->u.integer; + } + + num_digits = 0; + flags &= ~flag_num_zero; + + continue; + } + } else { + if (!num_digits) { + sprintf(error, "%d:%d: Expected digit after `e`", cur_line, + e_off); + goto e_failed; + } + + top->u.dbl *= + pow(10, + (double) (flags & flag_num_e_negative ? -num_e : num_e)); + } + + if (flags & flag_num_negative) { + if (top->type == json_integer) { + top->u.integer = -top->u.integer; + } else { + top->u.dbl = -top->u.dbl; + } + } + + flags |= flag_next | flag_reproc; + break; + + default: + break; + } + ; + } + + if (flags & flag_reproc) { + flags &= ~flag_reproc; + --i; + } + + if (flags & flag_next) { + flags = (flags & ~flag_next) | flag_need_comma; + + if (!top->parent) { + /* root value done */ + + flags |= flag_done; + continue; + } + + if (top->parent->type == json_array) { + flags |= flag_seek_value; + } + + if (!state.first_pass) { + json_value * parent = top->parent; + + switch (parent->type) { + case json_object: + + parent->u.object.values + [parent->u.object.length].value = top; + + break; + + case json_array: + + parent->u.array.values + [parent->u.array.length] = top; - if (error_buf) - { - if (*error) - strcpy (error_buf, error); - else - strcpy (error_buf, "Unknown error"); - } + break; - if (state.first_pass) - alloc = root; + default: + break; + } + ; + } - while (alloc) - { - top = alloc->_reserved.next_alloc; - state.settings.mem_free (alloc, state.settings.user_data); - alloc = top; - } + if ((++top->parent->u.array.length) > state.uint_max) { + goto e_overflow; + } - if (!state.first_pass) - json_value_free_ex (&state.settings, root); + top = top->parent; - return 0; + continue; + } + } + + alloc = root; + } + + return root; + +e_unknown_value: + + sprintf(error, "%d:%d: Unknown value", cur_line, e_off); + goto e_failed; + +e_alloc_failure: + + strcpy(error, "Memory allocation failure"); + goto e_failed; + +e_overflow: + + sprintf(error, "%d:%d: Too long (caught overflow)", cur_line, e_off); + goto e_failed; + +e_failed: + + if (error_buf) { + if (*error) { + strcpy(error_buf, error); + } else { + strcpy(error_buf, "Unknown error"); + } + } + + if (state.first_pass) { + alloc = root; + } + + while (alloc) { + top = alloc->_reserved.next_alloc; + state.settings.mem_free(alloc, state.settings.user_data); + alloc = top; + } + + if (!state.first_pass) { + json_value_free_ex(&state.settings, root); + } + + return 0; } -json_value * json_parse (const json_char * json, size_t length) +json_value * json_parse(const json_char * json, size_t length) { - json_settings settings = { 0 }; - return json_parse_ex (&settings, json, length, 0); + json_settings settings = { 0 }; + + return json_parse_ex(&settings, json, length, 0); } -void json_value_free_ex (json_settings * settings, json_value * value) +void json_value_free_ex(json_settings * settings, json_value * value) { - json_value * cur_value; + json_value * cur_value; - if (!value) - return; + if (!value) { + return; + } - value->parent = 0; + value->parent = 0; - while (value) - { - switch (value->type) - { - case json_array: + while (value) { + switch (value->type) { + case json_array: - if (!value->u.array.length) - { - settings->mem_free (value->u.array.values, settings->user_data); - break; - } + if (!value->u.array.length) { + settings->mem_free(value->u.array.values, settings->user_data); + break; + } - value = value->u.array.values [-- value->u.array.length]; - continue; + value = value->u.array.values [--value->u.array.length]; + continue; - case json_object: + case json_object: - if (!value->u.object.length) - { - settings->mem_free (value->u.object.values, settings->user_data); - break; - } + if (!value->u.object.length) { + settings->mem_free(value->u.object.values, settings->user_data); + break; + } - value = value->u.object.values [-- value->u.object.length].value; - continue; + value = value->u.object.values [--value->u.object.length].value; + continue; - case json_string: + case json_string: - settings->mem_free (value->u.string.ptr, settings->user_data); - break; + settings->mem_free(value->u.string.ptr, settings->user_data); + break; - default: - break; - }; + default: + break; + } + ; - cur_value = value; - value = value->parent; - settings->mem_free (cur_value, settings->user_data); - } + cur_value = value; + value = value->parent; + settings->mem_free(cur_value, settings->user_data); + } } -void json_value_free (json_value * value) +void json_value_free(json_value * value) { - json_settings settings = { 0 }; - settings.mem_free = default_free; - json_value_free_ex (&settings, value); + json_settings settings = { 0 }; + + settings.mem_free = default_free; + json_value_free_ex(&settings, value); } @@ -50,220 +50,211 @@ #include <string.h> - extern "C" - { +extern "C" +{ #endif -typedef struct -{ - unsigned long max_memory; - int settings; +typedef struct { + unsigned long max_memory; + int settings; - /* Custom allocator support (leave null to use malloc/free) - */ + /* Custom allocator support (leave null to use malloc/free) + */ - void * (* mem_alloc) (size_t, int zero, void * user_data); - void (* mem_free) (void *, void * user_data); + void * (*mem_alloc)(size_t, int zero, void * user_data); + void (* mem_free)(void *, void * user_data); - void * user_data; /* will be passed to mem_alloc and mem_free */ + void * user_data; /* will be passed to mem_alloc and mem_free */ } json_settings; #define json_enable_comments 0x01 -typedef enum -{ - json_none, - json_object, - json_array, - json_integer, - json_double, - json_string, - json_boolean, - json_null +typedef enum { + json_none, + json_object, + json_array, + json_integer, + json_double, + json_string, + json_boolean, + json_null } json_type; extern const struct _json_value json_value_none; -typedef struct _json_value -{ - struct _json_value * parent; +typedef struct _json_value { + struct _json_value * parent; - json_type type; + json_type type; - union - { - int boolean; - json_int_t integer; - double dbl; + union { + int boolean; + json_int_t integer; + double dbl; - struct - { - unsigned int length; - json_char * ptr; /* null terminated */ + struct { + unsigned int length; + json_char * ptr; /* null terminated */ - } string; + } string; - struct - { - unsigned int length; + struct { + unsigned int length; - struct - { - json_char * name; - unsigned int name_length; + struct { + json_char * name; + unsigned int name_length; - struct _json_value * value; + struct _json_value * value; - } * values; + } * values; - #if defined(__cplusplus) && __cplusplus >= 201103L - decltype(values) begin () const - { return values; - } - decltype(values) end () const - { return values + length; - } - #endif + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin() const + { return values; } + decltype(values) end() const + { return values + length; } + #endif - } object; + } object; - struct - { - unsigned int length; - struct _json_value ** values; + struct { + unsigned int length; + struct _json_value ** values; - #if defined(__cplusplus) && __cplusplus >= 201103L - decltype(values) begin () const - { return values; - } - decltype(values) end () const - { return values + length; - } - #endif + #if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin() const + { return values; } + decltype(values) end() const + { return values + length; } + #endif - } array; + } array; - } u; + } u; - union - { - struct _json_value * next_alloc; - void * object_mem; + union { + struct _json_value * next_alloc; + void * object_mem; - } _reserved; + } _reserved; - /* Some C++ operator sugar */ + /* Some C++ operator sugar */ #ifdef __cplusplus - public: - - inline _json_value () - { memset (this, 0, sizeof (_json_value)); - } - - inline const struct _json_value &operator [] (int index) const - { - if (type != json_array || index < 0 - || ((unsigned int) index) >= u.array.length) - { - return json_value_none; - } - - return *u.array.values [index]; - } - - inline const struct _json_value &operator [] (const char * index) const - { - if (type != json_object) - return json_value_none; - - for (unsigned int i = 0; i < u.object.length; ++ i) - if (!strcmp (u.object.values [i].name, index)) - return *u.object.values [i].value; - - return json_value_none; - } - - inline operator const char * () const - { - switch (type) - { - case json_string: - return u.string.ptr; - - default: - return ""; - }; - } - - inline operator json_int_t () const - { - switch (type) - { - case json_integer: - return u.integer; - - case json_double: - return (json_int_t) u.dbl; - - default: - return 0; - }; - } - - inline operator bool () const - { - if (type != json_boolean) - return false; - - return u.boolean != 0; - } - - inline operator double () const - { - switch (type) - { - case json_integer: - return (double) u.integer; - - case json_double: - return u.dbl; - - default: - return 0; - }; - } +public: + + inline _json_value () + { + memset(this, 0, sizeof(_json_value)); + } + + inline const struct _json_value &operator [](int index) const + { + if (type != json_array || index < 0 + || ((unsigned int)index) >= u.array.length) { + return json_value_none; + } + + return *u.array.values [index]; + } + + inline const struct _json_value &operator [](const char * index) const + { + if (type != json_object) { + return json_value_none; + } + + for (unsigned int i = 0; i < u.object.length; ++i) { + if (!strcmp(u.object.values [i].name, index)) { + return *u.object.values [i].value; + } + } + + return json_value_none; + } + + inline operator const char *() const + { + switch (type) { + case json_string: + return u.string.ptr; + + default: + return ""; + } + ; + } + + inline operator json_int_t() const + { + switch (type) { + case json_integer: + return u.integer; + + case json_double: + return (json_int_t)u.dbl; + + default: + return 0; + } + ; + } + + inline operator bool() const + { + if (type != json_boolean) { + return false; + } + + return u.boolean != 0; + } + + inline operator double() const + { + switch (type) { + case json_integer: + return (double)u.integer; + + case json_double: + return u.dbl; + + default: + return 0; + } + ; + } #endif } json_value; -json_value * json_parse (const json_char * json, - size_t length); +json_value * json_parse(const json_char * json, + size_t length); #define json_error_max 128 -json_value * json_parse_ex (json_settings * settings, - const json_char * json, - size_t length, - char * error); +json_value * json_parse_ex(json_settings * settings, + const json_char * json, + size_t length, + char * error); -void json_value_free (json_value *); +void json_value_free(json_value *); /* Not usually necessary, unless you used a custom mem_alloc and now want to * use a custom mem_free. */ -void json_value_free_ex (json_settings * settings, - json_value *); +void json_value_free_ex(json_settings * settings, + json_value *); #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif #endif diff --git a/lib/json_util.c b/lib/json_util.c index ff1d5bb9..b4f5078a 100644 --- a/lib/json_util.c +++ b/lib/json_util.c @@ -27,36 +27,41 @@ #include "json_util.h" -json_value *json_o_get( const json_value *obj, const json_char *name ) -{ +json_value *json_o_get(const json_value *obj, const json_char *name) +{ int i; - - if( !obj || obj->type != json_object ) + + if (!obj || obj->type != json_object) { return NULL; + } - for( i = 0; i < obj->u.object.length; ++ i) - if( strcmp( obj->u.object.values[i].name, name ) == 0 ) + for (i = 0; i < obj->u.object.length; ++i) { + if (strcmp(obj->u.object.values[i].name, name) == 0) { return obj->u.object.values[i].value; + } + } return NULL; } -const char *json_o_str( const json_value *obj, const json_char *name ) -{ - json_value *ret = json_o_get( obj, name ); - - if( ret && ret->type == json_string ) +const char *json_o_str(const json_value *obj, const json_char *name) +{ + json_value *ret = json_o_get(obj, name); + + if (ret && ret->type == json_string) { return ret->u.string.ptr; - else + } else { return NULL; + } } -char *json_o_strdup( const json_value *obj, const json_char *name ) +char *json_o_strdup(const json_value *obj, const json_char *name) { - json_value *ret = json_o_get( obj, name ); - - if( ret && ret->type == json_string && ret->u.string.ptr ) - return g_memdup( ret->u.string.ptr, ret->u.string.length + 1 ); - else + json_value *ret = json_o_get(obj, name); + + if (ret && ret->type == json_string && ret->u.string.ptr) { + return g_memdup(ret->u.string.ptr, ret->u.string.length + 1); + } else { return NULL; + } } diff --git a/lib/json_util.h b/lib/json_util.h index 7eb49515..363efc89 100644 --- a/lib/json_util.h +++ b/lib/json_util.h @@ -25,11 +25,11 @@ #define JSON_O_FOREACH(o, k, v) \ char *k; json_value *v; int __i; \ - for( __i = 0; ( __i < (o)->u.object.length ) && \ - ( k = (o)->u.object.values[__i].name ) && \ - ( v = (o)->u.object.values[__i].value ); \ - __i ++ ) + for (__i = 0; (__i < (o)->u.object.length) && \ + (k = (o)->u.object.values[__i].name) && \ + (v = (o)->u.object.values[__i].value); \ + __i ++) -json_value *json_o_get( const json_value *obj, const json_char *name ); -const char *json_o_str( const json_value *obj, const json_char *name ); -char *json_o_strdup( const json_value *obj, const json_char *name ); +json_value *json_o_get(const json_value *obj, const json_char *name); +const char *json_o_str(const json_value *obj, const json_char *name); +char *json_o_strdup(const json_value *obj, const json_char *name); @@ -18,6 +18,7 @@ void md5_append(md5_state_t *ctx, const guint8 *buf, unsigned int len) void md5_finish(md5_state_t *ctx, guint8 digest[MD5_HASH_SIZE]) { gsize digest_len = MD5_HASH_SIZE; + g_checksum_get_digest(*ctx, digest, &digest_len); g_checksum_free(*ctx); } @@ -27,6 +28,7 @@ void md5_finish(md5_state_t *ctx, guint8 digest[MD5_HASH_SIZE]) void md5_digest_keep(md5_state_t *ctx, guint8 digest[MD5_HASH_SIZE]) { md5_state_t copy = g_checksum_copy(*ctx); + md5_finish(©, digest); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -54,9 +54,11 @@ void strip_linefeed(gchar *text) int i, j; gchar *text2 = g_malloc(strlen(text) + 1); - for (i = 0, j = 0; text[i]; i++) - if (text[i] != '\r') + for (i = 0, j = 0; text[i]; i++) { + if (text[i] != '\r') { text2[j++] = text[i]; + } + } text2[j] = '\0'; strcpy(text, text2); @@ -74,47 +76,47 @@ time_t get_time(int year, int month, int day, int hour, int min, int sec) tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; - + return mktime(&tm); } -time_t mktime_utc( struct tm *tp ) +time_t mktime_utc(struct tm *tp) { struct tm utc; time_t res, tres; - + tp->tm_isdst = -1; - res = mktime( tp ); + res = mktime(tp); /* Problem is, mktime() just gave us the GMT timestamp for the given local time... While the given time WAS NOT local. So we should fix this now. - + Now I could choose between messing with environment variables (kludgy) or using timegm() (not portable)... Or doing the following, which I actually prefer... - + tzset() may also work but in other places I actually want to use local time. - + FFFFFFFFFFFFFFFFFFFFFUUUUUUUUUUUUUUUUUUUU!! */ - gmtime_r( &res, &utc ); + gmtime_r(&res, &utc); utc.tm_isdst = -1; - if( utc.tm_hour == tp->tm_hour && utc.tm_min == tp->tm_min ) + if (utc.tm_hour == tp->tm_hour && utc.tm_min == tp->tm_min) { /* Sweet! We're in UTC right now... */ return res; - - tres = mktime( &utc ); + } + + tres = mktime(&utc); res += res - tres; - + /* Yes, this is a hack. And it will go wrong around DST changes. BUT this is more likely to be threadsafe than messing with environment variables, and possibly more portable... */ - + return res; } -typedef struct htmlentity -{ +typedef struct htmlentity { char code[7]; char is[3]; } htmlentity_t; @@ -150,322 +152,330 @@ static const htmlentity_t ent[] = { "", "" } }; -void strip_html( char *in ) +void strip_html(char *in) { char *start = in; - char out[strlen(in)+1]; + char out[strlen(in) + 1]; char *s = out, *cs; int i, matched; int taglen; - - memset( out, 0, sizeof( out ) ); - - while( *in ) - { - if( *in == '<' && ( g_ascii_isalpha( *(in+1) ) || *(in+1) == '/' ) ) - { + + memset(out, 0, sizeof(out)); + + while (*in) { + if (*in == '<' && (g_ascii_isalpha(*(in + 1)) || *(in + 1) == '/')) { /* If in points at a < and in+1 points at a letter or a slash, this is probably a HTML-tag. Try to find a closing > and continue there. If the > can't be found, assume that it wasn't a HTML-tag after all. */ - + cs = in; - - while( *in && *in != '>' ) - 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, "b", taglen) == 0 ) + if (*in) { + if (g_strncasecmp(cs + 1, "b", taglen) == 0) { *(s++) = '\x02'; - else if( g_strncasecmp( cs+1, "/b", taglen) == 0 ) + } else if (g_strncasecmp(cs + 1, "/b", taglen) == 0) { *(s++) = '\x02'; - else if( g_strncasecmp( cs+1, "i", taglen) == 0 ) + } else if (g_strncasecmp(cs + 1, "i", taglen) == 0) { *(s++) = '\x1f'; - else if( g_strncasecmp( cs+1, "/i", taglen) == 0 ) + } else if (g_strncasecmp(cs + 1, "/i", taglen) == 0) { *(s++) = '\x1f'; - else if( g_strncasecmp( cs+1, "br", taglen) == 0 ) + } else if (g_strncasecmp(cs + 1, "br", taglen) == 0) { *(s++) = '\n'; - in ++; - } - else - { + } + in++; + } else { in = cs; *(s++) = *(in++); } - } - else if( *in == '&' ) - { + } else if (*in == '&') { cs = ++in; - while( *in && g_ascii_isalpha( *in ) ) - in ++; - - if( *in == ';' ) in ++; + while (*in && g_ascii_isalpha(*in)) { + in++; + } + + if (*in == ';') { + in++; + } matched = 0; - - for( i = 0; *ent[i].code; i ++ ) - if( g_strncasecmp( ent[i].code, cs, strlen( ent[i].code ) ) == 0 ) - { + + for (i = 0; *ent[i].code; i++) { + if (g_strncasecmp(ent[i].code, cs, strlen(ent[i].code)) == 0) { int j; - - for( j = 0; ent[i].is[j]; j ++ ) + + for (j = 0; ent[i].is[j]; j++) { *(s++) = ent[i].is[j]; - + } + matched = 1; break; } + } /* None of the entities were matched, so return the string */ - if( !matched ) - { + if (!matched) { in = cs - 1; *(s++) = *(in++); } - } - else - { + } else { *(s++) = *(in++); } } - - strcpy( start, out ); + + strcpy(start, out); } -char *escape_html( const char *html ) +char *escape_html(const char *html) { const char *c = html; GString *ret; char *str; - - if( html == NULL ) - return( NULL ); - - ret = g_string_new( "" ); - - while( *c ) - { - switch( *c ) - { - case '&': - ret = g_string_append( ret, "&" ); - break; - case '<': - ret = g_string_append( ret, "<" ); - break; - case '>': - ret = g_string_append( ret, ">" ); - break; - case '"': - ret = g_string_append( ret, """ ); - break; - default: - ret = g_string_append_c( ret, *c ); + + if (html == NULL) { + return(NULL); + } + + ret = g_string_new(""); + + while (*c) { + switch (*c) { + case '&': + ret = g_string_append(ret, "&"); + break; + case '<': + ret = g_string_append(ret, "<"); + break; + case '>': + ret = g_string_append(ret, ">"); + break; + case '"': + ret = g_string_append(ret, """); + break; + default: + ret = g_string_append_c(ret, *c); } - c ++; + c++; } - + str = ret->str; - g_string_free( ret, FALSE ); - return( str ); + g_string_free(ret, FALSE); + return(str); } /* Decode%20a%20file%20name */ -void http_decode( char *s ) +void http_decode(char *s) { char *t; int i, j, k; - - t = g_new( char, strlen( s ) + 1 ); - - for( i = j = 0; s[i]; i ++, j ++ ) - { - if( s[i] == '%' ) - { - if( sscanf( s + i + 1, "%2x", &k ) ) - { + + t = g_new(char, strlen(s) + 1); + + for (i = j = 0; s[i]; i++, j++) { + if (s[i] == '%') { + if (sscanf(s + i + 1, "%2x", &k)) { t[j] = k; i += 2; - } - else - { + } else { *t = 0; break; } - } - else - { + } else { t[j] = s[i]; } } t[j] = 0; - - strcpy( s, t ); - g_free( t ); + + strcpy(s, t); + g_free(t); } /* Warning: This one explodes the string. Worst-cases can make the string 3x its original size! */ /* This fuction is safe, but make sure you call it safely as well! */ -void http_encode( char *s ) +void http_encode(char *s) { - char t[strlen(s)+1]; + char t[strlen(s) + 1]; int i, j; - - strcpy( t, s ); - for( i = j = 0; t[i]; i ++, j ++ ) - { + + strcpy(t, s); + for (i = j = 0; t[i]; i++, j++) { /* Warning: g_ascii_isalnum() is locale-aware, so don't use it here! */ - if( ( t[i] >= 'A' && t[i] <= 'Z' ) || - ( t[i] >= 'a' && t[i] <= 'z' ) || - ( t[i] >= '0' && t[i] <= '9' ) || - strchr( "._-~", t[i] ) ) - { + if ((t[i] >= 'A' && t[i] <= 'Z') || + (t[i] >= 'a' && t[i] <= 'z') || + (t[i] >= '0' && t[i] <= '9') || + strchr("._-~", t[i])) { s[j] = t[i]; - } - else - { - sprintf( s + j, "%%%02X", ((unsigned char*)t)[i] ); + } else { + sprintf(s + j, "%%%02X", ((unsigned char *) t)[i]); j += 2; } } s[j] = 0; } -/* Strip newlines from a string. Modifies the string passed to it. */ -char *strip_newlines( char *source ) +/* Strip newlines from a string. Modifies the string passed to it. */ +char *strip_newlines(char *source) { - int i; + int i; - for( i = 0; source[i] != '\0'; i ++ ) - if( source[i] == '\n' || source[i] == '\r' ) + for (i = 0; source[i] != '\0'; i++) { + if (source[i] == '\n' || source[i] == '\r') { source[i] = ' '; - + } + } + return source; } /* Wrap an IPv4 address into IPv6 space. Not thread-safe... */ -char *ipv6_wrap( char *src ) +char *ipv6_wrap(char *src) { static char dst[64]; int i; - - for( i = 0; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) + + for (i = 0; src[i]; i++) { + if ((src[i] < '0' || src[i] > '9') && src[i] != '.') { break; - + } + } + /* Hmm, it's not even an IP... */ - if( src[i] ) + if (src[i]) { return src; - - g_snprintf( dst, sizeof( dst ), "::ffff:%s", src ); - + } + + g_snprintf(dst, sizeof(dst), "::ffff:%s", src); + return dst; } /* Unwrap an IPv4 address into IPv6 space. Thread-safe, because it's very simple. :-) */ -char *ipv6_unwrap( char *src ) +char *ipv6_unwrap(char *src) { int i; - - if( g_strncasecmp( src, "::ffff:", 7 ) != 0 ) + + if (g_strncasecmp(src, "::ffff:", 7) != 0) { return src; - - for( i = 7; src[i]; i ++ ) - if( ( src[i] < '0' || src[i] > '9' ) && src[i] != '.' ) + } + + for (i = 7; src[i]; i++) { + if ((src[i] < '0' || src[i] > '9') && src[i] != '.') { break; - + } + } + /* Hmm, it's not even an IP... */ - if( src[i] ) + if (src[i]) { return src; - - return ( src + 7 ); + } + + return (src + 7); } /* Convert from one charset to another. - + from_cs, to_cs: Source and destination charsets src, dst: Source and destination strings size: Size if src. 0 == use strlen(). strlen() is not reliable for UNICODE/UTF16 strings though. maxbuf: Maximum number of bytes to write to dst - + Returns the number of bytes written to maxbuf or -1 on an error. */ -signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ) +signed int do_iconv(char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf) { GIConv cd; size_t res; size_t inbytesleft, outbytesleft; char *inbuf = src; char *outbuf = dst; - - cd = g_iconv_open( to_cs, from_cs ); - if( cd == (GIConv) -1 ) + + cd = g_iconv_open(to_cs, from_cs); + if (cd == (GIConv) - 1) { return -1; - - inbytesleft = size ? size : strlen( src ); + } + + inbytesleft = size ? size : strlen(src); outbytesleft = maxbuf - 1; - res = g_iconv( cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + res = g_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); *outbuf = '\0'; - g_iconv_close( cd ); - - if( res != 0 ) + g_iconv_close(cd); + + if (res != 0) { return -1; - else + } else { return outbuf - dst; + } } /* A wrapper for /dev/urandom. * If /dev/urandom is not present or not usable, it calls abort() * to prevent bitlbee from working without a decent entropy source */ -void random_bytes( unsigned char *buf, int count ) +void random_bytes(unsigned char *buf, int count) { int fd; - if( ( ( fd = open( "/dev/urandom", O_RDONLY ) ) == -1 ) || - ( read( fd, buf, count ) == -1 ) ) - { - log_message( LOGLVL_ERROR, "/dev/urandom not present - aborting" ); + + if (((fd = open("/dev/urandom", O_RDONLY)) == -1) || + (read(fd, buf, count) == -1)) { + log_message(LOGLVL_ERROR, "/dev/urandom not present - aborting"); abort(); } - close( fd ); + close(fd); } -int is_bool( char *value ) +int is_bool(char *value) { - if( *value == 0 ) + if (*value == 0) { return 0; - - if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) + } + + if ((g_strcasecmp(value, + "true") == 0) || (g_strcasecmp(value, "yes") == 0) || (g_strcasecmp(value, "on") == 0)) { return 1; - if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) + } + if ((g_strcasecmp(value, + "false") == 0) || (g_strcasecmp(value, "no") == 0) || (g_strcasecmp(value, "off") == 0)) { return 1; - - while( *value ) - if( !g_ascii_isdigit( *value ) ) + } + + while (*value) { + if (!g_ascii_isdigit(*value)) { return 0; - else - value ++; - + } else { + value++; + } + } + return 1; } -int bool2int( char *value ) +int bool2int(char *value) { int i; - - if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) ) + + if ((g_strcasecmp(value, + "true") == 0) || (g_strcasecmp(value, "yes") == 0) || (g_strcasecmp(value, "on") == 0)) { return 1; - if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) ) + } + if ((g_strcasecmp(value, + "false") == 0) || (g_strcasecmp(value, "no") == 0) || (g_strcasecmp(value, "off") == 0)) { return 0; - - if( sscanf( value, "%d", &i ) == 1 ) + } + + if (sscanf(value, "%d", &i) == 1) { return i; - + } + return 0; } -struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ) -{ +struct ns_srv_reply **srv_lookup(char *service, char *protocol, char *domain) +{ struct ns_srv_reply **replies = NULL; + #ifdef HAVE_RESOLV_A struct ns_srv_reply *reply = NULL; char name[1024]; @@ -474,148 +484,148 @@ struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ) ns_msg nsh; ns_rr rr; int n, len, size; - - g_snprintf( name, sizeof( name ), "_%s._%s.%s", service, protocol, domain ); - - if( ( size = res_query( name, ns_c_in, ns_t_srv, querybuf, sizeof( querybuf ) ) ) <= 0 ) + + g_snprintf(name, sizeof(name), "_%s._%s.%s", service, protocol, domain); + + if ((size = res_query(name, ns_c_in, ns_t_srv, querybuf, sizeof(querybuf))) <= 0) { return NULL; - - if( ns_initparse( querybuf, size, &nsh ) != 0 ) + } + + if (ns_initparse(querybuf, size, &nsh) != 0) { return NULL; - + } + n = 0; - while( ns_parserr( &nsh, ns_s_an, n, &rr ) == 0 ) - { + while (ns_parserr(&nsh, ns_s_an, n, &rr) == 0) { char name[NS_MAXDNAME]; - if( ns_rr_rdlen( rr ) < 7) - break; + if (ns_rr_rdlen(rr) < 7) { + break; + } - buf = ns_rr_rdata( rr ); - - if( dn_expand(querybuf, querybuf + size, &buf[6], name, NS_MAXDNAME) == -1 ) + buf = ns_rr_rdata(rr); + + if (dn_expand(querybuf, querybuf + size, &buf[6], name, NS_MAXDNAME) == -1) { break; + } len = strlen(name) + 1; - - reply = g_malloc( sizeof( struct ns_srv_reply ) + len ); - memcpy( reply->name, name, len ); - - reply->prio = ( buf[0] << 8 ) | buf[1]; - reply->weight = ( buf[2] << 8 ) | buf[3]; - reply->port = ( buf[4] << 8 ) | buf[5]; - - n ++; - replies = g_renew( struct ns_srv_reply *, replies, n + 1 ); - replies[n-1] = reply; - } - if( replies ) + + reply = g_malloc(sizeof(struct ns_srv_reply) + len); + memcpy(reply->name, name, len); + + reply->prio = (buf[0] << 8) | buf[1]; + reply->weight = (buf[2] << 8) | buf[3]; + reply->port = (buf[4] << 8) | buf[5]; + + n++; + replies = g_renew(struct ns_srv_reply *, replies, n + 1); + replies[n - 1] = reply; + } + if (replies) { replies[n] = NULL; + } #endif - + return replies; } -void srv_free( struct ns_srv_reply **srv ) +void srv_free(struct ns_srv_reply **srv) { int i; - - if( srv == NULL ) + + if (srv == NULL) { return; - - for( i = 0; srv[i]; i ++ ) - g_free( srv[i] ); - g_free( srv ); + } + + for (i = 0; srv[i]; i++) { + g_free(srv[i]); + } + g_free(srv); } /* Word wrapping. Yes, I know this isn't UTF-8 clean. I'm willing to take the risk. */ -char *word_wrap( const char *msg, int line_len ) +char *word_wrap(const char *msg, int line_len) { - GString *ret = g_string_sized_new( strlen( msg ) + 16 ); - - while( strlen( msg ) > line_len ) - { + GString *ret = g_string_sized_new(strlen(msg) + 16); + + while (strlen(msg) > line_len) { int i; - + /* First try to find out if there's a newline already. Don't want to add more splits than necessary. */ - for( i = line_len; i > 0 && msg[i] != '\n'; i -- ); - if( msg[i] == '\n' ) - { - g_string_append_len( ret, msg, i + 1 ); + for (i = line_len; i > 0 && msg[i] != '\n'; i--) { + ; + } + if (msg[i] == '\n') { + g_string_append_len(ret, msg, i + 1); msg += i + 1; continue; } - - for( i = line_len; i > 0; i -- ) - { - if( msg[i] == '-' ) - { - g_string_append_len( ret, msg, i + 1 ); - g_string_append_c( ret, '\n' ); + + for (i = line_len; i > 0; i--) { + if (msg[i] == '-') { + g_string_append_len(ret, msg, i + 1); + g_string_append_c(ret, '\n'); msg += i + 1; break; - } - else if( msg[i] == ' ' ) - { - g_string_append_len( ret, msg, i ); - g_string_append_c( ret, '\n' ); + } else if (msg[i] == ' ') { + g_string_append_len(ret, msg, i); + g_string_append_c(ret, '\n'); msg += i + 1; break; } } - if( i == 0 ) - { - g_string_append_len( ret, msg, line_len ); - g_string_append_c( ret, '\n' ); + if (i == 0) { + g_string_append_len(ret, msg, line_len); + g_string_append_c(ret, '\n'); msg += line_len; } } - g_string_append( ret, msg ); - - return g_string_free( ret, FALSE ); + g_string_append(ret, msg); + + return g_string_free(ret, FALSE); } -gboolean ssl_sockerr_again( void *ssl ) +gboolean ssl_sockerr_again(void *ssl) { - if( ssl ) + if (ssl) { return ssl_errno == SSL_AGAIN; - else + } else { return sockerr_again(); + } } /* Returns values: -1 == Failure (base64-decoded to something unexpected) 0 == Okay 1 == Password doesn't match the hash. */ -int md5_verify_password( char *password, char *hash ) +int md5_verify_password(char *password, char *hash) { md5_byte_t *pass_dec = NULL; md5_byte_t pass_md5[16]; md5_state_t md5_state; int ret = -1, i; - - if( base64_decode( hash, &pass_dec ) == 21 ) - { - md5_init( &md5_state ); - md5_append( &md5_state, (md5_byte_t*) password, strlen( password ) ); - md5_append( &md5_state, (md5_byte_t*) pass_dec + 16, 5 ); /* Hmmm, salt! */ - md5_finish( &md5_state, pass_md5 ); - - for( i = 0; i < 16; i ++ ) - { - if( pass_dec[i] != pass_md5[i] ) - { + + if (base64_decode(hash, &pass_dec) == 21) { + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *) password, strlen(password)); + md5_append(&md5_state, (md5_byte_t *) pass_dec + 16, 5); /* Hmmm, salt! */ + md5_finish(&md5_state, pass_md5); + + for (i = 0; i < 16; i++) { + if (pass_dec[i] != pass_md5[i]) { ret = 1; break; } } - + /* If we reached the end of the loop, it was a match! */ - if( i == 16 ) + if (i == 16) { ret = 0; + } } - - g_free( pass_dec ); + + g_free(pass_dec); return ret; } @@ -623,119 +633,125 @@ int md5_verify_password( char *password, char *hash ) /* Split commands (root-style, *not* IRC-style). Handles "quoting of" white\ space in 'various ways'. Returns a NULL-terminated static char** so watch out with nested use! Definitely not thread-safe. */ -char **split_command_parts( char *command, int limit ) +char **split_command_parts(char *command, int limit) { - static char *cmd[IRC_MAX_ARGS+1]; + static char *cmd[IRC_MAX_ARGS + 1]; char *s, q = 0; int k; - - memset( cmd, 0, sizeof( cmd ) ); + + memset(cmd, 0, sizeof(cmd)); cmd[0] = command; k = 1; - for( s = command; *s && k < IRC_MAX_ARGS; s ++ ) - { - if( *s == ' ' && !q ) - { + for (s = command; *s && k < IRC_MAX_ARGS; s++) { + if (*s == ' ' && !q) { *s = 0; - while( *++s == ' ' ); - if( k != limit && (*s == '"' || *s == '\'') ) - { + while (*++s == ' ') { + ; + } + if (k != limit && (*s == '"' || *s == '\'')) { q = *s; - s ++; + s++; } - if( *s ) - { + if (*s) { cmd[k++] = s; if (limit && k > limit) { break; } - s --; - } - else - { + s--; + } else { break; } - } - else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) ) - { + } else if (*s == '\\' && ((!q && s[1]) || (q && q == s[1]))) { char *cpy; - - for( cpy = s; *cpy; cpy ++ ) + + for (cpy = s; *cpy; cpy++) { cpy[0] = cpy[1]; - } - else if( *s == q ) - { + } + } else if (*s == q) { q = *s = 0; } } - + /* Full zero-padding for easier argc checking. */ - while( k <= IRC_MAX_ARGS ) + while (k <= IRC_MAX_ARGS) { cmd[k++] = NULL; - + } + return cmd; } -char *get_rfc822_header( const char *text, const char *header, int len ) +char *get_rfc822_header(const char *text, const char *header, int len) { - int hlen = strlen( header ), i; + int hlen = strlen(header), i; const char *ret; - - if( text == NULL ) + + if (text == NULL) { return NULL; - - if( len == 0 ) - len = strlen( text ); - + } + + if (len == 0) { + len = strlen(text); + } + i = 0; - while( ( i + hlen ) < len ) - { + while ((i + hlen) < len) { /* Maybe this is a bit over-commented, but I just hate this part... */ - if( g_strncasecmp( text + i, header, hlen ) == 0 ) - { + if (g_strncasecmp(text + i, header, hlen) == 0) { /* Skip to the (probable) end of the header */ i += hlen; - + /* Find the first non-[: \t] character */ - while( i < len && ( text[i] == ':' || text[i] == ' ' || text[i] == '\t' ) ) i ++; - + while (i < len && (text[i] == ':' || text[i] == ' ' || text[i] == '\t')) { + i++; + } + /* Make sure we're still inside the string */ - if( i >= len ) return( NULL ); - + if (i >= len) { + return(NULL); + } + /* Save the position */ ret = text + i; - + /* Search for the end of this line */ - while( i < len && text[i] != '\r' && text[i] != '\n' ) i ++; - + while (i < len && text[i] != '\r' && text[i] != '\n') { + i++; + } + /* Make sure we're still inside the string */ - if( i >= len ) return( NULL ); - + if (i >= len) { + return(NULL); + } + /* Copy the found data */ - return( g_strndup( ret, text + i - ret ) ); + return(g_strndup(ret, text + i - ret)); } - + /* This wasn't the header we were looking for, skip to the next line. */ - while( i < len && ( text[i] != '\r' && text[i] != '\n' ) ) i ++; - while( i < len && ( text[i] == '\r' || text[i] == '\n' ) ) i ++; - + while (i < len && (text[i] != '\r' && text[i] != '\n')) { + i++; + } + while (i < len && (text[i] == '\r' || text[i] == '\n')) { + i++; + } + /* End of headers? */ - if( ( i >= 4 && strncmp( text + i - 4, "\r\n\r\n", 4 ) == 0 ) || - ( i >= 2 && ( strncmp( text + i - 2, "\n\n", 2 ) == 0 || - strncmp( text + i - 2, "\r\r", 2 ) == 0 ) ) ) - { + if ((i >= 4 && strncmp(text + i - 4, "\r\n\r\n", 4) == 0) || + (i >= 2 && (strncmp(text + i - 2, "\n\n", 2) == 0 || + strncmp(text + i - 2, "\r\r", 2) == 0))) { break; } } - + return NULL; } /* Takes a string, truncates it where it's safe, returns the new length */ -int truncate_utf8( char *string, int maxlen ) +int truncate_utf8(char *string, int maxlen) { char *end; - g_utf8_validate( (const gchar *) string, maxlen, (const gchar **) &end ); + + g_utf8_validate((const gchar *) string, maxlen, (const gchar **) &end); *end = '\0'; return end - string; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -29,8 +29,7 @@ #include <gmodule.h> #include <time.h> -struct ns_srv_reply -{ +struct ns_srv_reply { int prio; int weight; int port; @@ -44,22 +43,22 @@ struct ns_srv_reply #define NS_INT32SZ 4 #define NS_GET16(s, cp) do { \ - register const unsigned char *t_cp = (const unsigned char*)(cp); \ - (s) = ((guint16)t_cp[0] << 8) \ - | ((guint16)t_cp[1]) \ - ; \ - (cp) += NS_INT16SZ; \ -} while(0) + register const unsigned char *t_cp = (const unsigned char *) (cp); \ + (s) = ((guint16) t_cp[0] << 8) \ + | ((guint16) t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) #define NS_GET32(s, cp) do { \ - register const unsigned char *t_cp = (const unsigned char*)(cp); \ - (s) = ((guint16)t_cp[0] << 24) \ - | ((guint16)t_cp[1] << 16) \ - | ((guint16)t_cp[2] << 8) \ - | ((guint16)t_cp[3]) \ - ; \ - (cp) += NS_INT32SZ; \ -} while(0) + register const unsigned char *t_cp = (const unsigned char *) (cp); \ + (s) = ((guint16) t_cp[0] << 24) \ + | ((guint16) t_cp[1] << 16) \ + | ((guint16) t_cp[2] << 8) \ + | ((guint16) t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) #define ns_rr_rdlen(rr) ((rr).rdlength + 0) #define ns_rr_rdata(rr) ((rr).rdata + 0) @@ -83,11 +82,10 @@ typedef enum __ns_sect { ns_s_ns = 2, ns_s_ud = 2, ns_s_ar = 3, - ns_s_max =4 + ns_s_max = 4 } ns_sect; -typedef struct __ns_msg -{ +typedef struct __ns_msg { const unsigned char* _msg; const unsigned char* _eom; guint16 _id; @@ -118,37 +116,37 @@ typedef enum __ns_type { #endif /* NAMESER_HAS_NS_INITPARSE */ -G_MODULE_EXPORT void strip_linefeed( gchar *text ); -G_MODULE_EXPORT char *add_cr( char *text ); +G_MODULE_EXPORT void strip_linefeed(gchar *text); +G_MODULE_EXPORT char *add_cr(char *text); G_MODULE_EXPORT char *strip_newlines(char *source); -G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec ); -G_MODULE_EXPORT time_t mktime_utc( struct tm *tp ); -double gettime( void ); +G_MODULE_EXPORT time_t get_time(int year, int month, int day, int hour, int min, int sec); +G_MODULE_EXPORT time_t mktime_utc(struct tm *tp); +double gettime(void); -G_MODULE_EXPORT void strip_html( char *msg ); -G_MODULE_EXPORT char *escape_html( const char *html ); -G_MODULE_EXPORT void http_decode( char *s ); -G_MODULE_EXPORT void http_encode( char *s ); +G_MODULE_EXPORT void strip_html(char *msg); +G_MODULE_EXPORT char *escape_html(const char *html); +G_MODULE_EXPORT void http_decode(char *s); +G_MODULE_EXPORT void http_encode(char *s); -G_MODULE_EXPORT char *ipv6_wrap( char *src ); -G_MODULE_EXPORT char *ipv6_unwrap( char *src ); +G_MODULE_EXPORT char *ipv6_wrap(char *src); +G_MODULE_EXPORT char *ipv6_unwrap(char *src); -G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf ); +G_MODULE_EXPORT signed int do_iconv(char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf); -G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count ); +G_MODULE_EXPORT void random_bytes(unsigned char *buf, int count); -G_MODULE_EXPORT int is_bool( char *value ); -G_MODULE_EXPORT int bool2int( char *value ); +G_MODULE_EXPORT int is_bool(char *value); +G_MODULE_EXPORT int bool2int(char *value); -G_MODULE_EXPORT struct ns_srv_reply **srv_lookup( char *service, char *protocol, char *domain ); -G_MODULE_EXPORT void srv_free( struct ns_srv_reply **srv ); +G_MODULE_EXPORT struct ns_srv_reply **srv_lookup(char *service, char *protocol, char *domain); +G_MODULE_EXPORT void srv_free(struct ns_srv_reply **srv); -G_MODULE_EXPORT char *word_wrap( const char *msg, int line_len ); -G_MODULE_EXPORT gboolean ssl_sockerr_again( void *ssl ); -G_MODULE_EXPORT int md5_verify_password( char *password, char *hash ); -G_MODULE_EXPORT char **split_command_parts( char *command, int limit ); -G_MODULE_EXPORT char *get_rfc822_header( const char *text, const char *header, int len ); -G_MODULE_EXPORT int truncate_utf8( char *string, int maxlen ); +G_MODULE_EXPORT char *word_wrap(const char *msg, int line_len); +G_MODULE_EXPORT gboolean ssl_sockerr_again(void *ssl); +G_MODULE_EXPORT int md5_verify_password(char *password, char *hash); +G_MODULE_EXPORT char **split_command_parts(char *command, int limit); +G_MODULE_EXPORT char *get_rfc822_header(const char *text, const char *header, int len); +G_MODULE_EXPORT int truncate_utf8(char *string, int maxlen); #endif diff --git a/lib/ns_parse.c b/lib/ns_parse.c index 0462b67e..7f7a1bd2 100644 --- a/lib/ns_parse.c +++ b/lib/ns_parse.c @@ -38,7 +38,7 @@ /* Forward. */ -static void setsection(ns_msg *msg, ns_sect sect); +static void setsection(ns_msg *msg, ns_sect sect); /* Macros. */ @@ -46,135 +46,156 @@ static void setsection(ns_msg *msg, ns_sect sect); #define RETERR(err) do { errno = (err); return (-1); } while (0) #else #define RETERR(err) \ - do { errno = (err); if (errno == errno) return (-1); } while (0) + do { errno = (err); if (errno == errno) { return (-1); } } while (0) #endif -#define PARSE_FMT_PRESO 0 /* Parse using presentation-format names */ -#define PARSE_FMT_WIRE 1 /* Parse using network-format names */ +#define PARSE_FMT_PRESO 0 /* Parse using presentation-format names */ +#define PARSE_FMT_WIRE 1 /* Parse using network-format names */ /* Public. */ /* These need to be in the same order as the nres.h:ns_flag enum. */ struct _ns_flagdata _ns_flagdata[16] = { - { 0x8000, 15 }, /*%< qr. */ - { 0x7800, 11 }, /*%< opcode. */ - { 0x0400, 10 }, /*%< aa. */ - { 0x0200, 9 }, /*%< tc. */ - { 0x0100, 8 }, /*%< rd. */ - { 0x0080, 7 }, /*%< ra. */ - { 0x0040, 6 }, /*%< z. */ - { 0x0020, 5 }, /*%< ad. */ - { 0x0010, 4 }, /*%< cd. */ - { 0x000f, 0 }, /*%< rcode. */ - { 0x0000, 0 }, /*%< expansion (1/6). */ - { 0x0000, 0 }, /*%< expansion (2/6). */ - { 0x0000, 0 }, /*%< expansion (3/6). */ - { 0x0000, 0 }, /*%< expansion (4/6). */ - { 0x0000, 0 }, /*%< expansion (5/6). */ - { 0x0000, 0 }, /*%< expansion (6/6). */ + { 0x8000, 15 }, /*%< qr. */ + { 0x7800, 11 }, /*%< opcode. */ + { 0x0400, 10 }, /*%< aa. */ + { 0x0200, 9 }, /*%< tc. */ + { 0x0100, 8 }, /*%< rd. */ + { 0x0080, 7 }, /*%< ra. */ + { 0x0040, 6 }, /*%< z. */ + { 0x0020, 5 }, /*%< ad. */ + { 0x0010, 4 }, /*%< cd. */ + { 0x000f, 0 }, /*%< rcode. */ + { 0x0000, 0 }, /*%< expansion (1/6). */ + { 0x0000, 0 }, /*%< expansion (2/6). */ + { 0x0000, 0 }, /*%< expansion (3/6). */ + { 0x0000, 0 }, /*%< expansion (4/6). */ + { 0x0000, 0 }, /*%< expansion (5/6). */ + { 0x0000, 0 }, /*%< expansion (6/6). */ }; -int ns_msg_getflag(ns_msg handle, int flag) { +int ns_msg_getflag(ns_msg handle, int flag) +{ return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); } int -ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) +{ const u_char *optr = ptr; - for ((void)NULL; count > 0; count--) { + for ((void) NULL; count > 0; count--) { int b, rdlength; b = dn_skipname(ptr, eom); - if (b < 0) + if (b < 0) { RETERR(EMSGSIZE); - ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + } + ptr += b /*Name*/ + NS_INT16SZ /*Type*/ + NS_INT16SZ /*Class*/; if (section != ns_s_qd) { - if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) { RETERR(EMSGSIZE); - ptr += NS_INT32SZ/*TTL*/; + } + ptr += NS_INT32SZ /*TTL*/; NS_GET16(rdlength, ptr); - ptr += rdlength/*RData*/; + ptr += rdlength /*RData*/; } } - if (ptr > eom) + if (ptr > eom) { RETERR(EMSGSIZE); + } return (ptr - optr); } int -ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) +{ const u_char *eom = msg + msglen; int i; handle->_msg = msg; handle->_eom = eom; - if (msg + NS_INT16SZ > eom) + if (msg + NS_INT16SZ > eom) { RETERR(EMSGSIZE); + } NS_GET16(handle->_id, msg); - if (msg + NS_INT16SZ > eom) + if (msg + NS_INT16SZ > eom) { RETERR(EMSGSIZE); + } NS_GET16(handle->_flags, msg); for (i = 0; i < ns_s_max; i++) { - if (msg + NS_INT16SZ > eom) + if (msg + NS_INT16SZ > eom) { RETERR(EMSGSIZE); + } NS_GET16(handle->_counts[i], msg); } - for (i = 0; i < ns_s_max; i++) - if (handle->_counts[i] == 0) + for (i = 0; i < ns_s_max; i++) { + if (handle->_counts[i] == 0) { handle->_sections[i] = NULL; - else { - int b = ns_skiprr(msg, eom, (ns_sect)i, - handle->_counts[i]); + } else { + int b = ns_skiprr(msg, eom, (ns_sect) i, + handle->_counts[i]); - if (b < 0) + if (b < 0) { return (-1); + } handle->_sections[i] = msg; msg += b; } - if (msg != eom) + } + if (msg != eom) { RETERR(EMSGSIZE); + } setsection(handle, ns_s_max); return (0); } int -ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) +{ int b; int tmp; /* Make section right. */ tmp = section; - if (tmp < 0 || section >= ns_s_max) + if (tmp < 0 || section >= ns_s_max) { RETERR(ENODEV); - if (section != handle->_sect) + } + if (section != handle->_sect) { setsection(handle, section); + } /* Make rrnum right. */ - if (rrnum == -1) + if (rrnum == -1) { rrnum = handle->_rrnum; - if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + } + if (rrnum < 0 || rrnum >= handle->_counts[(int) section]) { RETERR(ENODEV); - if (rrnum < handle->_rrnum) + } + if (rrnum < handle->_rrnum) { setsection(handle, section); + } if (rrnum > handle->_rrnum) { b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, - rrnum - handle->_rrnum); + rrnum - handle->_rrnum); - if (b < 0) + if (b < 0) { return (-1); + } handle->_msg_ptr += b; handle->_rrnum = rrnum; } /* Do the parse. */ b = dn_expand(handle->_msg, handle->_eom, - handle->_msg_ptr, rr->name, NS_MAXDNAME); - if (b < 0) + handle->_msg_ptr, rr->name, NS_MAXDNAME); + if (b < 0) { return (-1); + } handle->_msg_ptr += b; - if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) { RETERR(EMSGSIZE); + } NS_GET16(rr->type, handle->_msg_ptr); NS_GET16(rr->rr_class, handle->_msg_ptr); if (section == ns_s_qd) { @@ -182,17 +203,20 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { rr->rdlength = 0; rr->rdata = NULL; } else { - if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) { RETERR(EMSGSIZE); + } NS_GET32(rr->ttl, handle->_msg_ptr); NS_GET16(rr->rdlength, handle->_msg_ptr); - if (handle->_msg_ptr + rr->rdlength > handle->_eom) + if (handle->_msg_ptr + rr->rdlength > handle->_eom) { RETERR(EMSGSIZE); + } rr->rdata = handle->_msg_ptr; handle->_msg_ptr += rr->rdlength; } - if (++handle->_rrnum > handle->_counts[(int)section]) - setsection(handle, (ns_sect)((int)section + 1)); + if (++handle->_rrnum > handle->_counts[(int) section]) { + setsection(handle, (ns_sect) ((int) section + 1)); + } /* All done. */ return (0); @@ -201,14 +225,15 @@ ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { /* Private. */ static void -setsection(ns_msg *msg, ns_sect sect) { +setsection(ns_msg *msg, ns_sect sect) +{ msg->_sect = sect; if (sect == ns_s_max) { msg->_rrnum = -1; msg->_msg_ptr = NULL; } else { msg->_rrnum = 0; - msg->_msg_ptr = msg->_sections[(int)sect]; + msg->_msg_ptr = msg->_sections[(int) sect]; } } diff --git a/lib/oauth.c b/lib/oauth.c index 54c272c8..f15a7135 100644 --- a/lib/oauth.c +++ b/lib/oauth.c @@ -34,396 +34,395 @@ #define HMAC_BLOCK_SIZE 64 -static char *oauth_sign( const char *method, const char *url, - const char *params, struct oauth_info *oi ) +static char *oauth_sign(const char *method, const char *url, + const char *params, struct oauth_info *oi) { uint8_t hash[SHA1_HASH_SIZE]; - GString *payload = g_string_new( "" ); + GString *payload = g_string_new(""); char *key; char *s; - - key = g_strdup_printf( "%s&%s", oi->sp->consumer_secret, oi->token_secret ? oi->token_secret : "" ); - - g_string_append_printf( payload, "%s&", method ); - - s = g_new0( char, strlen( url ) * 3 + 1 ); - strcpy( s, url ); - http_encode( s ); - g_string_append_printf( payload, "%s&", s ); - g_free( s ); - - s = g_new0( char, strlen( params ) * 3 + 1 ); - strcpy( s, params ); - http_encode( s ); - g_string_append( payload, s ); - g_free( s ); - - sha1_hmac( key, 0, payload->str, 0, hash ); - - g_free( key ); - g_string_free( payload, TRUE ); - - /* base64_encode + HTTP escape it (both consumers + + key = g_strdup_printf("%s&%s", oi->sp->consumer_secret, oi->token_secret ? oi->token_secret : ""); + + g_string_append_printf(payload, "%s&", method); + + s = g_new0(char, strlen(url) * 3 + 1); + strcpy(s, url); + http_encode(s); + g_string_append_printf(payload, "%s&", s); + g_free(s); + + s = g_new0(char, strlen(params) * 3 + 1); + strcpy(s, params); + http_encode(s); + g_string_append(payload, s); + g_free(s); + + sha1_hmac(key, 0, payload->str, 0, hash); + + g_free(key); + g_string_free(payload, TRUE); + + /* base64_encode + HTTP escape it (both consumers need it that away) and we're done. */ - s = base64_encode( hash, SHA1_HASH_SIZE ); - s = g_realloc( s, strlen( s ) * 3 + 1 ); - http_encode( s ); - + s = base64_encode(hash, SHA1_HASH_SIZE); + s = g_realloc(s, strlen(s) * 3 + 1); + http_encode(s); + return s; } static char *oauth_nonce() { unsigned char bytes[21]; - random_bytes( bytes, sizeof( bytes ) ); - return base64_encode( bytes, sizeof( bytes ) ); + + random_bytes(bytes, sizeof(bytes)); + return base64_encode(bytes, sizeof(bytes)); } -void oauth_params_add( GSList **params, const char *key, const char *value ) +void oauth_params_add(GSList **params, const char *key, const char *value) { char *item; - - if( !key || !value ) + + if (!key || !value) { return; - - item = g_strdup_printf( "%s=%s", key, value ); - *params = g_slist_insert_sorted( *params, item, (GCompareFunc) strcmp ); + } + + item = g_strdup_printf("%s=%s", key, value); + *params = g_slist_insert_sorted(*params, item, (GCompareFunc) strcmp); } -void oauth_params_del( GSList **params, const char *key ) +void oauth_params_del(GSList **params, const char *key) { - int key_len = strlen( key ); + int key_len = strlen(key); GSList *l, *n; - - if( params == NULL ) + + if (params == NULL) { return; - - for( l = *params; l; l = n ) - { + } + + for (l = *params; l; l = n) { n = l->next; - - if( strncmp( (char*) l->data, key, key_len ) == 0 && - ((char*)l->data)[key_len] == '=' ) - { - g_free( l->data ); - *params = g_slist_remove( *params, l->data ); + + if (strncmp((char *) l->data, key, key_len) == 0 && + ((char *) l->data)[key_len] == '=') { + g_free(l->data); + *params = g_slist_remove(*params, l->data); } } } -void oauth_params_set( GSList **params, const char *key, const char *value ) +void oauth_params_set(GSList **params, const char *key, const char *value) { - oauth_params_del( params, key ); - oauth_params_add( params, key, value ); + oauth_params_del(params, key); + oauth_params_add(params, key, value); } -const char *oauth_params_get( GSList **params, const char *key ) +const char *oauth_params_get(GSList **params, const char *key) { - int key_len = strlen( key ); + int key_len = strlen(key); GSList *l; - - if( params == NULL ) + + if (params == NULL) { return NULL; - - for( l = *params; l; l = l->next ) - { - if( strncmp( (char*) l->data, key, key_len ) == 0 && - ((char*)l->data)[key_len] == '=' ) - return (const char*) l->data + key_len + 1; } - + + for (l = *params; l; l = l->next) { + if (strncmp((char *) l->data, key, key_len) == 0 && + ((char *) l->data)[key_len] == '=') { + return (const char *) l->data + key_len + 1; + } + } + return NULL; } -void oauth_params_parse( GSList **params, char *in ) +void oauth_params_parse(GSList **params, char *in) { char *amp, *eq, *s; - - while( in && *in ) - { - eq = strchr( in, '=' ); - if( !eq ) + + while (in && *in) { + eq = strchr(in, '='); + if (!eq) { break; - + } + *eq = '\0'; - if( ( amp = strchr( eq + 1, '&' ) ) ) + if ((amp = strchr(eq + 1, '&'))) { *amp = '\0'; - - s = g_strdup( eq + 1 ); - http_decode( s ); - oauth_params_add( params, in, s ); - g_free( s ); - + } + + s = g_strdup(eq + 1); + http_decode(s); + oauth_params_add(params, in, s); + g_free(s); + *eq = '='; - if( amp == NULL ) + if (amp == NULL) { break; - + } + *amp = '&'; in = amp + 1; } } -void oauth_params_free( GSList **params ) +void oauth_params_free(GSList **params) { - while( params && *params ) - { - g_free( (*params)->data ); - *params = g_slist_remove( *params, (*params)->data ); + while (params && *params) { + g_free((*params)->data); + *params = g_slist_remove(*params, (*params)->data); } } -char *oauth_params_string( GSList *params ) +char *oauth_params_string(GSList *params) { GSList *l; - GString *str = g_string_new( "" ); - - for( l = params; l; l = l->next ) - { + GString *str = g_string_new(""); + + for (l = params; l; l = l->next) { char *s, *eq; - - s = g_malloc( strlen( l->data ) * 3 + 1 ); - strcpy( s, l->data ); - if( ( eq = strchr( s, '=' ) ) ) - http_encode( eq + 1 ); - g_string_append( str, s ); - g_free( s ); - - if( l->next ) - g_string_append_c( str, '&' ); + + s = g_malloc(strlen(l->data) * 3 + 1); + strcpy(s, l->data); + if ((eq = strchr(s, '='))) { + http_encode(eq + 1); + } + g_string_append(str, s); + g_free(s); + + if (l->next) { + g_string_append_c(str, '&'); + } } - - return g_string_free( str, FALSE ); + + return g_string_free(str, FALSE); } -void oauth_info_free( struct oauth_info *info ) +void oauth_info_free(struct oauth_info *info) { - if( info ) - { - g_free( info->auth_url ); - g_free( info->request_token ); - g_free( info->token ); - g_free( info->token_secret ); - oauth_params_free( &info->params ); - g_free( info ); + if (info) { + g_free(info->auth_url); + g_free(info->request_token); + g_free(info->token); + g_free(info->token_secret); + oauth_params_free(&info->params); + g_free(info); } } -static void oauth_add_default_params( GSList **params, const struct oauth_service *sp ) +static void oauth_add_default_params(GSList **params, const struct oauth_service *sp) { char *s; - - oauth_params_set( params, "oauth_consumer_key", sp->consumer_key ); - oauth_params_set( params, "oauth_signature_method", "HMAC-SHA1" ); - - s = g_strdup_printf( "%d", (int) time( NULL ) ); - oauth_params_set( params, "oauth_timestamp", s ); - g_free( s ); - + + oauth_params_set(params, "oauth_consumer_key", sp->consumer_key); + oauth_params_set(params, "oauth_signature_method", "HMAC-SHA1"); + + s = g_strdup_printf("%d", (int) time(NULL)); + oauth_params_set(params, "oauth_timestamp", s); + g_free(s); + s = oauth_nonce(); - oauth_params_set( params, "oauth_nonce", s ); - g_free( s ); - - oauth_params_set( params, "oauth_version", "1.0" ); + oauth_params_set(params, "oauth_nonce", s); + g_free(s); + + oauth_params_set(params, "oauth_version", "1.0"); } -static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, struct oauth_info *oi ) +static void *oauth_post_request(const char *url, GSList **params_, http_input_function func, struct oauth_info *oi) { GSList *params = NULL; char *s, *params_s, *post; void *req; url_t url_p; - - if( !url_set( &url_p, url ) ) - { - oauth_params_free( params_ ); + + if (!url_set(&url_p, url)) { + oauth_params_free(params_); return NULL; } - - if( params_ ) + + if (params_) { params = *params_; - - oauth_add_default_params( ¶ms, oi->sp ); - - params_s = oauth_params_string( params ); - oauth_params_free( ¶ms ); - - s = oauth_sign( "POST", url, params_s, oi ); - post = g_strdup_printf( "%s&oauth_signature=%s", params_s, s ); - g_free( params_s ); - g_free( s ); - - s = g_strdup_printf( "POST %s HTTP/1.0\r\n" - "Host: %s\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %zd\r\n" - "\r\n" - "%s", url_p.file, url_p.host, strlen( post ), post ); - g_free( post ); - - req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, - s, func, oi ); - g_free( s ); - + } + + oauth_add_default_params(¶ms, oi->sp); + + params_s = oauth_params_string(params); + oauth_params_free(¶ms); + + s = oauth_sign("POST", url, params_s, oi); + post = g_strdup_printf("%s&oauth_signature=%s", params_s, s); + g_free(params_s); + g_free(s); + + s = g_strdup_printf("POST %s HTTP/1.0\r\n" + "Host: %s\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %zd\r\n" + "\r\n" + "%s", url_p.file, url_p.host, strlen(post), post); + g_free(post); + + req = http_dorequest(url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, + s, func, oi); + g_free(s); + return req; } -static void oauth_request_token_done( struct http_request *req ); +static void oauth_request_token_done(struct http_request *req); -struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data ) +struct oauth_info *oauth_request_token(const struct oauth_service *sp, oauth_cb func, void *data) { - struct oauth_info *st = g_new0( struct oauth_info, 1 ); + struct oauth_info *st = g_new0(struct oauth_info, 1); GSList *params = NULL; - + st->func = func; st->data = data; st->sp = sp; - - oauth_params_add( ¶ms, "oauth_callback", "oob" ); - - if( !oauth_post_request( sp->url_request_token, ¶ms, oauth_request_token_done, st ) ) - { - oauth_info_free( st ); + + oauth_params_add(¶ms, "oauth_callback", "oob"); + + if (!oauth_post_request(sp->url_request_token, ¶ms, oauth_request_token_done, st)) { + oauth_info_free(st); return NULL; } - + return st; } -static void oauth_request_token_done( struct http_request *req ) +static void oauth_request_token_done(struct http_request *req) { struct oauth_info *st = req->data; - + st->http = req; - - if( req->status_code == 200 ) - { + + if (req->status_code == 200) { GSList *params = NULL; - - st->auth_url = g_strdup_printf( "%s?%s", st->sp->url_authorize, req->reply_body ); - oauth_params_parse( ¶ms, req->reply_body ); - st->request_token = g_strdup( oauth_params_get( ¶ms, "oauth_token" ) ); - st->token_secret = g_strdup( oauth_params_get( ¶ms, "oauth_token_secret" ) ); - oauth_params_free( ¶ms ); + + st->auth_url = g_strdup_printf("%s?%s", st->sp->url_authorize, req->reply_body); + oauth_params_parse(¶ms, req->reply_body); + st->request_token = g_strdup(oauth_params_get(¶ms, "oauth_token")); + st->token_secret = g_strdup(oauth_params_get(¶ms, "oauth_token_secret")); + oauth_params_free(¶ms); } - + st->stage = OAUTH_REQUEST_TOKEN; - st->func( st ); + st->func(st); } -static void oauth_access_token_done( struct http_request *req ); +static void oauth_access_token_done(struct http_request *req); -gboolean oauth_access_token( const char *pin, struct oauth_info *st ) +gboolean oauth_access_token(const char *pin, struct oauth_info *st) { GSList *params = NULL; - - oauth_params_add( ¶ms, "oauth_token", st->request_token ); - oauth_params_add( ¶ms, "oauth_verifier", pin ); - - return oauth_post_request( st->sp->url_access_token, ¶ms, oauth_access_token_done, st ) != NULL; + + oauth_params_add(¶ms, "oauth_token", st->request_token); + oauth_params_add(¶ms, "oauth_verifier", pin); + + return oauth_post_request(st->sp->url_access_token, ¶ms, oauth_access_token_done, st) != NULL; } -static void oauth_access_token_done( struct http_request *req ) +static void oauth_access_token_done(struct http_request *req) { struct oauth_info *st = req->data; - + st->http = req; - - if( req->status_code == 200 ) - { - oauth_params_parse( &st->params, req->reply_body ); - st->token = g_strdup( oauth_params_get( &st->params, "oauth_token" ) ); - g_free( st->token_secret ); - st->token_secret = g_strdup( oauth_params_get( &st->params, "oauth_token_secret" ) ); + + if (req->status_code == 200) { + oauth_params_parse(&st->params, req->reply_body); + st->token = g_strdup(oauth_params_get(&st->params, "oauth_token")); + g_free(st->token_secret); + st->token_secret = g_strdup(oauth_params_get(&st->params, "oauth_token_secret")); } - + st->stage = OAUTH_ACCESS_TOKEN; - if( st->func( st ) ) - { + if (st->func(st)) { /* Don't need these anymore, but keep the rest. */ - g_free( st->auth_url ); + g_free(st->auth_url); st->auth_url = NULL; - g_free( st->request_token ); + g_free(st->request_token); st->request_token = NULL; - oauth_params_free( &st->params ); + oauth_params_free(&st->params); } } -char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args ) +char *oauth_http_header(struct oauth_info *oi, const char *method, const char *url, char *args) { GSList *params = NULL, *l; char *sig = NULL, *params_s, *s; GString *ret = NULL; - - oauth_params_add( ¶ms, "oauth_token", oi->token ); - oauth_add_default_params( ¶ms, oi->sp ); - + + oauth_params_add(¶ms, "oauth_token", oi->token); + oauth_add_default_params(¶ms, oi->sp); + /* Start building the OAuth header. 'key="value", '... */ - ret = g_string_new( "OAuth " ); - for( l = params; l; l = l->next ) - { + ret = g_string_new("OAuth "); + for (l = params; l; l = l->next) { char *kv = l->data; - char *eq = strchr( kv, '=' ); - char esc[strlen(kv)*3+1]; - - if( eq == NULL ) + char *eq = strchr(kv, '='); + char esc[strlen(kv) * 3 + 1]; + + if (eq == NULL) { break; /* WTF */ - - strcpy( esc, eq + 1 ); - http_encode( esc ); - - g_string_append_len( ret, kv, eq - kv + 1 ); - g_string_append_c( ret, '"' ); - g_string_append( ret, esc ); - g_string_append( ret, "\", " ); + + } + strcpy(esc, eq + 1); + http_encode(esc); + + g_string_append_len(ret, kv, eq - kv + 1); + g_string_append_c(ret, '"'); + g_string_append(ret, esc); + g_string_append(ret, "\", "); } - + /* Now, before generating the signature, add GET/POST arguments to params since they should be included in the base signature string (but not in the HTTP header). */ - if( args ) - oauth_params_parse( ¶ms, args ); - if( ( s = strchr( url, '?' ) ) ) - { - s = g_strdup( s + 1 ); - oauth_params_parse( ¶ms, s ); - g_free( s ); + if (args) { + oauth_params_parse(¶ms, args); + } + if ((s = strchr(url, '?'))) { + s = g_strdup(s + 1); + oauth_params_parse(¶ms, s); + g_free(s); } - + /* Append the signature and we're done! */ - params_s = oauth_params_string( params ); - sig = oauth_sign( method, url, params_s, oi ); - g_string_append_printf( ret, "oauth_signature=\"%s\"", sig ); - g_free( params_s ); - - oauth_params_free( ¶ms ); - g_free( sig ); - - return ret ? g_string_free( ret, FALSE ) : NULL; + params_s = oauth_params_string(params); + sig = oauth_sign(method, url, params_s, oi); + g_string_append_printf(ret, "oauth_signature=\"%s\"", sig); + g_free(params_s); + + oauth_params_free(¶ms); + g_free(sig); + + return ret ? g_string_free(ret, FALSE) : NULL; } -char *oauth_to_string( struct oauth_info *oi ) +char *oauth_to_string(struct oauth_info *oi) { GSList *params = NULL; char *ret; - - oauth_params_add( ¶ms, "oauth_token", oi->token ); - oauth_params_add( ¶ms, "oauth_token_secret", oi->token_secret ); - ret = oauth_params_string( params ); - oauth_params_free( ¶ms ); - + + oauth_params_add(¶ms, "oauth_token", oi->token); + oauth_params_add(¶ms, "oauth_token_secret", oi->token_secret); + ret = oauth_params_string(params); + oauth_params_free(¶ms); + return ret; } -struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp ) +struct oauth_info *oauth_from_string(char *in, const struct oauth_service *sp) { - struct oauth_info *oi = g_new0( struct oauth_info, 1 ); + struct oauth_info *oi = g_new0(struct oauth_info, 1); GSList *params = NULL; - - oauth_params_parse( ¶ms, in ); - oi->token = g_strdup( oauth_params_get( ¶ms, "oauth_token" ) ); - oi->token_secret = g_strdup( oauth_params_get( ¶ms, "oauth_token_secret" ) ); - oauth_params_free( ¶ms ); + + oauth_params_parse(¶ms, in); + oi->token = g_strdup(oauth_params_get(¶ms, "oauth_token")); + oi->token_secret = g_strdup(oauth_params_get(¶ms, "oauth_token_secret")); + oauth_params_free(¶ms); oi->sp = sp; - + return oi; } diff --git a/lib/oauth.h b/lib/oauth.h index 50adc95c..c9115d57 100644 --- a/lib/oauth.h +++ b/lib/oauth.h @@ -27,73 +27,70 @@ struct oauth_info; /* Callback function called twice during the access token request process. Return FALSE if something broke and the process must be aborted. */ -typedef gboolean (*oauth_cb)( struct oauth_info * ); +typedef gboolean (*oauth_cb)(struct oauth_info *); -typedef enum -{ +typedef enum { OAUTH_INIT, OAUTH_REQUEST_TOKEN, OAUTH_ACCESS_TOKEN, } oauth_stage_t; -struct oauth_info -{ +struct oauth_info { oauth_stage_t stage; const struct oauth_service *sp; - + oauth_cb func; void *data; - + struct http_request *http; - + char *auth_url; char *request_token; - + char *token; char *token_secret; GSList *params; }; -struct oauth_service -{ +struct oauth_service { char *url_request_token; char *url_access_token; char *url_authorize; - + char *consumer_key; char *consumer_secret; }; -/* http://oauth.net/core/1.0a/#auth_step1 (section 6.1) +/* http://oauth.net/core/1.0a/#auth_step1 (section 6.1) Request an initial anonymous token which can be used to construct an authorization URL for the user. This is passed to the callback function in a struct oauth_info. */ -struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data ); +struct oauth_info *oauth_request_token(const struct oauth_service *sp, oauth_cb func, void *data); /* http://oauth.net/core/1.0a/#auth_step3 (section 6.3) The user gets a PIN or so which we now exchange for the final access token. This is passed to the callback function in the same struct oauth_info. */ -gboolean oauth_access_token( const char *pin, struct oauth_info *st ); +gboolean oauth_access_token(const char *pin, struct oauth_info *st); /* http://oauth.net/core/1.0a/#anchor12 (section 7) Generate an OAuth Authorization: HTTP header. access_token should be saved/fetched using the functions above. args can be a string with whatever's going to be in the POST body of the request. GET args will automatically be grabbed from url. */ -char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args ); +char *oauth_http_header(struct oauth_info *oi, const char *method, const char *url, char *args); /* Shouldn't normally be required unless the process is aborted by the user. */ -void oauth_info_free( struct oauth_info *info ); +void oauth_info_free(struct oauth_info *info); /* Convert to and back from strings, for easier saving. */ -char *oauth_to_string( struct oauth_info *oi ); -struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp ); +char *oauth_to_string(struct oauth_info *oi); +struct oauth_info *oauth_from_string(char *in, const struct oauth_service *sp); /* For reading misc. data. */ -void oauth_params_add( GSList **params, const char *key, const char *value ); -void oauth_params_parse( GSList **params, char *in ); -void oauth_params_free( GSList **params ); -char *oauth_params_string( GSList *params ); -void oauth_params_set( GSList **params, const char *key, const char *value ); -const char *oauth_params_get( GSList **params, const char *key ); +void oauth_params_add(GSList **params, const char *key, const char *value); +void oauth_params_parse(GSList **params, char *in); +void oauth_params_free(GSList **params); +char *oauth_params_string(GSList *params); +void oauth_params_set(GSList **params, const char *key, const char *value); +const char *oauth_params_get(GSList **params, const char *key); diff --git a/lib/oauth2.c b/lib/oauth2.c index b66197ba..d6cf9a53 100644 --- a/lib/oauth2.c +++ b/lib/oauth2.c @@ -27,14 +27,14 @@ a pretty nice standard called OAuth 1.0a. That, and the fact that they use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its responses. - + Apparently too many people were too retarded to comprehend the elementary bits of crypto in OAuth 1.0a (took me one afternoon to implement) so the standard was replaced with what comes down to a complicated scheme around what's really just application-specific passwords. - + And then a bunch of mostly incompatible implementations. Great work, guys. - + http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ */ #include <glib.h> @@ -45,150 +45,148 @@ #include "json_util.h" #include "url.h" -char *oauth2_url( const struct oauth2_service *sp ) +char *oauth2_url(const struct oauth2_service *sp) { - return g_strconcat( sp->auth_url, - "?scope=", sp->scope, - "&response_type=code" - "&redirect_uri=", sp->redirect_url, - "&client_id=", sp->consumer_key, - NULL ); + return g_strconcat(sp->auth_url, + "?scope=", sp->scope, + "&response_type=code" + "&redirect_uri=", sp->redirect_url, + "&client_id=", sp->consumer_key, + NULL); } -struct oauth2_access_token_data -{ +struct oauth2_access_token_data { oauth2_token_callback func; gpointer data; }; -static void oauth2_access_token_done( struct http_request *req ); +static void oauth2_access_token_done(struct http_request *req); -int oauth2_access_token( const struct oauth2_service *sp, - const char *auth_type, const char *auth, - oauth2_token_callback func, gpointer data ) +int oauth2_access_token(const struct oauth2_service *sp, + const char *auth_type, const char *auth, + oauth2_token_callback func, gpointer data) { GSList *args = NULL; char *args_s, *s; url_t url_p; struct http_request *req; struct oauth2_access_token_data *cb_data; - - if( !url_set( &url_p, sp->token_url ) ) + + if (!url_set(&url_p, sp->token_url)) { return 0; - - oauth_params_add( &args, "client_id", sp->consumer_key ); - oauth_params_add( &args, "client_secret", sp->consumer_secret ); - oauth_params_add( &args, "grant_type", auth_type ); - if( strcmp( auth_type, OAUTH2_AUTH_CODE ) == 0 ) - { - oauth_params_add( &args, "redirect_uri", sp->redirect_url ); - oauth_params_add( &args, "code", auth ); } - else - { - oauth_params_add( &args, "refresh_token", auth ); + + oauth_params_add(&args, "client_id", sp->consumer_key); + oauth_params_add(&args, "client_secret", sp->consumer_secret); + oauth_params_add(&args, "grant_type", auth_type); + if (strcmp(auth_type, OAUTH2_AUTH_CODE) == 0) { + oauth_params_add(&args, "redirect_uri", sp->redirect_url); + oauth_params_add(&args, "code", auth); + } else { + oauth_params_add(&args, "refresh_token", auth); } - args_s = oauth_params_string( args ); - oauth_params_free( &args ); - - s = g_strdup_printf( "POST %s HTTP/1.0\r\n" - "Host: %s\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %zd\r\n" - "\r\n" - "%s", url_p.file, url_p.host, strlen( args_s ), args_s ); - g_free( args_s ); - - cb_data = g_new0( struct oauth2_access_token_data, 1 ); + args_s = oauth_params_string(args); + oauth_params_free(&args); + + s = g_strdup_printf("POST %s HTTP/1.0\r\n" + "Host: %s\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %zd\r\n" + "\r\n" + "%s", url_p.file, url_p.host, strlen(args_s), args_s); + g_free(args_s); + + cb_data = g_new0(struct oauth2_access_token_data, 1); cb_data->func = func; cb_data->data = data; - - req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, - s, oauth2_access_token_done, cb_data ); - - g_free( s ); - - if( req == NULL ) - g_free( cb_data ); - + + req = http_dorequest(url_p.host, url_p.port, url_p.proto == PROTO_HTTPS, + s, oauth2_access_token_done, cb_data); + + g_free(s); + + if (req == NULL) { + g_free(cb_data); + } + return req != NULL; } -static char* oauth2_parse_error( json_value *e ) +static char* oauth2_parse_error(json_value *e) { /* This does a reasonable job with some of the flavours of error responses I've seen. Because apparently it's not standardised. */ - - if( e->type == json_object ) - { + + if (e->type == json_object) { /* Facebook style */ - const char *msg = json_o_str( e, "message" ); - const char *type = json_o_str( e, "type" ); - json_value *code_o = json_o_get( e, "code" ); + const char *msg = json_o_str(e, "message"); + const char *type = json_o_str(e, "type"); + json_value *code_o = json_o_get(e, "code"); int code = 0; - - if( code_o && code_o->type == json_integer ) + + if (code_o && code_o->type == json_integer) { code = code_o->u.integer; - - return g_strdup_printf( "Error %d: %s", code, msg ? msg : type ? type : "Unknown error" ); - } - else if( e->type == json_string ) - { - return g_strdup( e->u.string.ptr ); + } + + return g_strdup_printf("Error %d: %s", code, msg ? msg : type ? type : "Unknown error"); + } else if (e->type == json_string) { + return g_strdup(e->u.string.ptr); } return NULL; } -static void oauth2_access_token_done( struct http_request *req ) +static void oauth2_access_token_done(struct http_request *req) { struct oauth2_access_token_data *cb_data = req->data; char *atoken = NULL, *rtoken = NULL, *error = NULL; char *content_type; - - if( getenv( "BITLBEE_DEBUG" ) && req->reply_body ) - printf( "%s\n", req->reply_body ); - - content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 ); - - if( content_type && ( strstr( content_type, "application/json" ) || - strstr( content_type, "text/javascript" ) ) ) - { - json_value *js = json_parse( req->reply_body, req->body_size ); - if( js && js->type == json_object ) - { - JSON_O_FOREACH( js, k, v ) - { - if( strcmp( k, "error" ) == 0 ) - error = oauth2_parse_error( v ); - if( v->type != json_string ) + + if (getenv("BITLBEE_DEBUG") && req->reply_body) { + printf("%s\n", req->reply_body); + } + + content_type = get_rfc822_header(req->reply_headers, "Content-Type", 0); + + if (content_type && (strstr(content_type, "application/json") || + strstr(content_type, "text/javascript"))) { + json_value *js = json_parse(req->reply_body, req->body_size); + if (js && js->type == json_object) { + JSON_O_FOREACH(js, k, v){ + if (strcmp(k, "error") == 0) { + error = oauth2_parse_error(v); + } + if (v->type != json_string) { continue; - if( strcmp( k, "access_token" ) == 0 ) - atoken = g_strdup( v->u.string.ptr ); - if( strcmp( k, "refresh_token" ) == 0 ) - rtoken = g_strdup( v->u.string.ptr ); + } + if (strcmp(k, "access_token") == 0) { + atoken = g_strdup(v->u.string.ptr); + } + if (strcmp(k, "refresh_token") == 0) { + rtoken = g_strdup(v->u.string.ptr); + } } } - json_value_free( js ); - } - else - { + json_value_free(js); + } else { /* Facebook use their own odd format here, seems to be URL-encoded. */ GSList *p_in = NULL; - - oauth_params_parse( &p_in, req->reply_body ); - atoken = g_strdup( oauth_params_get( &p_in, "access_token" ) ); - rtoken = g_strdup( oauth_params_get( &p_in, "refresh_token" ) ); - oauth_params_free( &p_in ); + + oauth_params_parse(&p_in, req->reply_body); + atoken = g_strdup(oauth_params_get(&p_in, "access_token")); + rtoken = g_strdup(oauth_params_get(&p_in, "refresh_token")); + oauth_params_free(&p_in); } - if( getenv( "BITLBEE_DEBUG" ) ) - printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken ); - if( !atoken && !rtoken && !error ) - error = g_strdup( "Unusable response" ); - - cb_data->func( cb_data->data, atoken, rtoken, error ); - g_free( content_type ); - g_free( atoken ); - g_free( rtoken ); - g_free( error ); - g_free( cb_data ); + if (getenv("BITLBEE_DEBUG")) { + printf("Extracted atoken=%s rtoken=%s\n", atoken, rtoken); + } + if (!atoken && !rtoken && !error) { + error = g_strdup("Unusable response"); + } + + cb_data->func(cb_data->data, atoken, rtoken, error); + g_free(content_type); + g_free(atoken); + g_free(rtoken); + g_free(error); + g_free(cb_data); } diff --git a/lib/oauth2.h b/lib/oauth2.h index b3811f49..4d6abdb1 100644 --- a/lib/oauth2.h +++ b/lib/oauth2.h @@ -24,11 +24,10 @@ /* Implementation mostly based on my experience with writing the previous OAuth module, and from http://code.google.com/apis/accounts/docs/OAuth2.html . */ -typedef void (*oauth2_token_callback)( gpointer data, const char *atoken, - const char *rtoken, const char *error ); +typedef void (*oauth2_token_callback)(gpointer data, const char *atoken, + const char *rtoken, const char *error); -struct oauth2_service -{ +struct oauth2_service { char *auth_url; char *token_url; char *redirect_url; @@ -42,10 +41,10 @@ struct oauth2_service /* Generate a URL the user should open in his/her browser to get an authorization code. */ -char *oauth2_url( const struct oauth2_service *sp ); +char *oauth2_url(const struct oauth2_service *sp); /* Exchanges an auth code or refresh token for an access token. auth_type is one of the two OAUTH2_AUTH_.. constants above. */ -int oauth2_access_token( const struct oauth2_service *sp, - const char *auth_type, const char *auth, - oauth2_token_callback func, gpointer data ); +int oauth2_access_token(const struct oauth2_service *sp, + const char *auth_type, const char *auth, + oauth2_token_callback func, gpointer data); diff --git a/lib/proxy.c b/lib/proxy.c index 2e0dc2cf..66621ebc 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -67,8 +67,9 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition struct PHB *phb = data; socklen_t len; int error = ETIMEDOUT; + len = sizeof(error); - + if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) { if ((phb->gai_cur = phb->gai_cur->ai_next)) { int new_fd; @@ -86,9 +87,9 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition closesocket(source); b_event_remove(phb->inpa); phb->inpa = 0; - if( phb->proxy_func ) + if (phb->proxy_func) { phb->proxy_func(phb->proxy_data, -1, B_EV_IO_READ); - else { + } else { phb->func(phb->data, -1, B_EV_IO_READ); g_free(phb); } @@ -98,13 +99,13 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition sock_make_blocking(source); b_event_remove(phb->inpa); phb->inpa = 0; - if( phb->proxy_func ) + if (phb->proxy_func) { phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ); - else { + } else { phb->func(phb->data, source, B_EV_IO_READ); g_free(phb); } - + return FALSE; } @@ -112,62 +113,62 @@ static int proxy_connect_none(const char *host, unsigned short port_, struct PHB { struct sockaddr_in me; int fd = -1; - - if (phb->gai_cur == NULL) - { + + if (phb->gai_cur == NULL) { int ret; char port[6]; struct addrinfo hints; - + g_snprintf(port, sizeof(port), "%d", port_); - + memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; - - if (!(ret = getaddrinfo(host, port, &hints, &phb->gai))) + + if (!(ret = getaddrinfo(host, port, &hints, &phb->gai))) { phb->gai_cur = phb->gai; - else + } else { event_debug("gai(): %s\n", gai_strerror(ret)); + } } - - for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next) - { + + for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next) { if ((fd = socket(phb->gai_cur->ai_family, phb->gai_cur->ai_socktype, phb->gai_cur->ai_protocol)) < 0) { - event_debug( "socket failed: %d\n", errno); + event_debug("socket failed: %d\n", errno); continue; } sock_make_nonblocking(fd); - if (global.conf->iface_out) - { + if (global.conf->iface_out) { me.sin_family = AF_INET; me.sin_port = 0; - me.sin_addr.s_addr = inet_addr( global.conf->iface_out ); - - if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0) + me.sin_addr.s_addr = inet_addr(global.conf->iface_out); + + if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0) { event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out); + } } event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port_, fd); - + if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) { - event_debug( "connect failed: %s\n", strerror(errno)); + event_debug("connect failed: %s\n", strerror(errno)); closesocket(fd); fd = -1; continue; } else { phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb); phb->fd = fd; - + break; } } - - if(fd < 0 && host) + + if (fd < 0 && host) { g_free(phb); + } return fd; } @@ -187,11 +188,12 @@ static gboolean http_canread(gpointer data, gint source, b_input_condition cond) b_event_remove(phb->inpa); - while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { - if (inputline[pos - 1] == '\n') + while ((pos < sizeof(inputline) - 1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { + if (inputline[pos - 1] == '\n') { nlc++; - else if (inputline[pos - 1] != '\r') + } else if (inputline[pos - 1] != '\r') { nlc = 0; + } } inputline[pos] = '\0'; @@ -207,7 +209,7 @@ static gboolean http_canread(gpointer data, gint source, b_input_condition cond) phb->func(phb->data, -1, B_EV_IO_READ); g_free(phb->host); g_free(phb); - + return FALSE; } @@ -217,8 +219,10 @@ static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond struct PHB *phb = data; socklen_t len; int error = ETIMEDOUT; - if (phb->inpa > 0) + + if (phb->inpa > 0) { b_event_remove(phb->inpa); + } len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); @@ -230,7 +234,7 @@ static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond sock_make_blocking(source); g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port, - phb->host, phb->port); + phb->host, phb->port); if (send(source, cmd, strlen(cmd), 0) < 0) { close(source); phb->func(phb->data, -1, B_EV_IO_READ); @@ -265,7 +269,7 @@ static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond } phb->inpa = b_input_add(source, B_EV_IO_READ, http_canread, phb); - + return FALSE; } @@ -275,8 +279,8 @@ static int proxy_connect_http(const char *host, unsigned short port, struct PHB phb->port = port; phb->proxy_func = http_canwrite; phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); + + return(proxy_connect_none(proxyhost, proxyport, phb)); } @@ -301,7 +305,7 @@ static gboolean s4_canread(gpointer data, gint source, b_input_condition cond) phb->func(phb->data, -1, B_EV_IO_READ); g_free(phb->host); g_free(phb); - + return FALSE; } @@ -312,8 +316,10 @@ static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) struct PHB *phb = data; socklen_t len; int error = ETIMEDOUT; - if (phb->inpa > 0) + + if (phb->inpa > 0) { b_event_remove(phb->inpa); + } len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); @@ -337,10 +343,10 @@ static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) packet[1] = 1; packet[2] = phb->port >> 8; packet[3] = phb->port & 0xff; - packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; - packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; - packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; - packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; + packet[4] = (unsigned char) (hp->h_addr_list[0])[0]; + packet[5] = (unsigned char) (hp->h_addr_list[0])[1]; + packet[6] = (unsigned char) (hp->h_addr_list[0])[2]; + packet[7] = (unsigned char) (hp->h_addr_list[0])[3]; packet[8] = 0; if (write(source, packet, 9) != 9) { close(source); @@ -351,7 +357,7 @@ static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond) } phb->inpa = b_input_add(source, B_EV_IO_READ, s4_canread, phb); - + return FALSE; } @@ -361,8 +367,8 @@ static int proxy_connect_socks4(const char *host, unsigned short port, struct PH phb->port = port; phb->proxy_func = s4_canwrite; phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); + + return(proxy_connect_none(proxyhost, proxyport, phb)); } @@ -393,7 +399,7 @@ static gboolean s5_canread_again(gpointer data, gint source, b_input_condition c phb->func(phb->data, source, B_EV_IO_READ); g_free(phb->host); g_free(phb); - + return FALSE; } @@ -402,11 +408,11 @@ static void s5_sendconnect(gpointer data, gint source) unsigned char buf[512]; struct PHB *phb = data; int hlen = strlen(phb->host); - + buf[0] = 0x05; - buf[1] = 0x01; /* CONNECT */ - buf[2] = 0x00; /* reserved */ - buf[3] = 0x03; /* address type -- host name */ + buf[1] = 0x01; /* CONNECT */ + buf[2] = 0x00; /* reserved */ + buf[3] = 0x03; /* address type -- host name */ buf[4] = hlen; memcpy(buf + 5, phb->host, hlen); buf[5 + strlen(phb->host)] = phb->port >> 8; @@ -447,7 +453,7 @@ static gboolean s5_readauth(gpointer data, gint source, b_input_condition cond) } s5_sendconnect(phb, source); - + return FALSE; } @@ -476,7 +482,7 @@ static gboolean s5_canread(gpointer data, gint source, b_input_condition cond) if (buf[1] == 0x02) { unsigned int i = strlen(proxyuser), j = strlen(proxypass); - buf[0] = 0x01; /* version 1 */ + buf[0] = 0x01; /* version 1 */ buf[1] = i; memcpy(buf + 2, proxyuser, i); buf[2 + i] = j; @@ -493,7 +499,7 @@ static gboolean s5_canread(gpointer data, gint source, b_input_condition cond) } else { s5_sendconnect(phb, source); } - + return FALSE; } @@ -504,8 +510,10 @@ static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) struct PHB *phb = data; socklen_t len; int error = ETIMEDOUT; - if (phb->inpa > 0) + + if (phb->inpa > 0) { b_event_remove(phb->inpa); + } len = sizeof(error); if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { close(source); @@ -517,11 +525,11 @@ static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) sock_make_blocking(source); i = 0; - buf[0] = 0x05; /* SOCKS version 5 */ + buf[0] = 0x05; /* SOCKS version 5 */ if (proxyuser[0]) { - buf[1] = 0x02; /* two methods */ - buf[2] = 0x00; /* no authentication */ - buf[3] = 0x02; /* username/password authentication */ + buf[1] = 0x02; /* two methods */ + buf[2] = 0x00; /* no authentication */ + buf[3] = 0x02; /* username/password authentication */ i = 4; } else { buf[1] = 0x01; @@ -538,7 +546,7 @@ static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond) } phb->inpa = b_input_add(source, B_EV_IO_READ, s5_canread, phb); - + return FALSE; } @@ -548,8 +556,8 @@ static int proxy_connect_socks5(const char *host, unsigned short port, struct PH phb->port = port; phb->proxy_func = s5_canwrite; phb->proxy_data = phb; - - return( proxy_connect_none( proxyhost, proxyport, phb ) ); + + return(proxy_connect_none(proxyhost, proxyport, phb)); } @@ -558,24 +566,25 @@ static int proxy_connect_socks5(const char *host, unsigned short port, struct PH int proxy_connect(const char *host, int port, b_event_handler func, gpointer data) { struct PHB *phb; - + if (!host || port <= 0 || !func || strlen(host) > 128) { return -1; } - + phb = g_new0(struct PHB, 1); phb->func = func; phb->data = data; - - if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) + + if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) { return proxy_connect_none(host, port, phb); - else if (proxytype == PROXY_HTTP) + } else if (proxytype == PROXY_HTTP) { return proxy_connect_http(host, port, phb); - else if (proxytype == PROXY_SOCKS4) + } else if (proxytype == PROXY_SOCKS4) { return proxy_connect_socks4(host, port, phb); - else if (proxytype == PROXY_SOCKS5) + } else if (proxytype == PROXY_SOCKS5) { return proxy_connect_socks5(host, port, phb); - + } + g_free(phb); return -1; } diff --git a/lib/proxy.h b/lib/proxy.h index b84b37ff..9688aaa6 100644 --- a/lib/proxy.h +++ b/lib/proxy.h @@ -21,7 +21,7 @@ /* this is the export part of the proxy.c file. it does a little prototype-ing stuff and redefine some net function to mask them - with some kind of transparent layer */ + with some kind of transparent layer */ #ifndef _PROXY_H_ #define _PROXY_H_ @@ -41,8 +41,8 @@ #define PROXY_SOCKS5 3 extern char proxyhost[128]; -extern int proxyport; -extern int proxytype; +extern int proxyport; +extern int proxytype; extern char proxyuser[128]; extern char proxypass[128]; @@ -16,6 +16,7 @@ void sha1_append(sha1_state_t *ctx, const guint8 * message_array, guint len) void sha1_finish(sha1_state_t *ctx, guint8 digest[SHA1_HASH_SIZE]) { gsize digest_len = SHA1_HASH_SIZE; + g_checksum_get_digest(*ctx, digest, &digest_len); g_checksum_free(*ctx); } @@ -27,71 +28,74 @@ void sha1_hmac(const char *key_, size_t key_len, const char *payload, size_t pay { sha1_state_t sha1; guint8 hash[SHA1_HASH_SIZE]; - guint8 key[HMAC_BLOCK_SIZE+1]; + guint8 key[HMAC_BLOCK_SIZE + 1]; int i; - - if( key_len == 0 ) - key_len = strlen( key_ ); - if( payload_len == 0 ) - payload_len = strlen( payload ); - + + if (key_len == 0) { + key_len = strlen(key_); + } + if (payload_len == 0) { + payload_len = strlen(payload); + } + /* Create K. If our current key is >64 chars we have to hash it, otherwise just pad. */ - memset( key, 0, HMAC_BLOCK_SIZE + 1 ); - if( key_len > HMAC_BLOCK_SIZE ) - { - sha1_init( &sha1 ); - sha1_append( &sha1, (guint8*) key_, key_len ); - sha1_finish( &sha1, key ); - } - else - { - memcpy( key, key_, key_len ); + memset(key, 0, HMAC_BLOCK_SIZE + 1); + if (key_len > HMAC_BLOCK_SIZE) { + sha1_init(&sha1); + sha1_append(&sha1, (guint8 *) key_, key_len); + sha1_finish(&sha1, key); + } else { + memcpy(key, key_, key_len); } - + /* Inner part: H(K XOR 0x36, text) */ - sha1_init( &sha1 ); - for( i = 0; i < HMAC_BLOCK_SIZE; i ++ ) + sha1_init(&sha1); + for (i = 0; i < HMAC_BLOCK_SIZE; i++) { key[i] ^= 0x36; - sha1_append( &sha1, key, HMAC_BLOCK_SIZE ); - sha1_append( &sha1, (const guint8*) payload, payload_len ); - sha1_finish( &sha1, hash ); - + } + sha1_append(&sha1, key, HMAC_BLOCK_SIZE); + sha1_append(&sha1, (const guint8 *) payload, payload_len); + sha1_finish(&sha1, hash); + /* Final result: H(K XOR 0x5C, inner stuff) */ - sha1_init( &sha1 ); - for( i = 0; i < HMAC_BLOCK_SIZE; i ++ ) + sha1_init(&sha1); + for (i = 0; i < HMAC_BLOCK_SIZE; i++) { key[i] ^= 0x36 ^ 0x5c; - sha1_append( &sha1, key, HMAC_BLOCK_SIZE ); - sha1_append( &sha1, hash, SHA1_HASH_SIZE ); - sha1_finish( &sha1, digest ); + } + sha1_append(&sha1, key, HMAC_BLOCK_SIZE); + sha1_append(&sha1, hash, SHA1_HASH_SIZE); + sha1_finish(&sha1, digest); } /* I think this follows the scheme described on: http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29 My random data comes from a SHA1 generator but hey, it's random enough for me, and RFC 4122 looks way more complicated than I need this to be. - + Returns a value that must be free()d. */ -char *sha1_random_uuid( sha1_state_t * context ) +char *sha1_random_uuid(sha1_state_t * context) { guint8 dig[SHA1_HASH_SIZE]; - char *ret = g_new0( char, 40 ); /* 36 chars + \0 */ + char *ret = g_new0(char, 40); /* 36 chars + \0 */ int i, p; - + sha1_finish(context, dig); - for( p = i = 0; i < 16; i ++ ) - { - if( i == 4 || i == 6 || i == 8 || i == 10 ) + for (p = i = 0; i < 16; i++) { + if (i == 4 || i == 6 || i == 8 || i == 10) { ret[p++] = '-'; - if( i == 6 ) - dig[i] = ( dig[i] & 0x0f ) | 0x40; - if( i == 8 ) - dig[i] = ( dig[i] & 0x30 ) | 0x80; - - sprintf( ret + p, "%02x", dig[i] ); + } + if (i == 6) { + dig[i] = (dig[i] & 0x0f) | 0x40; + } + if (i == 8) { + dig[i] = (dig[i] & 0x30) | 0x80; + } + + sprintf(ret + p, "%02x", dig[i]); p += 2; } ret[p] = '\0'; - + return ret; } diff --git a/lib/ssl_client.h b/lib/ssl_client.h index d23d21f0..d2e12534 100644 --- a/lib/ssl_client.h +++ b/lib/ssl_client.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -56,39 +56,39 @@ typedef gboolean (*ssl_input_function)(gpointer, int, void*, b_input_condition); /* Perform any global initialization the SSL library might need. */ -G_MODULE_EXPORT void ssl_init( void ); +G_MODULE_EXPORT void ssl_init(void); /* Connect to host:port, call the given function when the connection is ready to be used for SSL traffic. This is all done asynchronously, no blocking I/O! (Except for the DNS lookups, for now...) */ -G_MODULE_EXPORT void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ); +G_MODULE_EXPORT void *ssl_connect(char *host, int port, gboolean verify, ssl_input_function func, gpointer data); /* Start an SSL session on an existing fd. Useful for STARTTLS functionality, for example in Jabber. */ -G_MODULE_EXPORT void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ); +G_MODULE_EXPORT void *ssl_starttls(int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data); /* Obviously you need special read/write functions to read data. */ -G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len ); -G_MODULE_EXPORT int ssl_write( void *conn, const char *buf, int len ); +G_MODULE_EXPORT int ssl_read(void *conn, char *buf, int len); +G_MODULE_EXPORT int ssl_write(void *conn, const char *buf, int len); /* Now needed by most SSL libs. See for more info: http://www.gnu.org/software/gnutls/manual/gnutls.html#index-gnutls_005frecord_005fcheck_005fpending-209 http://www.openssl.org/docs/ssl/SSL_pending.html - + Required because OpenSSL empties the TCP buffer completely but doesn't necessarily give us all the unencrypted data. Or maybe you didn't ask for all of it because your buffer is too small. - + Returns 0 if there's nothing left, 1 if there's more data. */ -G_MODULE_EXPORT int ssl_pending( void *conn ); +G_MODULE_EXPORT int ssl_pending(void *conn); /* Abort the SSL connection and disconnect the socket. Do not use close() directly, both the SSL library and the peer will be unhappy! */ -G_MODULE_EXPORT void ssl_disconnect( void *conn_ ); +G_MODULE_EXPORT void ssl_disconnect(void *conn_); /* Get the fd for this connection, you will usually need it for event handling. */ -G_MODULE_EXPORT int ssl_getfd( void *conn ); +G_MODULE_EXPORT int ssl_getfd(void *conn); /* This function returns B_EV_IO_READ/WRITE. With SSL connections it's possible that something has to be read while actually were trying to @@ -96,10 +96,11 @@ G_MODULE_EXPORT int ssl_getfd( void *conn ); SSL operation returned SSL_AGAIN, *always* use this function when adding an event handler to the queue. (And it should perform exactly the same action as the handler that just received the SSL_AGAIN.) */ -G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn ); +G_MODULE_EXPORT b_input_condition ssl_getdirection(void *conn); /* Converts a verification bitfield passed to ssl_input_function into a more useful string. Or NULL if it had no useful bits set. */ -G_MODULE_EXPORT char *ssl_verify_strerror( int code ); +G_MODULE_EXPORT char *ssl_verify_strerror(int code); -G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res); +G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, + size_t input_len, const unsigned char *iv, unsigned char **res); diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c index fade7de2..749b00b6 100644 --- a/lib/ssl_gnutls.c +++ b/lib/ssl_gnutls.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -49,8 +49,7 @@ gnutls_certificate_credentials_t xcred; #define SSLDEBUG 0 -struct scd -{ +struct scd { ssl_input_function func; gpointer data; int fd; @@ -58,117 +57,117 @@ struct scd int inpa; char *hostname; gboolean verify; - + gnutls_session_t session; }; static GHashTable *session_cache; -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); +static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond); +static gboolean ssl_starttls_real(gpointer data, gint source, b_input_condition cond); +static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond); -static void ssl_deinit( void ); +static void ssl_deinit(void); -static void ssl_log( int level, const char *line ) +static void ssl_log(int level, const char *line) { - printf( "%d %s", level, line ); + printf("%d %s", level, line); } -void ssl_init( void ) +void ssl_init(void) { - if( initialized ) + if (initialized) { return; - + } + gnutls_global_init(); - gnutls_certificate_allocate_credentials( &xcred ); - if( global.conf->cafile ) - { - gnutls_certificate_set_x509_trust_file( xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM ); - + gnutls_certificate_allocate_credentials(&xcred); + if (global.conf->cafile) { + gnutls_certificate_set_x509_trust_file(xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM); + /* Not needed in GnuTLS 2.11+ (enabled by default there) so don't do it (resets possible other defaults). */ - if( !gnutls_check_version( "2.11" ) ) - gnutls_certificate_set_verify_flags( xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); + if (!gnutls_check_version("2.11")) { + gnutls_certificate_set_verify_flags(xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); + } } initialized = TRUE; - - gnutls_global_set_log_function( ssl_log ); + + gnutls_global_set_log_function(ssl_log); /* gnutls_global_set_log_level( 3 ); */ - - session_cache = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); - - atexit( ssl_deinit ); + + session_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + atexit(ssl_deinit); } -static void ssl_deinit( void ) +static void ssl_deinit(void) { gnutls_global_deinit(); - gnutls_certificate_free_credentials( xcred ); - g_hash_table_destroy( session_cache ); + gnutls_certificate_free_credentials(xcred); + g_hash_table_destroy(session_cache); session_cache = NULL; } -void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_connect(char *host, int port, gboolean verify, ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); - + struct scd *conn = g_new0(struct scd, 1); + conn->func = func; conn->data = data; conn->inpa = -1; - conn->hostname = g_strdup( host ); + conn->hostname = g_strdup(host); conn->verify = verify && global.conf->cafile; - conn->fd = proxy_connect( host, port, ssl_connected, conn ); - - if( conn->fd < 0 ) - { - g_free( conn ); + conn->fd = proxy_connect(host, port, ssl_connected, conn); + + if (conn->fd < 0) { + g_free(conn); return NULL; } - + return conn; } -void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_starttls(int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); - + struct scd *conn = g_new0(struct scd, 1); + conn->fd = fd; conn->func = func; conn->data = data; conn->inpa = -1; - conn->hostname = g_strdup( hostname ); - + conn->hostname = g_strdup(hostname); + /* For now, SSL verification is globally enabled by setting the cafile setting in bitlbee.conf. Commented out by default because probably not everyone has this file in the same place and plenty of folks may not have the cert of their private Jabber server in it. */ conn->verify = verify && global.conf->cafile; - + /* This function should be called via a (short) timeout instead of directly from here, because these SSL calls are *supposed* to be *completely* asynchronous and not ready yet when this function (or *_connect, for examle) returns. Also, errors are reported via the callback function, not via this function's return value. - + In short, doing things like this makes the rest of the code a lot simpler. */ - - b_timeout_add( 1, ssl_starttls_real, conn ); - + + b_timeout_add(1, ssl_starttls_real, conn); + return conn; } -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_starttls_real(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; - - return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); + + return ssl_connected(conn, conn->fd, B_EV_IO_WRITE); } -static int verify_certificate_callback( gnutls_session_t session ) +static int verify_certificate_callback(gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; @@ -177,317 +176,328 @@ static int verify_certificate_callback( gnutls_session_t session ) int verifyret = 0; gnutls_x509_crt_t cert; struct scd *conn; - - conn = gnutls_session_get_ptr( session ); - gnutlsret = gnutls_certificate_verify_peers2( session, &status ); - if( gnutlsret < 0 ) + conn = gnutls_session_get_ptr(session); + + gnutlsret = gnutls_certificate_verify_peers2(session, &status); + if (gnutlsret < 0) { return VERIFY_CERT_ERROR; + } - if( status & GNUTLS_CERT_INVALID ) + if (status & GNUTLS_CERT_INVALID) { verifyret |= VERIFY_CERT_INVALID; + } - if( status & GNUTLS_CERT_REVOKED ) + if (status & GNUTLS_CERT_REVOKED) { verifyret |= VERIFY_CERT_REVOKED; + } - if( status & GNUTLS_CERT_SIGNER_NOT_FOUND ) + if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { verifyret |= VERIFY_CERT_SIGNER_NOT_FOUND; + } - if( status & GNUTLS_CERT_SIGNER_NOT_CA ) + if (status & GNUTLS_CERT_SIGNER_NOT_CA) { verifyret |= VERIFY_CERT_SIGNER_NOT_CA; + } - if( status & GNUTLS_CERT_INSECURE_ALGORITHM ) + if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { verifyret |= VERIFY_CERT_INSECURE_ALGORITHM; + } #ifdef GNUTLS_CERT_NOT_ACTIVATED /* Amusingly, the GnuTLS function used above didn't check for expiry until GnuTLS 2.8 or so. (See CVE-2009-1417) */ - if( status & GNUTLS_CERT_NOT_ACTIVATED ) + if (status & GNUTLS_CERT_NOT_ACTIVATED) { verifyret |= VERIFY_CERT_NOT_ACTIVATED; + } - if( status & GNUTLS_CERT_EXPIRED ) + if (status & GNUTLS_CERT_EXPIRED) { verifyret |= VERIFY_CERT_EXPIRED; + } #endif - if( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 || gnutls_x509_crt_init( &cert ) < 0 ) + if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509 || gnutls_x509_crt_init(&cert) < 0) { return VERIFY_CERT_ERROR; + } - cert_list = gnutls_certificate_get_peers( session, &cert_list_size ); - if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 ) + cert_list = gnutls_certificate_get_peers(session, &cert_list_size); + if (cert_list == NULL || gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { return VERIFY_CERT_ERROR; + } - if( !gnutls_x509_crt_check_hostname( cert, conn->hostname ) ) - { + if (!gnutls_x509_crt_check_hostname(cert, conn->hostname)) { verifyret |= VERIFY_CERT_INVALID; verifyret |= VERIFY_CERT_WRONG_HOSTNAME; } - gnutls_x509_crt_deinit( cert ); + gnutls_x509_crt_deinit(cert); return verifyret; } -struct ssl_session -{ +struct ssl_session { size_t size; char data[]; }; -static void ssl_cache_add( struct scd *conn ) +static void ssl_cache_add(struct scd *conn) { size_t data_size = 0; struct ssl_session *data; char *hostname; - - if( !conn->hostname || - gnutls_session_get_data( conn->session, NULL, &data_size ) != 0 ) + + if (!conn->hostname || + gnutls_session_get_data(conn->session, NULL, &data_size) != 0) { return; - - data = g_malloc( sizeof( struct ssl_session ) + data_size ); - if( gnutls_session_get_data( conn->session, data->data, &data_size ) != 0 ) - { - g_free( data ); + } + + data = g_malloc(sizeof(struct ssl_session) + data_size); + if (gnutls_session_get_data(conn->session, data->data, &data_size) != 0) { + g_free(data); return; } - - hostname = g_strdup( conn->hostname ); - g_hash_table_insert( session_cache, hostname, data ); + + hostname = g_strdup(conn->hostname); + g_hash_table_insert(session_cache, hostname, data); } -static void ssl_cache_resume( struct scd *conn ) +static void ssl_cache_resume(struct scd *conn) { struct ssl_session *data; - - if( conn->hostname && - ( data = g_hash_table_lookup( session_cache, conn->hostname ) ) ) - { - gnutls_session_set_data( conn->session, data->data, data->size ); - g_hash_table_remove( session_cache, conn->hostname ); + + if (conn->hostname && + (data = g_hash_table_lookup(session_cache, conn->hostname))) { + gnutls_session_set_data(conn->session, data->data, data->size); + g_hash_table_remove(session_cache, conn->hostname); } } -char *ssl_verify_strerror( int code ) +char *ssl_verify_strerror(int code) { - GString *ret = g_string_new( "" ); - - if( code & VERIFY_CERT_REVOKED ) - g_string_append( ret, "certificate has been revoked, " ); - if( code & VERIFY_CERT_SIGNER_NOT_FOUND ) - g_string_append( ret, "certificate hasn't got a known issuer, " ); - if( code & VERIFY_CERT_SIGNER_NOT_CA ) - g_string_append( ret, "certificate's issuer is not a CA, " ); - if( code & VERIFY_CERT_INSECURE_ALGORITHM ) - g_string_append( ret, "certificate uses an insecure algorithm, " ); - if( code & VERIFY_CERT_NOT_ACTIVATED ) - g_string_append( ret, "certificate has not been activated, " ); - if( code & VERIFY_CERT_EXPIRED ) - g_string_append( ret, "certificate has expired, " ); - if( code & VERIFY_CERT_WRONG_HOSTNAME ) - g_string_append( ret, "certificate hostname mismatch, " ); - - if( ret->len == 0 ) - { - g_string_free( ret, TRUE ); - return NULL; + GString *ret = g_string_new(""); + + if (code & VERIFY_CERT_REVOKED) { + g_string_append(ret, "certificate has been revoked, "); + } + if (code & VERIFY_CERT_SIGNER_NOT_FOUND) { + g_string_append(ret, "certificate hasn't got a known issuer, "); + } + if (code & VERIFY_CERT_SIGNER_NOT_CA) { + g_string_append(ret, "certificate's issuer is not a CA, "); + } + if (code & VERIFY_CERT_INSECURE_ALGORITHM) { + g_string_append(ret, "certificate uses an insecure algorithm, "); + } + if (code & VERIFY_CERT_NOT_ACTIVATED) { + g_string_append(ret, "certificate has not been activated, "); } - else - { - g_string_truncate( ret, ret->len - 2 ); - return g_string_free( ret, FALSE ); + if (code & VERIFY_CERT_EXPIRED) { + g_string_append(ret, "certificate has expired, "); + } + if (code & VERIFY_CERT_WRONG_HOSTNAME) { + g_string_append(ret, "certificate hostname mismatch, "); + } + + if (ret->len == 0) { + g_string_free(ret, TRUE); + return NULL; + } else { + g_string_truncate(ret, ret->len - 2); + return g_string_free(ret, FALSE); } } -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; - - if( source == -1 ) - { - conn->func( conn->data, 0, NULL, cond ); - g_free( conn ); + + if (source == -1) { + conn->func(conn->data, 0, NULL, cond); + g_free(conn); return FALSE; } - + ssl_init(); - - gnutls_init( &conn->session, GNUTLS_CLIENT ); - gnutls_session_set_ptr( conn->session, (void *) conn ); + + gnutls_init(&conn->session, GNUTLS_CLIENT); + gnutls_session_set_ptr(conn->session, (void *) conn); #if GNUTLS_VERSION_NUMBER < 0x020c00 - gnutls_transport_set_lowat( conn->session, 0 ); + gnutls_transport_set_lowat(conn->session, 0); #endif - gnutls_set_default_priority( conn->session ); - gnutls_credentials_set( conn->session, GNUTLS_CRD_CERTIFICATE, xcred ); - if( conn->hostname && !g_ascii_isdigit( conn->hostname[0] ) ) - gnutls_server_name_set( conn->session, GNUTLS_NAME_DNS, - conn->hostname, strlen( conn->hostname ) ); - - sock_make_nonblocking( conn->fd ); - gnutls_transport_set_ptr( conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd ); - - ssl_cache_resume( conn ); - - return ssl_handshake( data, source, cond ); + gnutls_set_default_priority(conn->session); + gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, xcred); + if (conn->hostname && !g_ascii_isdigit(conn->hostname[0])) { + gnutls_server_name_set(conn->session, GNUTLS_NAME_DNS, + conn->hostname, strlen(conn->hostname)); + } + + sock_make_nonblocking(conn->fd); + gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) GNUTLS_STUPID_CAST conn->fd); + + ssl_cache_resume(conn); + + return ssl_handshake(data, source, cond); } -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; int st, stver; - + /* This function returns false, so avoid calling b_event_remove again */ conn->inpa = -1; - - if( ( st = gnutls_handshake( conn->session ) ) < 0 ) - { - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) - { - conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), - ssl_handshake, data ); - } - else - { - conn->func( conn->data, 0, NULL, cond ); - - gnutls_deinit( conn->session ); - closesocket( conn->fd ); - - g_free( conn ); - } - } - else - { - if( conn->verify && ( stver = verify_certificate_callback( conn->session ) ) != 0 ) - { - conn->func( conn->data, stver, NULL, cond ); - gnutls_deinit( conn->session ); - closesocket( conn->fd ); + if ((st = gnutls_handshake(conn->session)) < 0) { + if (st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED) { + conn->inpa = b_input_add(conn->fd, ssl_getdirection(conn), + ssl_handshake, data); + } else { + conn->func(conn->data, 0, NULL, cond); + + gnutls_deinit(conn->session); + closesocket(conn->fd); - g_free( conn ); + g_free(conn); } - else - { + } else { + if (conn->verify && (stver = verify_certificate_callback(conn->session)) != 0) { + conn->func(conn->data, stver, NULL, cond); + + gnutls_deinit(conn->session); + closesocket(conn->fd); + + g_free(conn); + } else { /* For now we can't handle non-blocking perfectly everywhere... */ - sock_make_blocking( conn->fd ); - - ssl_cache_add( conn ); + sock_make_blocking(conn->fd); + + ssl_cache_add(conn); conn->established = TRUE; - conn->func( conn->data, 0, conn, cond ); + conn->func(conn->data, 0, conn, cond); } } - + return FALSE; } -int ssl_read( void *conn, char *buf, int len ) +int ssl_read(void *conn, char *buf, int len) { int st; - - if( !((struct scd*)conn)->established ) - { + + if (!((struct scd*) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - - st = gnutls_record_recv( ((struct scd*)conn)->session, buf, len ); - + + st = gnutls_record_recv(((struct scd*) conn)->session, buf, len); + ssl_errno = SSL_OK; - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + if (st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED) { ssl_errno = SSL_AGAIN; - - if( SSLDEBUG && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 2, buf, st ); - + } + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { + len = write(2, buf, st); + } + return st; } -int ssl_write( void *conn, const char *buf, int len ) +int ssl_write(void *conn, const char *buf, int len) { int st; - - if( !((struct scd*)conn)->established ) - { + + if (!((struct scd*) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - - st = gnutls_record_send( ((struct scd*)conn)->session, buf, len ); - + + st = gnutls_record_send(((struct scd*) conn)->session, buf, len); + ssl_errno = SSL_OK; - if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED ) + if (st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED) { ssl_errno = SSL_AGAIN; - - if( SSLDEBUG && getenv( "BITLBEE_DEBUG" ) && st > 0 ) len = write( 2, buf, st ); - + } + + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { + len = write(2, buf, st); + } + return st; } -int ssl_pending( void *conn ) +int ssl_pending(void *conn) { - if( conn == NULL ) + if (conn == NULL) { return 0; - - if( !((struct scd*)conn)->established ) - { + } + + if (!((struct scd*) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return 0; } #if GNUTLS_VERSION_NUMBER >= 0x03000d && GNUTLS_VERSION_NUMBER <= 0x030012 - if( ssl_errno == SSL_AGAIN ) + if (ssl_errno == SSL_AGAIN) { return 0; + } #endif - - return gnutls_record_check_pending( ((struct scd*)conn)->session ) != 0; + + return gnutls_record_check_pending(((struct scd*) conn)->session) != 0; } -void ssl_disconnect( void *conn_ ) +void ssl_disconnect(void *conn_) { struct scd *conn = conn_; - - if( conn->inpa != -1 ) - b_event_remove( conn->inpa ); - - if( conn->established ) - gnutls_bye( conn->session, GNUTLS_SHUT_WR ); - - closesocket( conn->fd ); - - if( conn->session ) - gnutls_deinit( conn->session ); - g_free( conn->hostname ); - g_free( conn ); + + if (conn->inpa != -1) { + b_event_remove(conn->inpa); + } + + if (conn->established) { + gnutls_bye(conn->session, GNUTLS_SHUT_WR); + } + + closesocket(conn->fd); + + if (conn->session) { + gnutls_deinit(conn->session); + } + g_free(conn->hostname); + g_free(conn); } -int ssl_getfd( void *conn ) +int ssl_getfd(void *conn) { - return( ((struct scd*)conn)->fd ); + return(((struct scd*) conn)->fd); } -b_input_condition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection(void *conn) { - return( gnutls_record_get_direction( ((struct scd*)conn)->session ) ? - B_EV_IO_WRITE : B_EV_IO_READ ); + return(gnutls_record_get_direction(((struct scd*) conn)->session) ? + B_EV_IO_WRITE : B_EV_IO_READ); } -size_t ssl_des3_encrypt( const unsigned char *key, size_t key_len, const unsigned char *input, - size_t input_len, const unsigned char *iv, unsigned char **res ) +size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, + size_t input_len, const unsigned char *iv, unsigned char **res) { gcry_cipher_hd_t gcr; gcry_error_t st; - + ssl_init(); - - *res = g_malloc( input_len ); - st = gcry_cipher_open( &gcr, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0 ) || - gcry_cipher_setkey( gcr, key, key_len ) || - gcry_cipher_setiv( gcr, iv, 8 ) || - gcry_cipher_encrypt( gcr, *res, input_len, input, input_len ); - - gcry_cipher_close( gcr ); - - if( st == 0 ) + + *res = g_malloc(input_len); + st = gcry_cipher_open(&gcr, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0) || + gcry_cipher_setkey(gcr, key, key_len) || + gcry_cipher_setiv(gcr, iv, 8) || + gcry_cipher_encrypt(gcr, *res, input_len, input, input_len); + + gcry_cipher_close(gcr); + + if (st == 0) { return input_len; - - g_free( *res ); + } + + g_free(*res); return 0; } diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c index 00a574f7..09e50f3f 100644 --- a/lib/ssl_nss.c +++ b/lib/ssl_nss.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -59,12 +59,12 @@ struct scd { }; static gboolean ssl_connected(gpointer data, gint source, - b_input_condition cond); + b_input_condition cond); static gboolean ssl_starttls_real(gpointer data, gint source, - b_input_condition cond); + b_input_condition cond); static SECStatus nss_auth_cert(void *arg, PRFileDesc * socket, PRBool checksig, - PRBool isserver) + PRBool isserver) { return SECSuccess; } @@ -73,8 +73,9 @@ static SECStatus nss_bad_cert(void *arg, PRFileDesc * socket) { PRErrorCode err; - if (!arg) + if (!arg) { return SECFailure; + } *(PRErrorCode *) arg = err = PORT_GetError(); @@ -113,7 +114,7 @@ void ssl_init(void) } void *ssl_connect(char *host, int port, gboolean verify, - ssl_input_function func, gpointer data) + ssl_input_function func, gpointer data) { struct scd *conn = g_new0(struct scd, 1); @@ -136,7 +137,7 @@ void *ssl_connect(char *host, int port, gboolean verify, } static gboolean ssl_starttls_real(gpointer data, gint source, - b_input_condition cond) + b_input_condition cond) { struct scd *conn = data; @@ -144,7 +145,7 @@ static gboolean ssl_starttls_real(gpointer data, gint source, } void *ssl_starttls(int fd, char *hostname, gboolean verify, - ssl_input_function func, gpointer data) + ssl_input_function func, gpointer data) { struct scd *conn = g_new0(struct scd, 1); @@ -174,7 +175,7 @@ void *ssl_starttls(int fd, char *hostname, gboolean verify, } static gboolean ssl_connected(gpointer data, gint source, - b_input_condition cond) + b_input_condition cond) { struct scd *conn = data; @@ -182,28 +183,31 @@ static gboolean ssl_connected(gpointer data, gint source, if (conn->verify) { conn->func(conn->data, 1, NULL, cond); - if (source >= 0) + if (source >= 0) { closesocket(source); + } g_free(conn->hostname); g_free(conn); return FALSE; } - if (source == -1) + if (source == -1) { goto ssl_connected_failure; + } /* Until we find out how to handle non-blocking I/O with NSS... */ sock_make_blocking(conn->fd); conn->prfd = SSL_ImportFD(NULL, PR_ImportTCPSocket(source)); - if (!conn->prfd) + if (!conn->prfd) { goto ssl_connected_failure; + } SSL_OptionSet(conn->prfd, SSL_SECURITY, PR_TRUE); SSL_OptionSet(conn->prfd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); SSL_BadCertHook(conn->prfd, (SSLBadCertHandler) nss_bad_cert, NULL); SSL_AuthCertificateHook(conn->prfd, (SSLAuthCertificate) nss_auth_cert, - (void *)CERT_GetDefaultCertDB()); + (void *) CERT_GetDefaultCertDB()); SSL_SetURL(conn->prfd, conn->hostname); SSL_ResetHandshake(conn->prfd, PR_FALSE); @@ -215,14 +219,16 @@ static gboolean ssl_connected(gpointer data, gint source, conn->func(conn->data, 0, conn, cond); return FALSE; - ssl_connected_failure: +ssl_connected_failure: conn->func(conn->data, 0, NULL, cond); - if (conn->prfd) + if (conn->prfd) { PR_Close(conn->prfd); - if (source >= 0) + } + if (source >= 0) { closesocket(source); + } g_free(conn->hostname); g_free(conn); @@ -234,20 +240,22 @@ int ssl_read(void *conn, char *buf, int len) int st; PRErrorCode PR_err; - if (!((struct scd *)conn)->established) { + if (!((struct scd *) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - st = PR_Read(((struct scd *)conn)->prfd, buf, len); + st = PR_Read(((struct scd *) conn)->prfd, buf, len); PR_err = PR_GetError(); ssl_errno = SSL_OK; - if (PR_err == PR_WOULD_BLOCK_ERROR) + if (PR_err == PR_WOULD_BLOCK_ERROR) { ssl_errno = SSL_AGAIN; + } - if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { len = write(STDERR_FILENO, buf, st); + } return st; } @@ -257,26 +265,28 @@ int ssl_write(void *conn, const char *buf, int len) int st; PRErrorCode PR_err; - if (!((struct scd *)conn)->established) { + if (!((struct scd *) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - st = PR_Write(((struct scd *)conn)->prfd, buf, len); + st = PR_Write(((struct scd *) conn)->prfd, buf, len); PR_err = PR_GetError(); ssl_errno = SSL_OK; - if (PR_err == PR_WOULD_BLOCK_ERROR) + if (PR_err == PR_WOULD_BLOCK_ERROR) { ssl_errno = SSL_AGAIN; + } - if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) + if (SSLDEBUG && getenv("BITLBEE_DEBUG") && st > 0) { len = write(2, buf, st); + } return st; } int ssl_pending(void *conn) { - struct scd *c = (struct scd *)conn; + struct scd *c = (struct scd *) conn; if (c == NULL) { return 0; @@ -292,8 +302,9 @@ void ssl_disconnect(void *conn_) // When we swich to NSS_Init, we should have here // NSS_Shutdown(); - if (conn->prfd) + if (conn->prfd) { PR_Close(conn->prfd); + } g_free(conn->hostname); g_free(conn); @@ -301,7 +312,7 @@ void ssl_disconnect(void *conn_) int ssl_getfd(void *conn) { - return (((struct scd *)conn)->fd); + return (((struct scd *) conn)->fd); } b_input_condition ssl_getdirection(void *conn) @@ -313,13 +324,13 @@ b_input_condition ssl_getdirection(void *conn) char *ssl_verify_strerror(int code) { return - g_strdup - ("SSL certificate verification not supported by BitlBee NSS code."); + g_strdup + ("SSL certificate verification not supported by BitlBee NSS code."); } size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, - const unsigned char *input, size_t input_len, - const unsigned char *iv, unsigned char **res) + const unsigned char *input, size_t input_len, + const unsigned char *iv, unsigned char **res) { #define CIPHER_MECH CKM_DES3_CBC #define MAX_OUTPUT_LEN 72 @@ -341,45 +352,45 @@ size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, ssl_init(); } - keyItem.data = (unsigned char *)key; + keyItem.data = (unsigned char *) key; keyItem.len = key_len; slot = PK11_GetBestSlot(CIPHER_MECH, NULL); if (slot == NULL) { fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } symKey = - PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, - &keyItem, NULL); + PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, + &keyItem, NULL); if (symKey == NULL) { fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } - ivItem.data = (unsigned char *)iv; + ivItem.data = (unsigned char *) iv; /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ ivItem.len = 8; secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); if (secParam == NULL) { fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } ctx = - PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, - secParam); + PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, + secParam); if (ctx == NULL) { fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } @@ -387,10 +398,10 @@ size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, *res = g_new0(unsigned char, MAX_OUTPUT_LEN); rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, - (unsigned char *)input, input_len); + (unsigned char *) input, input_len); if (rv != SECSuccess) { fprintf(stderr, "PK11_CipherOp failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } @@ -398,25 +409,29 @@ size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, assert(len1 <= MAX_OUTPUT_LEN); rv = PK11_DigestFinal(ctx, *res + len1, &len2, - (unsigned int)MAX_OUTPUT_LEN - len1); + (unsigned int) MAX_OUTPUT_LEN - len1); if (rv != SECSuccess) { fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", - PR_GetError()); + PR_GetError()); rc = 0; goto out; } rc = len1 + len2; - out: - if (ctx) +out: + if (ctx) { PK11_DestroyContext(ctx, PR_TRUE); - if (symKey) + } + if (symKey) { PK11_FreeSymKey(symKey); - if (secParam) + } + if (secParam) { SECITEM_FreeItem(secParam, PR_TRUE); - if (slot) + } + if (slot) { PK11_FreeSlot(slot); + } return rc; } diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c index 63937380..c286d509 100644 --- a/lib/ssl_openssl.c +++ b/lib/ssl_openssl.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -39,263 +39,270 @@ int ssl_errno = 0; static gboolean initialized = FALSE; -struct scd -{ +struct scd { ssl_input_function func; gpointer data; int fd; gboolean established; gboolean verify; char *hostname; - + int inpa; - int lasterr; /* Necessary for SSL_get_error */ + int lasterr; /* Necessary for SSL_get_error */ SSL *ssl; }; static SSL_CTX *ssl_ctx; -static void ssl_conn_free( struct scd *conn ); -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ); -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ); -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ); +static void ssl_conn_free(struct scd *conn); +static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond); +static gboolean ssl_starttls_real(gpointer data, gint source, b_input_condition cond); +static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond); -void ssl_init( void ) +void ssl_init(void) { const SSL_METHOD *meth; - + SSL_library_init(); - + meth = TLSv1_client_method(); - ssl_ctx = SSL_CTX_new( meth ); - + ssl_ctx = SSL_CTX_new(meth); + initialized = TRUE; } -void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_connect(char *host, int port, gboolean verify, ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); - - conn->fd = proxy_connect( host, port, ssl_connected, conn ); - if( conn->fd < 0 ) - { - ssl_conn_free( conn ); + struct scd *conn = g_new0(struct scd, 1); + + conn->fd = proxy_connect(host, port, ssl_connected, conn); + if (conn->fd < 0) { + ssl_conn_free(conn); return NULL; } - + conn->func = func; conn->data = data; conn->inpa = -1; - conn->hostname = g_strdup( host ); - + conn->hostname = g_strdup(host); + return conn; } -void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data ) +void *ssl_starttls(int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data) { - struct scd *conn = g_new0( struct scd, 1 ); - + struct scd *conn = g_new0(struct scd, 1); + conn->fd = fd; conn->func = func; conn->data = data; conn->inpa = -1; conn->verify = verify && global.conf->cafile; - conn->hostname = g_strdup( hostname ); - + conn->hostname = g_strdup(hostname); + /* This function should be called via a (short) timeout instead of directly from here, because these SSL calls are *supposed* to be *completely* asynchronous and not ready yet when this function (or *_connect, for examle) returns. Also, errors are reported via the callback function, not via this function's return value. - + In short, doing things like this makes the rest of the code a lot simpler. */ - - b_timeout_add( 1, ssl_starttls_real, conn ); - + + b_timeout_add(1, ssl_starttls_real, conn); + return conn; } -static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_starttls_real(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; - - return ssl_connected( conn, conn->fd, B_EV_IO_WRITE ); + + return ssl_connected(conn, conn->fd, B_EV_IO_WRITE); } -static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_connected(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; - - if( conn->verify ) - { + + if (conn->verify) { /* Right now we don't have any verification functionality for OpenSSL. */ - conn->func( conn->data, 1, NULL, cond ); - if( source >= 0 ) closesocket( source ); - ssl_conn_free( conn ); + conn->func(conn->data, 1, NULL, cond); + if (source >= 0) { + closesocket(source); + } + ssl_conn_free(conn); return FALSE; } - if( source == -1 ) + if (source == -1) { goto ssl_connected_failure; - - if( !initialized ) - { + } + + if (!initialized) { ssl_init(); } - - - if( ssl_ctx == NULL ) + + + if (ssl_ctx == NULL) { goto ssl_connected_failure; - - conn->ssl = SSL_new( ssl_ctx ); - if( conn->ssl == NULL ) + } + + conn->ssl = SSL_new(ssl_ctx); + if (conn->ssl == NULL) { goto ssl_connected_failure; - + } + /* We can do at least the handshake with non-blocking I/O */ - sock_make_nonblocking( conn->fd ); - SSL_set_fd( conn->ssl, conn->fd ); - - if( conn->hostname && !g_ascii_isdigit( conn->hostname[0] ) ) - SSL_set_tlsext_host_name( conn->ssl, conn->hostname ); - - return ssl_handshake( data, source, cond ); + sock_make_nonblocking(conn->fd); + SSL_set_fd(conn->ssl, conn->fd); + + if (conn->hostname && !g_ascii_isdigit(conn->hostname[0])) { + SSL_set_tlsext_host_name(conn->ssl, conn->hostname); + } + + return ssl_handshake(data, source, cond); ssl_connected_failure: - conn->func( conn->data, 0, NULL, cond ); - ssl_disconnect( conn ); + conn->func(conn->data, 0, NULL, cond); + ssl_disconnect(conn); return FALSE; -} +} -static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond ) +static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond) { struct scd *conn = data; int st; - - if( ( st = SSL_connect( conn->ssl ) ) < 0 ) - { - conn->lasterr = SSL_get_error( conn->ssl, st ); - if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE ) - { - conn->func( conn->data, 0, NULL, cond ); - ssl_disconnect( conn ); + + if ((st = SSL_connect(conn->ssl)) < 0) { + conn->lasterr = SSL_get_error(conn->ssl, st); + if (conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE) { + conn->func(conn->data, 0, NULL, cond); + ssl_disconnect(conn); return FALSE; } - - conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ), ssl_handshake, data ); + + conn->inpa = b_input_add(conn->fd, ssl_getdirection(conn), ssl_handshake, data); return FALSE; } - + conn->established = TRUE; - sock_make_blocking( conn->fd ); /* For now... */ - conn->func( conn->data, 0, conn, cond ); + sock_make_blocking(conn->fd); /* For now... */ + conn->func(conn->data, 0, conn, cond); return FALSE; } -int ssl_read( void *conn, char *buf, int len ) +int ssl_read(void *conn, char *buf, int len) { int st; - - if( !((struct scd*)conn)->established ) - { + + if (!((struct scd*) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - - st = SSL_read( ((struct scd*)conn)->ssl, buf, len ); - + + st = SSL_read(((struct scd*) conn)->ssl, buf, len); + ssl_errno = SSL_OK; - if( st <= 0 ) - { - ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); - if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) + if (st <= 0) { + ((struct scd*) conn)->lasterr = SSL_get_error(((struct scd*) conn)->ssl, st); + if (((struct scd*) conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*) conn)->lasterr == + SSL_ERROR_WANT_WRITE) { ssl_errno = SSL_AGAIN; + } } - - if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st ); - + + if (0 && getenv("BITLBEE_DEBUG") && st > 0) { + write(1, buf, st); + } + return st; } -int ssl_write( void *conn, const char *buf, int len ) +int ssl_write(void *conn, const char *buf, int len) { int st; - - if( !((struct scd*)conn)->established ) - { + + if (!((struct scd*) conn)->established) { ssl_errno = SSL_NOHANDSHAKE; return -1; } - - st = SSL_write( ((struct scd*)conn)->ssl, buf, len ); - - if( 0 && getenv( "BITLBEE_DEBUG" ) && st > 0 ) write( 1, buf, st ); - + + st = SSL_write(((struct scd*) conn)->ssl, buf, len); + + if (0 && getenv("BITLBEE_DEBUG") && st > 0) { + write(1, buf, st); + } + ssl_errno = SSL_OK; - if( st <= 0 ) - { - ((struct scd*)conn)->lasterr = SSL_get_error( ((struct scd*)conn)->ssl, st ); - if( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ) + if (st <= 0) { + ((struct scd*) conn)->lasterr = SSL_get_error(((struct scd*) conn)->ssl, st); + if (((struct scd*) conn)->lasterr == SSL_ERROR_WANT_READ || ((struct scd*) conn)->lasterr == + SSL_ERROR_WANT_WRITE) { ssl_errno = SSL_AGAIN; + } } - + return st; } -int ssl_pending( void *conn ) +int ssl_pending(void *conn) { - return ( ((struct scd*)conn) && ((struct scd*)conn)->established ) ? - SSL_pending( ((struct scd*)conn)->ssl ) > 0 : 0; + return (((struct scd*) conn) && ((struct scd*) conn)->established) ? + SSL_pending(((struct scd*) conn)->ssl) > 0 : 0; } -static void ssl_conn_free( struct scd *conn ) +static void ssl_conn_free(struct scd *conn) { - SSL_free( conn->ssl ); - g_free( conn->hostname ); - g_free( conn ); - + SSL_free(conn->ssl); + g_free(conn->hostname); + g_free(conn); + } -void ssl_disconnect( void *conn_ ) +void ssl_disconnect(void *conn_) { struct scd *conn = conn_; - - if( conn->inpa != -1 ) - b_event_remove( conn->inpa ); - - if( conn->established ) - SSL_shutdown( conn->ssl ); - - closesocket( conn->fd ); - - ssl_conn_free( conn ); + + if (conn->inpa != -1) { + b_event_remove(conn->inpa); + } + + if (conn->established) { + SSL_shutdown(conn->ssl); + } + + closesocket(conn->fd); + + ssl_conn_free(conn); } -int ssl_getfd( void *conn ) +int ssl_getfd(void *conn) { - return( ((struct scd*)conn)->fd ); + return(((struct scd*) conn)->fd); } -b_input_condition ssl_getdirection( void *conn ) +b_input_condition ssl_getdirection(void *conn) { - return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ ); + return(((struct scd*) conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ); } -char *ssl_verify_strerror( int code ) +char *ssl_verify_strerror(int code) { - return g_strdup( "SSL certificate verification not supported by BitlBee OpenSSL code." ); + return g_strdup("SSL certificate verification not supported by BitlBee OpenSSL code."); } -size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res) +size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, + const unsigned char *iv, unsigned char **res) { - int output_length = 0; + int output_length = 0; EVP_CIPHER_CTX ctx; - + *res = g_new0(unsigned char, 72); - + /* Don't set key or IV because we will modify the parameters */ EVP_CIPHER_CTX_init(&ctx); EVP_CipherInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, NULL, NULL, 1); @@ -305,8 +312,8 @@ size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1); EVP_CipherUpdate(&ctx, *res, &output_length, input, input_len); EVP_CipherFinal_ex(&ctx, *res, &output_length); - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_cleanup(&ctx); //EVP_cleanup(); - + return output_length; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2001-2005 Wilmer van der Gaast and others * @@ -26,84 +26,74 @@ #include "url.h" /* Convert an URL to a url_t structure */ -int url_set( url_t *url, const char *set_url ) +int url_set(url_t *url, const char *set_url) { - char s[MAX_STRING+1]; + char s[MAX_STRING + 1]; char *i; - - memset( url, 0, sizeof( url_t ) ); - memset( s, 0, sizeof( s ) ); - + + memset(url, 0, sizeof(url_t)); + memset(s, 0, sizeof(s)); + /* protocol:// */ - if( ( i = strstr( set_url, "://" ) ) == NULL ) - { + if ((i = strstr(set_url, "://")) == NULL) { url->proto = PROTO_DEFAULT; - strncpy( s, set_url, MAX_STRING ); - } - else - { - if( g_strncasecmp( set_url, "http", i - set_url ) == 0 ) + strncpy(s, set_url, MAX_STRING); + } else { + if (g_strncasecmp(set_url, "http", i - set_url) == 0) { url->proto = PROTO_HTTP; - else if( g_strncasecmp( set_url, "https", i - set_url ) == 0 ) + } else if (g_strncasecmp(set_url, "https", i - set_url) == 0) { url->proto = PROTO_HTTPS; - else if( g_strncasecmp( set_url, "socks4", i - set_url ) == 0 ) + } else if (g_strncasecmp(set_url, "socks4", i - set_url) == 0) { url->proto = PROTO_SOCKS4; - else if( g_strncasecmp( set_url, "socks5", i - set_url ) == 0 ) + } else if (g_strncasecmp(set_url, "socks5", i - set_url) == 0) { url->proto = PROTO_SOCKS5; - else + } else { return 0; - - strncpy( s, i + 3, MAX_STRING ); + } + + strncpy(s, i + 3, MAX_STRING); } - + /* Split */ - if( ( i = strchr( s, '/' ) ) == NULL ) - { - strcpy( url->file, "/" ); - } - else - { - strncpy( url->file, i, MAX_STRING ); + if ((i = strchr(s, '/')) == NULL) { + strcpy(url->file, "/"); + } else { + strncpy(url->file, i, MAX_STRING); *i = 0; } - strncpy( url->host, s, MAX_STRING ); - + strncpy(url->host, s, MAX_STRING); + /* Check for username in host field */ - if( strrchr( url->host, '@' ) != NULL ) - { - strncpy( url->user, url->host, MAX_STRING ); - i = strrchr( url->user, '@' ); + if (strrchr(url->host, '@') != NULL) { + strncpy(url->user, url->host, MAX_STRING); + i = strrchr(url->user, '@'); *i = 0; - strcpy( url->host, i + 1 ); + strcpy(url->host, i + 1); *url->pass = 0; } /* If not: Fill in defaults */ - else - { + else { *url->user = *url->pass = 0; } - + /* Password? */ - if( ( i = strchr( url->user, ':' ) ) != NULL ) - { + if ((i = strchr(url->user, ':')) != NULL) { *i = 0; - strcpy( url->pass, i + 1 ); + strcpy(url->pass, i + 1); } /* Port number? */ - if( ( i = strchr( url->host, ':' ) ) != NULL ) - { + if ((i = strchr(url->host, ':')) != NULL) { *i = 0; - sscanf( i + 1, "%d", &url->port ); - } - else - { - if( url->proto == PROTO_HTTP ) + sscanf(i + 1, "%d", &url->port); + } else { + if (url->proto == PROTO_HTTP) { url->port = 80; - else if( url->proto == PROTO_HTTPS ) + } else if (url->proto == PROTO_HTTPS) { url->port = 443; - else if( url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS5 ) + } else if (url->proto == PROTO_SOCKS4 || url->proto == PROTO_SOCKS5) { url->port = 1080; + } } - - return( url->port > 0 ); + + return(url->port > 0); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2001-2004 Wilmer van der Gaast and others * @@ -31,14 +31,13 @@ #define PROTO_SOCKS5 4 #define PROTO_DEFAULT PROTO_HTTP -typedef struct url -{ +typedef struct url { int proto; int port; - char host[MAX_STRING+1]; - char file[MAX_STRING+1]; - char user[MAX_STRING+1]; - char pass[MAX_STRING+1]; + char host[MAX_STRING + 1]; + char file[MAX_STRING + 1]; + char user[MAX_STRING + 1]; + char pass[MAX_STRING + 1]; } url_t; -int url_set( url_t *url, const char *set_url ); +int url_set(url_t *url, const char *set_url); diff --git a/lib/xmltree.c b/lib/xmltree.c index 6253d760..a98c91e1 100644 --- a/lib/xmltree.c +++ b/lib/xmltree.c @@ -32,74 +32,74 @@ #define g_strcasecmp g_ascii_strcasecmp #define g_strncasecmp g_ascii_strncasecmp -static void xt_start_element( GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error ) +static void xt_start_element(GMarkupParseContext *ctx, const gchar *element_name, const gchar **attr_names, + const gchar **attr_values, gpointer data, GError **error) { struct xt_parser *xt = data; - struct xt_node *node = g_new0( struct xt_node, 1 ), *nt; + struct xt_node *node = g_new0(struct xt_node, 1), *nt; int i; - + node->parent = xt->cur; - node->name = g_strdup( element_name ); - + node->name = g_strdup(element_name); + /* First count the number of attributes */ - for( i = 0; attr_names[i]; i ++ ); - + for (i = 0; attr_names[i]; i++) { + ; + } + /* Then allocate a NULL-terminated array. */ - node->attr = g_new0( struct xt_attr, i + 1 ); - + node->attr = g_new0(struct xt_attr, i + 1); + /* And fill it, saving one variable by starting at the end. */ - for( i --; i >= 0; i -- ) - { - node->attr[i].key = g_strdup( attr_names[i] ); - node->attr[i].value = g_strdup( attr_values[i] ); + for (i--; i >= 0; i--) { + node->attr[i].key = g_strdup(attr_names[i]); + node->attr[i].value = g_strdup(attr_values[i]); } - + /* Add it to the linked list of children nodes, if we have a current node yet. */ - if( xt->cur ) - { - if( xt->cur->children ) - { - for( nt = xt->cur->children; nt->next; nt = nt->next ); + if (xt->cur) { + if (xt->cur->children) { + for (nt = xt->cur->children; nt->next; nt = nt->next) { + ; + } nt->next = node; - } - else - { + } else { xt->cur->children = node; } - } - else if( xt->root ) - { + } else if (xt->root) { /* ERROR situation: A second root-element??? */ } - + /* Now this node will be the new current node. */ xt->cur = node; /* And maybe this is the root? */ - if( xt->root == NULL ) + if (xt->root == NULL) { xt->root = node; + } } -static void xt_text( GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error ) +static void xt_text(GMarkupParseContext *ctx, const gchar *text, gsize text_len, gpointer data, GError **error) { struct xt_parser *xt = data; struct xt_node *node = xt->cur; - - if( node == NULL ) + + if (node == NULL) { return; - + } + /* FIXME: Does g_renew also OFFICIALLY accept NULL arguments? */ - node->text = g_renew( char, node->text, node->text_len + text_len + 1 ); - memcpy( node->text + node->text_len, text, text_len ); + node->text = g_renew(char, node->text, node->text_len + text_len + 1); + memcpy(node->text + node->text_len, text, text_len); node->text_len += text_len; /* Zero termination is always nice to have. */ node->text[node->text_len] = 0; } -static void xt_end_element( GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error ) +static void xt_end_element(GMarkupParseContext *ctx, const gchar *element_name, gpointer data, GError **error) { struct xt_parser *xt = data; - + xt->cur->flags |= XT_COMPLETE; xt->cur = xt->cur->parent; } @@ -113,29 +113,29 @@ GMarkupParser xt_parser_funcs = NULL }; -struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data ) +struct xt_parser *xt_new(const struct xt_handler_entry *handlers, gpointer data) { - struct xt_parser *xt = g_new0( struct xt_parser, 1 ); - + struct xt_parser *xt = g_new0(struct xt_parser, 1); + xt->data = data; xt->handlers = handlers; - xt_reset( xt ); - + xt_reset(xt); + return xt; } /* Reset the parser, flush everything we have so far. For example, we need this for XMPP when doing TLS/SASL to restart the stream. */ -void xt_reset( struct xt_parser *xt ) +void xt_reset(struct xt_parser *xt) { - if( xt->parser ) - g_markup_parse_context_free( xt->parser ); - - xt->parser = g_markup_parse_context_new( &xt_parser_funcs, 0, xt, NULL ); - - if( xt->root ) - { - xt_free_node( xt->root ); + if (xt->parser) { + g_markup_parse_context_free(xt->parser); + } + + xt->parser = g_markup_parse_context_new(&xt_parser_funcs, 0, xt, NULL); + + if (xt->root) { + xt_free_node(xt->root); xt->root = NULL; xt->cur = NULL; } @@ -143,395 +143,397 @@ void xt_reset( struct xt_parser *xt ) /* Feed the parser, don't execute any handler. Returns -1 on errors, 0 on end-of-stream and 1 otherwise. */ -int xt_feed( struct xt_parser *xt, const char *text, int text_len ) +int xt_feed(struct xt_parser *xt, const char *text, int text_len) { - if( !g_markup_parse_context_parse( xt->parser, text, text_len, &xt->gerr ) ) - { + if (!g_markup_parse_context_parse(xt->parser, text, text_len, &xt->gerr)) { return -1; } - - return !( xt->root && xt->root->flags & XT_COMPLETE ); + + return !(xt->root && xt->root->flags & XT_COMPLETE); } /* Find completed nodes and see if a handler has to be called. Passing a node isn't necessary if you want to start at the root, just pass NULL. This second argument is needed for recursive calls. */ -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ) +int xt_handle(struct xt_parser *xt, struct xt_node *node, int depth) { struct xt_node *c; xt_status st; int i; - - if( xt->root == NULL ) + + if (xt->root == NULL) { return 1; - - if( node == NULL ) - return xt_handle( xt, xt->root, depth ); - - if( depth != 0 ) - for( c = node->children; c; c = c->next ) - if( !xt_handle( xt, c, depth > 0 ? depth - 1 : depth ) ) + } + + if (node == NULL) { + return xt_handle(xt, xt->root, depth); + } + + if (depth != 0) { + for (c = node->children; c; c = c->next) { + if (!xt_handle(xt, c, depth > 0 ? depth - 1 : depth)) { return 0; - - if( node->flags & XT_COMPLETE && !( node->flags & XT_SEEN ) ) - { - if( xt->handlers ) for( i = 0; xt->handlers[i].func; i ++ ) - { - /* This one is fun! \o/ */ - - /* If handler.name == NULL it means it should always match. */ - if( ( xt->handlers[i].name == NULL || - /* If it's not, compare. There should always be a name. */ - g_strcasecmp( xt->handlers[i].name, node->name ) == 0 ) && - /* If handler.parent == NULL, it's a match. */ - ( xt->handlers[i].parent == NULL || - /* If there's a parent node, see if the name matches. */ - ( node->parent ? g_strcasecmp( xt->handlers[i].parent, node->parent->name ) == 0 : - /* If there's no parent, the handler should mention <root> as a parent. */ - strcmp( xt->handlers[i].parent, "<root>" ) == 0 ) ) ) - { - st = xt->handlers[i].func( node, xt->data ); - - if( st == XT_ABORT ) - return 0; - else if( st != XT_NEXT ) - break; } } - + } + + if (node->flags & XT_COMPLETE && !(node->flags & XT_SEEN)) { + if (xt->handlers) { + for (i = 0; xt->handlers[i].func; i++) { + /* This one is fun! \o/ */ + + /* If handler.name == NULL it means it should always match. */ + if ((xt->handlers[i].name == NULL || + /* If it's not, compare. There should always be a name. */ + g_strcasecmp(xt->handlers[i].name, node->name) == 0) && + /* If handler.parent == NULL, it's a match. */ + (xt->handlers[i].parent == NULL || + /* If there's a parent node, see if the name matches. */ + (node->parent ? g_strcasecmp(xt->handlers[i].parent, node->parent->name) == 0 : + /* If there's no parent, the handler should mention <root> as a parent. */ + strcmp(xt->handlers[i].parent, "<root>") == 0))) { + st = xt->handlers[i].func(node, xt->data); + + if (st == XT_ABORT) { + return 0; + } else if (st != XT_NEXT) { + break; + } + } + } + } + node->flags |= XT_SEEN; } - + return 1; } /* Garbage collection: Cleans up all nodes that are handled. Useful for streams because there's no reason to keep a complete packet history in memory. */ -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ) +void xt_cleanup(struct xt_parser *xt, struct xt_node *node, int depth) { struct xt_node *c, *prev; - - if( !xt || !xt->root ) + + if (!xt || !xt->root) { return; - - if( node == NULL ) - { - xt_cleanup( xt, xt->root, depth ); + } + + if (node == NULL) { + xt_cleanup(xt, xt->root, depth); return; } - - if( node->flags & XT_SEEN && node == xt->root ) - { - xt_free_node( xt->root ); + + if (node->flags & XT_SEEN && node == xt->root) { + xt_free_node(xt->root); xt->root = xt->cur = NULL; /* xt->cur should be NULL already, BTW... */ - + return; } - + /* c contains the current node, prev the previous node (or NULL). I admit, this one's pretty horrible. */ - for( c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children ) - { - if( c->flags & XT_SEEN ) - { + for (c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children) { + if (c->flags & XT_SEEN) { /* Remove the node from the linked list. */ - if( prev ) + if (prev) { prev->next = c->next; - else + } else { node->children = c->next; - - xt_free_node( c ); - + } + + xt_free_node(c); + /* Since the for loop wants to get c->next, make sure c points at something that exists (and that c->next will actually be the next item we should check). c can be NULL now, if we just removed the first item. That explains the ? thing in for(). */ c = prev; - } - else - { + } else { /* This node can't be cleaned up yet, but maybe a subnode can. */ - if( depth != 0 ) - xt_cleanup( xt, c, depth > 0 ? depth - 1 : depth ); + if (depth != 0) { + xt_cleanup(xt, c, depth > 0 ? depth - 1 : depth); + } } } } -struct xt_node *xt_from_string( const char *in, int len ) +struct xt_node *xt_from_string(const char *in, int len) { struct xt_parser *parser; struct xt_node *ret = NULL; - - if( len == 0 ) - len = strlen( in ); - - parser = xt_new( NULL, NULL ); - xt_feed( parser, in, len ); - if( parser->cur == NULL ) - { + + if (len == 0) { + len = strlen(in); + } + + parser = xt_new(NULL, NULL); + xt_feed(parser, in, len); + if (parser->cur == NULL) { ret = parser->root; parser->root = NULL; } - xt_free( parser ); - + xt_free(parser); + return ret; } -static void xt_to_string_real( struct xt_node *node, GString *str, int indent ) +static void xt_to_string_real(struct xt_node *node, GString *str, int indent) { char *buf; struct xt_node *c; int i; - - if( indent > 1 ) - g_string_append_len( str, "\n\t\t\t\t\t\t\t\t", - indent < 8 ? indent : 8 ); - - g_string_append_printf( str, "<%s", node->name ); - - for( i = 0; node->attr[i].key; i ++ ) - { - buf = g_markup_printf_escaped( " %s=\"%s\"", node->attr[i].key, node->attr[i].value ); - g_string_append( str, buf ); - g_free( buf ); - } - - if( node->text == NULL && node->children == NULL ) - { - g_string_append( str, "/>" ); + + if (indent > 1) { + g_string_append_len(str, "\n\t\t\t\t\t\t\t\t", + indent < 8 ? indent : 8); + } + + g_string_append_printf(str, "<%s", node->name); + + for (i = 0; node->attr[i].key; i++) { + buf = g_markup_printf_escaped(" %s=\"%s\"", node->attr[i].key, node->attr[i].value); + g_string_append(str, buf); + g_free(buf); + } + + if (node->text == NULL && node->children == NULL) { + g_string_append(str, "/>"); return; } - - g_string_append( str, ">" ); - if( node->text_len > 0 ) - { - buf = g_markup_escape_text( node->text, node->text_len ); - g_string_append( str, buf ); - g_free( buf ); - } - - for( c = node->children; c; c = c->next ) - xt_to_string_real( c, str, indent ? indent + 1 : 0 ); - - if( indent > 0 && node->children ) - g_string_append_len( str, "\n\t\t\t\t\t\t\t\t", - indent < 8 ? indent : 8 ); - - g_string_append_printf( str, "</%s>", node->name ); + + g_string_append(str, ">"); + if (node->text_len > 0) { + buf = g_markup_escape_text(node->text, node->text_len); + g_string_append(str, buf); + g_free(buf); + } + + for (c = node->children; c; c = c->next) { + xt_to_string_real(c, str, indent ? indent + 1 : 0); + } + + if (indent > 0 && node->children) { + g_string_append_len(str, "\n\t\t\t\t\t\t\t\t", + indent < 8 ? indent : 8); + } + + g_string_append_printf(str, "</%s>", node->name); } -char *xt_to_string( struct xt_node *node ) +char *xt_to_string(struct xt_node *node) { GString *ret; - - ret = g_string_new( "" ); - xt_to_string_real( node, ret, 0 ); - return g_string_free( ret, FALSE ); + + ret = g_string_new(""); + xt_to_string_real(node, ret, 0); + return g_string_free(ret, FALSE); } /* WITH indentation! */ -char *xt_to_string_i( struct xt_node *node ) +char *xt_to_string_i(struct xt_node *node) { GString *ret; - - ret = g_string_new( "" ); - xt_to_string_real( node, ret, 1 ); - return g_string_free( ret, FALSE ); + + ret = g_string_new(""); + xt_to_string_real(node, ret, 1); + return g_string_free(ret, FALSE); } -void xt_print( struct xt_node *node ) +void xt_print(struct xt_node *node) { - char *str = xt_to_string_i( node ); - fprintf( stderr, "%s", str ); - g_free( str ); + char *str = xt_to_string_i(node); + + fprintf(stderr, "%s", str); + g_free(str); } -struct xt_node *xt_dup( struct xt_node *node ) +struct xt_node *xt_dup(struct xt_node *node) { - struct xt_node *dup = g_new0( struct xt_node, 1 ); + struct xt_node *dup = g_new0(struct xt_node, 1); struct xt_node *c, *dc = NULL; int i; - + /* Let's NOT copy the parent element here BTW! Only do it for children. */ - - dup->name = g_strdup( node->name ); + + dup->name = g_strdup(node->name); dup->flags = node->flags; - if( node->text ) - { - dup->text = g_memdup( node->text, node->text_len + 1 ); + if (node->text) { + dup->text = g_memdup(node->text, node->text_len + 1); dup->text_len = node->text_len; } - + /* Count the number of attributes and allocate the new array. */ - for( i = 0; node->attr[i].key; i ++ ); - dup->attr = g_new0( struct xt_attr, i + 1 ); - + for (i = 0; node->attr[i].key; i++) { + ; + } + dup->attr = g_new0(struct xt_attr, i + 1); + /* Copy them all! */ - for( i --; i >= 0; i -- ) - { - dup->attr[i].key = g_strdup( node->attr[i].key ); - dup->attr[i].value = g_strdup( node->attr[i].value ); + for (i--; i >= 0; i--) { + dup->attr[i].key = g_strdup(node->attr[i].key); + dup->attr[i].value = g_strdup(node->attr[i].value); } - + /* This nice mysterious loop takes care of the children. */ - for( c = node->children; c; c = c->next ) - { - if( dc == NULL ) - dc = dup->children = xt_dup( c ); - else - dc = ( dc->next = xt_dup( c ) ); - + for (c = node->children; c; c = c->next) { + if (dc == NULL) { + dc = dup->children = xt_dup(c); + } else { + dc = (dc->next = xt_dup(c)); + } + dc->parent = dup; } - + return dup; } /* Frees a node. This doesn't clean up references to itself from parents! */ -void xt_free_node( struct xt_node *node ) +void xt_free_node(struct xt_node *node) { int i; - - if( !node ) + + if (!node) { return; - - g_free( node->name ); - g_free( node->text ); - - for( i = 0; node->attr[i].key; i ++ ) - { - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - } - g_free( node->attr ); - - while( node->children ) - { + } + + g_free(node->name); + g_free(node->text); + + for (i = 0; node->attr[i].key; i++) { + g_free(node->attr[i].key); + g_free(node->attr[i].value); + } + g_free(node->attr); + + while (node->children) { struct xt_node *next = node->children->next; - - xt_free_node( node->children ); + + xt_free_node(node->children); node->children = next; } - - g_free( node ); + + g_free(node); } -void xt_free( struct xt_parser *xt ) +void xt_free(struct xt_parser *xt) { - if( !xt ) + if (!xt) { return; - - if( xt->root ) - xt_free_node( xt->root ); - - g_markup_parse_context_free( xt->parser ); - - g_free( xt ); + } + + if (xt->root) { + xt_free_node(xt->root); + } + + g_markup_parse_context_free(xt->parser); + + g_free(xt); } /* To find a node's child with a specific name, pass the node's children list, not the node itself! The reason you have to do this by hand: So that you can also use this function as a find-next. */ -struct xt_node *xt_find_node( struct xt_node *node, const char *name ) +struct xt_node *xt_find_node(struct xt_node *node, const char *name) { - while( node ) - { + while (node) { char *colon; - - if( g_strcasecmp( node->name, name ) == 0 || - ( ( colon = strchr( node->name, ':' ) ) && - g_strcasecmp( colon + 1, name ) == 0 ) ) + + if (g_strcasecmp(node->name, name) == 0 || + ((colon = strchr(node->name, ':')) && + g_strcasecmp(colon + 1, name) == 0)) { break; - + } + node = node->next; } - + return node; } /* More advanced than the one above, understands something like ../foo/bar to find a subnode bar of a node foo which is a child of node's parent. Pass the node directly, not its list of children. */ -struct xt_node *xt_find_path( struct xt_node *node, const char *name ) +struct xt_node *xt_find_path(struct xt_node *node, const char *name) { - while( name && *name && node ) - { + while (name && *name && node) { char *colon, *slash; int n; - - if( ( slash = strchr( name, '/' ) ) ) + + if ((slash = strchr(name, '/'))) { n = slash - name; - else - n = strlen( name ); - - if( strncmp( name, "..", n ) == 0 ) - { - node = node->parent; + } else { + n = strlen(name); } - else - { + + if (strncmp(name, "..", n) == 0) { + node = node->parent; + } else { node = node->children; - - while( node ) - { - if( g_strncasecmp( node->name, name, n ) == 0 || - ( ( colon = strchr( node->name, ':' ) ) && - g_strncasecmp( colon + 1, name, n ) == 0 ) ) + + while (node) { + if (g_strncasecmp(node->name, name, n) == 0 || + ((colon = strchr(node->name, ':')) && + g_strncasecmp(colon + 1, name, n) == 0)) { break; - + } + node = node->next; } } - + name = slash ? slash + 1 : NULL; } - + return node; } -char *xt_find_attr( struct xt_node *node, const char *key ) +char *xt_find_attr(struct xt_node *node, const char *key) { int i; char *colon; - - if( !node ) + + if (!node) { return NULL; - - for( i = 0; node->attr[i].key; i ++ ) - if( g_strcasecmp( node->attr[i].key, key ) == 0 ) + } + + for (i = 0; node->attr[i].key; i++) { + if (g_strcasecmp(node->attr[i].key, key) == 0) { break; - + } + } + /* This is an awful hack that only takes care of namespace prefixes inside a tag. Since IMHO excessive namespace usage in XMPP is massive overkill anyway (this code exists for almost four years now and never really missed it): Meh. */ - if( !node->attr[i].key && strcmp( key, "xmlns" ) == 0 && - ( colon = strchr( node->name, ':' ) ) ) - { + if (!node->attr[i].key && strcmp(key, "xmlns") == 0 && + (colon = strchr(node->name, ':'))) { *colon = '\0'; - for( i = 0; node->attr[i].key; i ++ ) - if( strncmp( node->attr[i].key, "xmlns:", 6 ) == 0 && - strcmp( node->attr[i].key + 6, node->name ) == 0 ) + for (i = 0; node->attr[i].key; i++) { + if (strncmp(node->attr[i].key, "xmlns:", 6) == 0 && + strcmp(node->attr[i].key + 6, node->name) == 0) { break; + } + } *colon = ':'; } - + return node->attr[i].value; } -struct xt_node *xt_find_node_by_attr( struct xt_node *xt, const char *tag, const char *key, const char *value ) +struct xt_node *xt_find_node_by_attr(struct xt_node *xt, const char *tag, const char *key, const char *value) { struct xt_node *c; char *s; - for( c = xt; ( c = xt_find_node( c, tag ) ); c = c->next ) - { - if( ( s = xt_find_attr( c, key ) ) && strcmp( s, value ) == 0 ) - { + for (c = xt; (c = xt_find_node(c, tag)); c = c->next) { + if ((s = xt_find_attr(c, key)) && strcmp(s, value) == 0) { return c; } } @@ -541,164 +543,159 @@ struct xt_node *xt_find_node_by_attr( struct xt_node *xt, const char *tag, const /* Strip a few non-printable characters that aren't allowed in XML streams (and upset some XMPP servers for example). */ -void xt_strip_text( char *in ) +void xt_strip_text(char *in) { char *out = in; static const char nonprint[32] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 0..7 */ 0, 1, 1, 0, 0, 1, 0, 0, /* 9 (tab), 10 (\n), 13 (\r) */ }; - - if( !in ) + + if (!in) { return; + } - while( *in ) - { - if( (unsigned int) *in >= ' ' || nonprint[(unsigned int) *in] ) - *out ++ = *in; - in ++; + while (*in) { + if ((unsigned int) *in >= ' ' || nonprint[(unsigned int) *in]) { + *out++ = *in; + } + in++; } *out = *in; } -struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children ) +struct xt_node *xt_new_node(char *name, const char *text, struct xt_node *children) { struct xt_node *node, *c; - - node = g_new0( struct xt_node, 1 ); - node->name = g_strdup( name ); + + node = g_new0(struct xt_node, 1); + node->name = g_strdup(name); node->children = children; - node->attr = g_new0( struct xt_attr, 1 ); - - if( text ) - { - node->text = g_strdup( text ); - xt_strip_text( node->text ); - node->text_len = strlen( node->text ); - } - - for( c = children; c; c = c->next ) - { - if( c->parent != NULL ) - { + node->attr = g_new0(struct xt_attr, 1); + + if (text) { + node->text = g_strdup(text); + xt_strip_text(node->text); + node->text_len = strlen(node->text); + } + + for (c = children; c; c = c->next) { + if (c->parent != NULL) { /* ERROR CONDITION: They seem to have a parent already??? */ } - + c->parent = node; } - + return node; } -void xt_add_child( struct xt_node *parent, struct xt_node *child ) +void xt_add_child(struct xt_node *parent, struct xt_node *child) { struct xt_node *node; - + /* This function can actually be used to add more than one child, so do handle this properly. */ - for( node = child; node; node = node->next ) - { - if( node->parent != NULL ) - { + for (node = child; node; node = node->next) { + if (node->parent != NULL) { /* ERROR CONDITION: They seem to have a parent already??? */ } - + node->parent = parent; } - - if( parent->children == NULL ) - { + + if (parent->children == NULL) { parent->children = child; - } - else - { - for( node = parent->children; node->next; node = node->next ); + } else { + for (node = parent->children; node->next; node = node->next) { + ; + } node->next = child; } } /* Same, but at the beginning. */ -void xt_insert_child( struct xt_node *parent, struct xt_node *child ) +void xt_insert_child(struct xt_node *parent, struct xt_node *child) { struct xt_node *node, *last = NULL; - - if( child == NULL ) + + if (child == NULL) { return; /* BUG */ - - for( node = child; node; node = node->next ) - { - if( node->parent != NULL ) - { + + } + for (node = child; node; node = node->next) { + if (node->parent != NULL) { /* ERROR CONDITION: They seem to have a parent already??? */ } - + node->parent = parent; last = node; } - + last->next = parent->children; parent->children = child; } -void xt_add_attr( struct xt_node *node, const char *key, const char *value ) +void xt_add_attr(struct xt_node *node, const char *key, const char *value) { int i; - + /* Now actually it'd be nice if we can also change existing attributes (which actually means this function doesn't have the right name). So let's find out if we have this attribute already... */ - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) + for (i = 0; node->attr[i].key; i++) { + if (strcmp(node->attr[i].key, key) == 0) { break; - - if( node->attr[i].key == NULL ) - { - /* If not, allocate space for a new attribute. */ - node->attr = g_renew( struct xt_attr, node->attr, i + 2 ); - node->attr[i].key = g_strdup( key ); - node->attr[i+1].key = NULL; + } } - else - { + + if (node->attr[i].key == NULL) { + /* If not, allocate space for a new attribute. */ + node->attr = g_renew(struct xt_attr, node->attr, i + 2); + node->attr[i].key = g_strdup(key); + node->attr[i + 1].key = NULL; + } else { /* Otherwise, free the old value before setting the new one. */ - g_free( node->attr[i].value ); + g_free(node->attr[i].value); } - - node->attr[i].value = g_strdup( value ); + + node->attr[i].value = g_strdup(value); } -int xt_remove_attr( struct xt_node *node, const char *key ) +int xt_remove_attr(struct xt_node *node, const char *key) { int i, last; - - for( i = 0; node->attr[i].key; i ++ ) - if( strcmp( node->attr[i].key, key ) == 0 ) + + for (i = 0; node->attr[i].key; i++) { + if (strcmp(node->attr[i].key, key) == 0) { break; - + } + } + /* If we didn't find the attribute... */ - if( node->attr[i].key == NULL ) + if (node->attr[i].key == NULL) { return 0; - - g_free( node->attr[i].key ); - g_free( node->attr[i].value ); - + } + + g_free(node->attr[i].key); + g_free(node->attr[i].value); + /* If it's the last, this is easy: */ - if( node->attr[i+1].key == NULL ) - { + if (node->attr[i + 1].key == NULL) { node->attr[i].key = node->attr[i].value = NULL; - } - else /* It's also pretty easy, actually. */ - { + } else { /* It's also pretty easy, actually. */ /* Find the last item. */ - for( last = i + 1; node->attr[last+1].key; last ++ ); - + for (last = i + 1; node->attr[last + 1].key; last++) { + ; + } + node->attr[i] = node->attr[last]; node->attr[last].key = NULL; node->attr[last].value = NULL; } - + /* Let's not bother with reallocating memory here. It takes time and most packets don't stay in memory for long anyway. */ - + return 1; } diff --git a/lib/xmltree.h b/lib/xmltree.h index af13b859..85b10983 100644 --- a/lib/xmltree.h +++ b/lib/xmltree.h @@ -24,79 +24,73 @@ #ifndef _XMLTREE_H #define _XMLTREE_H -typedef enum -{ - XT_COMPLETE = 1, /* </tag> reached */ - XT_SEEN = 2, /* Handler called (or not defined) */ +typedef enum { + XT_COMPLETE = 1, /* </tag> reached */ + XT_SEEN = 2, /* Handler called (or not defined) */ } xt_flags; -typedef enum -{ - XT_ABORT, /* Abort, don't handle the rest anymore */ - XT_HANDLED, /* Handled this tag properly, go to the next one */ - XT_NEXT /* Try if there's another matching handler */ +typedef enum { + XT_ABORT, /* Abort, don't handle the rest anymore */ + XT_HANDLED, /* Handled this tag properly, go to the next one */ + XT_NEXT /* Try if there's another matching handler */ } xt_status; -struct xt_attr -{ +struct xt_attr { char *key, *value; }; -struct xt_node -{ +struct xt_node { struct xt_node *parent; struct xt_node *children; - + char *name; struct xt_attr *attr; char *text; int text_len; - + struct xt_node *next; xt_flags flags; }; -typedef xt_status (*xt_handler_func) ( struct xt_node *node, gpointer data ); +typedef xt_status (*xt_handler_func) (struct xt_node *node, gpointer data); -struct xt_handler_entry -{ +struct xt_handler_entry { char *name, *parent; xt_handler_func func; }; -struct xt_parser -{ +struct xt_parser { GMarkupParseContext *parser; struct xt_node *root; struct xt_node *cur; - + const struct xt_handler_entry *handlers; gpointer data; - + GError *gerr; }; -struct xt_parser *xt_new( const struct xt_handler_entry *handlers, gpointer data ); -void xt_reset( struct xt_parser *xt ); -int xt_feed( struct xt_parser *xt, const char *text, int text_len ); -int xt_handle( struct xt_parser *xt, struct xt_node *node, int depth ); -void xt_cleanup( struct xt_parser *xt, struct xt_node *node, int depth ); -struct xt_node *xt_from_string( const char *in, int text_len ); -char *xt_to_string( struct xt_node *node ); -char *xt_to_string_i( struct xt_node *node ); -void xt_print( struct xt_node *node ); -struct xt_node *xt_dup( struct xt_node *node ); -void xt_free_node( struct xt_node *node ); -void xt_free( struct xt_parser *xt ); -struct xt_node *xt_find_node( struct xt_node *node, const char *name ); -struct xt_node *xt_find_path( struct xt_node *node, const char *name ); -char *xt_find_attr( struct xt_node *node, const char *key ); -struct xt_node *xt_find_node_by_attr( struct xt_node *xt, const char *tag, const char *key, const char *value ); +struct xt_parser *xt_new(const struct xt_handler_entry *handlers, gpointer data); +void xt_reset(struct xt_parser *xt); +int xt_feed(struct xt_parser *xt, const char *text, int text_len); +int xt_handle(struct xt_parser *xt, struct xt_node *node, int depth); +void xt_cleanup(struct xt_parser *xt, struct xt_node *node, int depth); +struct xt_node *xt_from_string(const char *in, int text_len); +char *xt_to_string(struct xt_node *node); +char *xt_to_string_i(struct xt_node *node); +void xt_print(struct xt_node *node); +struct xt_node *xt_dup(struct xt_node *node); +void xt_free_node(struct xt_node *node); +void xt_free(struct xt_parser *xt); +struct xt_node *xt_find_node(struct xt_node *node, const char *name); +struct xt_node *xt_find_path(struct xt_node *node, const char *name); +char *xt_find_attr(struct xt_node *node, const char *key); +struct xt_node *xt_find_node_by_attr(struct xt_node *xt, const char *tag, const char *key, const char *value); -struct xt_node *xt_new_node( char *name, const char *text, struct xt_node *children ); -void xt_add_child( struct xt_node *parent, struct xt_node *child ); -void xt_insert_child( struct xt_node *parent, struct xt_node *child ); -void xt_add_attr( struct xt_node *node, const char *key, const char *value ); -int xt_remove_attr( struct xt_node *node, const char *key ); +struct xt_node *xt_new_node(char *name, const char *text, struct xt_node *children); +void xt_add_child(struct xt_node *parent, struct xt_node *child); +void xt_insert_child(struct xt_node *parent, struct xt_node *child); +void xt_add_attr(struct xt_node *node, const char *key, const char *value); +int xt_remove_attr(struct xt_node *node, const char *key); #endif @@ -1,10 +1,10 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2005 Wilmer van der Gaast and others * \********************************************************************/ -/* Logging services for the bee */ +/* Logging services for the bee */ /* This program is free software; you can redistribute it and/or modify @@ -34,8 +34,9 @@ static void log_irc(int level, const char *logmessage); static void log_syslog(int level, const char *logmessage); static void log_console(int level, const char *logmessage); -void log_init(void) { - openlog("bitlbee", LOG_PID, LOG_DAEMON); +void log_init(void) +{ + openlog("bitlbee", LOG_PID, LOG_DAEMON); logoutput.informational = &log_null; logoutput.warning = &log_null; @@ -47,56 +48,60 @@ void log_init(void) { return; } -void log_link(int level, int output) { +void log_link(int level, int output) +{ /* I know it's ugly, but it works and I didn't feel like messing with pointer to function pointers */ - if(level == LOGLVL_INFO) { - if(output == LOGOUTPUT_NULL) - logoutput.informational = &log_null; - else if(output == LOGOUTPUT_IRC) - logoutput.informational = &log_irc; - else if(output == LOGOUTPUT_SYSLOG) - logoutput.informational = &log_syslog; - else if(output == LOGOUTPUT_CONSOLE) - logoutput.informational = &log_console; - } - else if(level == LOGLVL_WARNING) { - if(output == LOGOUTPUT_NULL) + if (level == LOGLVL_INFO) { + if (output == LOGOUTPUT_NULL) { + logoutput.informational = &log_null; + } else if (output == LOGOUTPUT_IRC) { + logoutput.informational = &log_irc; + } else if (output == LOGOUTPUT_SYSLOG) { + logoutput.informational = &log_syslog; + } else if (output == LOGOUTPUT_CONSOLE) { + logoutput.informational = &log_console; + } + } else if (level == LOGLVL_WARNING) { + if (output == LOGOUTPUT_NULL) { logoutput.warning = &log_null; - else if(output == LOGOUTPUT_IRC) + } else if (output == LOGOUTPUT_IRC) { logoutput.warning = &log_irc; - else if(output == LOGOUTPUT_SYSLOG) + } else if (output == LOGOUTPUT_SYSLOG) { logoutput.warning = &log_syslog; - else if(output == LOGOUTPUT_CONSOLE) + } else if (output == LOGOUTPUT_CONSOLE) { logoutput.warning = &log_console; - } - else if(level == LOGLVL_ERROR) { - if(output == LOGOUTPUT_NULL) + } + } else if (level == LOGLVL_ERROR) { + if (output == LOGOUTPUT_NULL) { logoutput.error = &log_null; - else if(output == LOGOUTPUT_IRC) + } else if (output == LOGOUTPUT_IRC) { logoutput.error = &log_irc; - else if(output == LOGOUTPUT_SYSLOG) + } else if (output == LOGOUTPUT_SYSLOG) { logoutput.error = &log_syslog; - else if(output == LOGOUTPUT_CONSOLE) + } else if (output == LOGOUTPUT_CONSOLE) { logoutput.error = &log_console; + } } #ifdef DEBUG - else if(level == LOGLVL_DEBUG) { - if(output == LOGOUTPUT_NULL) + else if (level == LOGLVL_DEBUG) { + if (output == LOGOUTPUT_NULL) { logoutput.debug = &log_null; - else if(output == LOGOUTPUT_IRC) + } else if (output == LOGOUTPUT_IRC) { logoutput.debug = &log_irc; - else if(output == LOGOUTPUT_SYSLOG) + } else if (output == LOGOUTPUT_SYSLOG) { logoutput.debug = &log_syslog; - else if(output == LOGOUTPUT_CONSOLE) + } else if (output == LOGOUTPUT_CONSOLE) { logoutput.debug = &log_console; + } } #endif - return; + return; } -void log_message(int level, const char *message, ... ) { +void log_message(int level, const char *message, ...) +{ va_list ap; char *msgstring; @@ -105,71 +110,92 @@ void log_message(int level, const char *message, ... ) { msgstring = g_strdup_vprintf(message, ap); va_end(ap); - if(level == LOGLVL_INFO) + if (level == LOGLVL_INFO) { (*(logoutput.informational))(level, msgstring); - if(level == LOGLVL_WARNING) + } + if (level == LOGLVL_WARNING) { (*(logoutput.warning))(level, msgstring); - if(level == LOGLVL_ERROR) + } + if (level == LOGLVL_ERROR) { (*(logoutput.error))(level, msgstring); + } #ifdef DEBUG - if(level == LOGLVL_DEBUG) + if (level == LOGLVL_DEBUG) { (*(logoutput.debug))(level, msgstring); + } #endif g_free(msgstring); - + return; } -void log_error(const char *functionname) { +void log_error(const char *functionname) +{ log_message(LOGLVL_ERROR, "%s: %s", functionname, strerror(errno)); - + return; } -static void log_null(int level, const char *message) { +static void log_null(int level, const char *message) +{ return; } -static void log_irc(int level, const char *message) { - if(level == LOGLVL_ERROR) +static void log_irc(int level, const char *message) +{ + if (level == LOGLVL_ERROR) { irc_write_all(1, "ERROR :Error: %s", message); - if(level == LOGLVL_WARNING) + } + if (level == LOGLVL_WARNING) { irc_write_all(0, "ERROR :Warning: %s", message); - if(level == LOGLVL_INFO) - irc_write_all(0, "ERROR :Informational: %s", message); + } + if (level == LOGLVL_INFO) { + irc_write_all(0, "ERROR :Informational: %s", message); + } #ifdef DEBUG - if(level == LOGLVL_DEBUG) - irc_write_all(0, "ERROR :Debug: %s", message); -#endif + if (level == LOGLVL_DEBUG) { + irc_write_all(0, "ERROR :Debug: %s", message); + } +#endif return; } -static void log_syslog(int level, const char *message) { - if(level == LOGLVL_ERROR) +static void log_syslog(int level, const char *message) +{ + if (level == LOGLVL_ERROR) { syslog(LOG_ERR, "%s", message); - if(level == LOGLVL_WARNING) + } + if (level == LOGLVL_WARNING) { syslog(LOG_WARNING, "%s", message); - if(level == LOGLVL_INFO) + } + if (level == LOGLVL_INFO) { syslog(LOG_INFO, "%s", message); + } #ifdef DEBUG - if(level == LOGLVL_DEBUG) + if (level == LOGLVL_DEBUG) { syslog(LOG_DEBUG, "%s", message); + } #endif return; } -static void log_console(int level, const char *message) { - if(level == LOGLVL_ERROR) +static void log_console(int level, const char *message) +{ + if (level == LOGLVL_ERROR) { fprintf(stderr, "Error: %s\n", message); - if(level == LOGLVL_WARNING) + } + if (level == LOGLVL_WARNING) { fprintf(stderr, "Warning: %s\n", message); - if(level == LOGLVL_INFO) + } + if (level == LOGLVL_INFO) { fprintf(stdout, "Informational: %s\n", message); + } #ifdef DEBUG - if(level == LOGLVL_DEBUG) + if (level == LOGLVL_DEBUG) { fprintf(stdout, "Debug: %s\n", message); + } #endif /* Always log stuff in syslogs too. */ log_syslog(level, message); @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2005 Wilmer van der Gaast and others * @@ -44,7 +44,7 @@ typedef enum { typedef struct log_t { void (*error)(int level, const char *logmessage); - void (*warning)(int level, const char *logmessage); + void (*warning)(int level, const char *logmessage); void (*informational)(int level, const char *logmessage); #ifdef DEBUG void (*debug)(int level, const char *logmessage); @@ -53,7 +53,7 @@ typedef struct log_t { void log_init(void); void log_link(int level, int output); -void log_message(int level, const char *message, ...) G_GNUC_PRINTF( 2, 3 ); +void log_message(int level, const char *message, ...) G_GNUC_PRINTF(2, 3); void log_error(const char *functionname); #endif @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -33,243 +33,218 @@ static char *nick_lc_chars = "0123456789abcdefghijklmnopqrstuvwxyz{}^`-_|"; static char *nick_uc_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]~`-_\\"; /* Store handles in lower case and strip spaces, because AIM is braindead. */ -static char *clean_handle( const char *orig ) +static char *clean_handle(const char *orig) { - char *new = g_malloc( strlen( orig ) + 1 ); + char *new = g_malloc(strlen(orig) + 1); int i = 0; - + do { - if (*orig != ' ') - new[i++] = g_ascii_tolower( *orig ); - } - while (*(orig++)); - + if (*orig != ' ') { + new[i++] = g_ascii_tolower(*orig); + } + } while (*(orig++)); + return new; } -void nick_set_raw( account_t *acc, const char *handle, const char *nick ) +void nick_set_raw(account_t *acc, const char *handle, const char *nick) { - char *store_handle, *store_nick = g_malloc( MAX_NICK_LENGTH + 1 ); + char *store_handle, *store_nick = g_malloc(MAX_NICK_LENGTH + 1); irc_t *irc = (irc_t *) acc->bee->ui_data; - - store_handle = clean_handle( handle ); + + store_handle = clean_handle(handle); store_nick[MAX_NICK_LENGTH] = '\0'; - strncpy( store_nick, nick, MAX_NICK_LENGTH ); - nick_strip( irc, store_nick ); - - g_hash_table_replace( acc->nicks, store_handle, store_nick ); + strncpy(store_nick, nick, MAX_NICK_LENGTH); + nick_strip(irc, store_nick); + + g_hash_table_replace(acc->nicks, store_handle, store_nick); } -void nick_set( bee_user_t *bu, const char *nick ) +void nick_set(bee_user_t *bu, const char *nick) { - nick_set_raw( bu->ic->acc, bu->handle, nick ); + nick_set_raw(bu->ic->acc, bu->handle, nick); } -char *nick_get( bee_user_t *bu ) +char *nick_get(bee_user_t *bu) { - static char nick[MAX_NICK_LENGTH+1]; + static char nick[MAX_NICK_LENGTH + 1]; char *store_handle, *found_nick; irc_t *irc = (irc_t *) bu->bee->ui_data; - - memset( nick, 0, MAX_NICK_LENGTH + 1 ); - - store_handle = clean_handle( bu->handle ); + + memset(nick, 0, MAX_NICK_LENGTH + 1); + + store_handle = clean_handle(bu->handle); /* Find out if we stored a nick for this person already. If not, try to generate a sane nick automatically. */ - if( ( found_nick = g_hash_table_lookup( bu->ic->acc->nicks, store_handle ) ) ) - { - strncpy( nick, found_nick, MAX_NICK_LENGTH ); - } - else if( ( found_nick = nick_gen( bu ) ) ) - { - strncpy( nick, found_nick, MAX_NICK_LENGTH ); - g_free( found_nick ); - } - else - { + if ((found_nick = g_hash_table_lookup(bu->ic->acc->nicks, store_handle))) { + strncpy(nick, found_nick, MAX_NICK_LENGTH); + } else if ((found_nick = nick_gen(bu))) { + strncpy(nick, found_nick, MAX_NICK_LENGTH); + g_free(found_nick); + } else { /* Keep this fallback since nick_gen() can return NULL in some cases. */ char *s; - - g_snprintf( nick, MAX_NICK_LENGTH, "%s", bu->handle ); - if( ( s = strchr( nick, '@' ) ) ) - while( *s ) + + g_snprintf(nick, MAX_NICK_LENGTH, "%s", bu->handle); + if ((s = strchr(nick, '@'))) { + while (*s) { *(s++) = 0; - - nick_strip( irc, nick ); - if( set_getbool( &bu->bee->set, "lcnicks" ) ) - nick_lc( irc, nick ); + } + } + + nick_strip(irc, nick); + if (set_getbool(&bu->bee->set, "lcnicks")) { + nick_lc(irc, nick); + } } - g_free( store_handle ); - + g_free(store_handle); + /* Make sure the nick doesn't collide with an existing one by adding underscores and that kind of stuff, if necessary. */ - nick_dedupe( bu, nick ); - + nick_dedupe(bu, nick); + return nick; } -char *nick_gen( bee_user_t *bu ) +char *nick_gen(bee_user_t *bu) { gboolean ok = FALSE; /* Set to true once the nick contains something unique. */ - GString *ret = g_string_sized_new( MAX_NICK_LENGTH + 1 ); + GString *ret = g_string_sized_new(MAX_NICK_LENGTH + 1); char *rets; irc_t *irc = (irc_t *) bu->bee->ui_data; - char *fmt = set_getstr( &bu->ic->acc->set, "nick_format" ) ? : - set_getstr( &bu->bee->set, "nick_format" ); - - while( fmt && *fmt && ret->len < MAX_NICK_LENGTH ) - { + char *fmt = set_getstr(&bu->ic->acc->set, "nick_format") ? : + set_getstr(&bu->bee->set, "nick_format"); + + while (fmt && *fmt && ret->len < MAX_NICK_LENGTH) { char *part = NULL, chop = '\0', *asc = NULL, *s; int len = INT_MAX; - - if( *fmt != '%' ) - { - g_string_append_c( ret, *fmt ); - fmt ++; + + if (*fmt != '%') { + g_string_append_c(ret, *fmt); + fmt++; continue; } - - fmt ++; - while( *fmt ) - { + + fmt++; + while (*fmt) { /* -char means chop off everything from char */ - if( *fmt == '-' ) - { + if (*fmt == '-') { chop = fmt[1]; - if( chop == '\0' ) - { - g_string_free( ret, TRUE ); + if (chop == '\0') { + g_string_free(ret, TRUE); return NULL; } fmt += 2; - } - else if( g_ascii_isdigit( *fmt ) ) - { + } else if (g_ascii_isdigit(*fmt)) { len = 0; /* Grab a number. */ - while( g_ascii_isdigit( *fmt ) ) - len = len * 10 + ( *(fmt++) - '0' ); - } - else if( g_strncasecmp( fmt, "nick", 4 ) == 0 ) - { + while (g_ascii_isdigit(*fmt)) { + len = len * 10 + (*(fmt++) - '0'); + } + } else if (g_strncasecmp(fmt, "nick", 4) == 0) { part = bu->nick ? : bu->handle; fmt += 4; ok |= TRUE; break; - } - else if( g_strncasecmp( fmt, "handle", 6 ) == 0 ) - { + } else if (g_strncasecmp(fmt, "handle", 6) == 0) { part = bu->handle; fmt += 6; ok |= TRUE; break; - } - else if( g_strncasecmp( fmt, "full_name", 9 ) == 0 ) - { + } else if (g_strncasecmp(fmt, "full_name", 9) == 0) { part = bu->fullname; fmt += 9; ok |= part && *part; break; - } - else if( g_strncasecmp( fmt, "first_name", 10 ) == 0 ) - { + } else if (g_strncasecmp(fmt, "first_name", 10) == 0) { part = bu->fullname; fmt += 10; ok |= part && *part; chop = ' '; break; - } - else if( g_strncasecmp( fmt, "group", 5 ) == 0 ) - { + } else if (g_strncasecmp(fmt, "group", 5) == 0) { part = bu->group ? bu->group->name : NULL; fmt += 5; break; - } - else if( g_strncasecmp( fmt, "account", 7 ) == 0 ) - { + } else if (g_strncasecmp(fmt, "account", 7) == 0) { part = bu->ic->acc->tag; fmt += 7; break; - } - else - { - g_string_free( ret, TRUE ); + } else { + g_string_free(ret, TRUE); return NULL; } } - - if( !part ) + + if (!part) { continue; - + } + /* Credits to Josay_ in #bitlbee for this idea. //TRANSLIT should do lossy/approximate conversions, so letters with accents don't just get stripped. Note that it depends on LC_CTYPE being set to something other than C/POSIX. */ - if( !( irc && irc->status & IRC_UTF8_NICKS ) ) - part = asc = g_convert_with_fallback( part, -1, "ASCII//TRANSLIT", - "UTF-8", "", NULL, NULL, NULL ); - - if( part && chop && ( s = strchr( part, chop ) ) ) - len = MIN( len, s - part ); - - if( part ) - { - if( len < INT_MAX ) - g_string_append_len( ret, part, len ); - else - g_string_append( ret, part ); + if (!(irc && irc->status & IRC_UTF8_NICKS)) { + part = asc = g_convert_with_fallback(part, -1, "ASCII//TRANSLIT", + "UTF-8", "", NULL, NULL, NULL); + } + + if (part && chop && (s = strchr(part, chop))) { + len = MIN(len, s - part); + } + + if (part) { + if (len < INT_MAX) { + g_string_append_len(ret, part, len); + } else { + g_string_append(ret, part); + } } - g_free( asc ); + g_free(asc); } - - rets = g_string_free( ret, FALSE ); - if( ok && rets && *rets ) - { - nick_strip( irc, rets ); - truncate_utf8( rets, MAX_NICK_LENGTH ); + + rets = g_string_free(ret, FALSE); + if (ok && rets && *rets) { + nick_strip(irc, rets); + truncate_utf8(rets, MAX_NICK_LENGTH); return rets; } - g_free( rets ); + g_free(rets); return NULL; } -void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] ) +void nick_dedupe(bee_user_t *bu, char nick[MAX_NICK_LENGTH + 1]) { - irc_t *irc = (irc_t*) bu->bee->ui_data; + irc_t *irc = (irc_t *) bu->bee->ui_data; int inf_protection = 256; irc_user_t *iu; - + /* Now, find out if the nick is already in use at the moment, and make subtle changes to make it unique. */ - while( !nick_ok( irc, nick ) || - ( ( iu = irc_user_by_name( irc, nick ) ) && iu->bu != bu ) ) - { - if( strlen( nick ) < ( MAX_NICK_LENGTH - 1 ) ) - { - nick[strlen(nick)+1] = 0; + while (!nick_ok(irc, nick) || + ((iu = irc_user_by_name(irc, nick)) && iu->bu != bu)) { + if (strlen(nick) < (MAX_NICK_LENGTH - 1)) { + nick[strlen(nick) + 1] = 0; nick[strlen(nick)] = '_'; - } - else - { + } else { /* We've got no more space for underscores, so truncate it and replace the last three chars with a random "_XX" suffix */ - int len = truncate_utf8( nick, MAX_NICK_LENGTH - 3 ); + int len = truncate_utf8(nick, MAX_NICK_LENGTH - 3); nick[len] = '_'; - g_snprintf(nick + len + 1, 3, "%2x", rand() ); + g_snprintf(nick + len + 1, 3, "%2x", rand()); } - - if( inf_protection-- == 0 ) - { - g_snprintf( nick, MAX_NICK_LENGTH + 1, "xx%x", rand() ); - - irc_rootmsg( irc, "Warning: Something went wrong while trying " - "to generate a nickname for contact %s on %s.", - bu->handle, bu->ic->acc->tag ); - irc_rootmsg( irc, "This might be a bug in BitlBee, or the result " - "of a faulty nick_format setting. Will use %s " - "instead.", nick ); - + + if (inf_protection-- == 0) { + g_snprintf(nick, MAX_NICK_LENGTH + 1, "xx%x", rand()); + + irc_rootmsg(irc, "Warning: Something went wrong while trying " + "to generate a nickname for contact %s on %s.", + bu->handle, bu->ic->acc->tag); + irc_rootmsg(irc, "This might be a bug in BitlBee, or the result " + "of a faulty nick_format setting. Will use %s " + "instead.", nick); + break; } } @@ -277,158 +252,147 @@ void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] ) /* Just check if there is a nickname set for this buddy or if we'd have to generate one. */ -int nick_saved( bee_user_t *bu ) +int nick_saved(bee_user_t *bu) { char *store_handle, *found; - - store_handle = clean_handle( bu->handle ); - found = g_hash_table_lookup( bu->ic->acc->nicks, store_handle ); - g_free( store_handle ); - + + store_handle = clean_handle(bu->handle); + found = g_hash_table_lookup(bu->ic->acc->nicks, store_handle); + g_free(store_handle); + return found != NULL; } -void nick_del( bee_user_t *bu ) +void nick_del(bee_user_t *bu) { - g_hash_table_remove( bu->ic->acc->nicks, bu->handle ); + g_hash_table_remove(bu->ic->acc->nicks, bu->handle); } -void nick_strip( irc_t *irc, char *nick ) +void nick_strip(irc_t *irc, char *nick) { int len = 0; - - if( irc && ( irc->status & IRC_UTF8_NICKS ) ) - { + + if (irc && (irc->status & IRC_UTF8_NICKS)) { gunichar c; - char *p = nick, *n, tmp[strlen(nick)+1]; - - while( p && *p ) - { - c = g_utf8_get_char_validated( p, -1 ); - n = g_utf8_find_next_char( p, NULL ); - - if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || - strchr( nick_uc_chars, c ) ) ) || - !g_unichar_isgraph( c ) ) - { - strcpy( tmp, n ); - strcpy( p, tmp ); - } - else + char *p = nick, *n, tmp[strlen(nick) + 1]; + + while (p && *p) { + c = g_utf8_get_char_validated(p, -1); + n = g_utf8_find_next_char(p, NULL); + + if ((c < 0x7f && !(strchr(nick_lc_chars, c) || + strchr(nick_uc_chars, c))) || + !g_unichar_isgraph(c)) { + strcpy(tmp, n); + strcpy(p, tmp); + } else { p = n; + } } - if( p ) + if (p) { len = p - nick; - } - else - { + } + } else { int i; - - for( i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++ ) - { - if( strchr( nick_lc_chars, nick[i] ) || - strchr( nick_uc_chars, nick[i] ) ) - { + + for (i = len = 0; nick[i] && len < MAX_NICK_LENGTH; i++) { + if (strchr(nick_lc_chars, nick[i]) || + strchr(nick_uc_chars, nick[i])) { nick[len] = nick[i]; len++; } } } - if( g_ascii_isdigit( nick[0] ) ) - { + if (g_ascii_isdigit(nick[0])) { char *orig; - + /* First character of a nick can't be a digit, so insert an underscore if necessary. */ - orig = g_strdup( nick ); - g_snprintf( nick, MAX_NICK_LENGTH, "_%s", orig ); - g_free( orig ); - len ++; + orig = g_strdup(nick); + g_snprintf(nick, MAX_NICK_LENGTH, "_%s", orig); + g_free(orig); + len++; } - while( len <= MAX_NICK_LENGTH ) + while (len <= MAX_NICK_LENGTH) { nick[len++] = '\0'; + } } -gboolean nick_ok( irc_t *irc, const char *nick ) +gboolean nick_ok(irc_t *irc, const char *nick) { const char *s; - + /* Empty/long nicks are not allowed, nor numbers at [0] */ - if( !*nick || g_ascii_isdigit( nick[0] ) || strlen( nick ) > MAX_NICK_LENGTH ) + if (!*nick || g_ascii_isdigit(nick[0]) || strlen(nick) > MAX_NICK_LENGTH) { return 0; - - if( irc && ( irc->status & IRC_UTF8_NICKS ) ) - { + } + + if (irc && (irc->status & IRC_UTF8_NICKS)) { gunichar c; const char *p = nick, *n; - - while( p && *p ) - { - c = g_utf8_get_char_validated( p, -1 ); - n = g_utf8_find_next_char( p, NULL ); - - if( ( c < 0x7f && !( strchr( nick_lc_chars, c ) || - strchr( nick_uc_chars, c ) ) ) || - !g_unichar_isgraph( c ) ) - { + + while (p && *p) { + c = g_utf8_get_char_validated(p, -1); + n = g_utf8_find_next_char(p, NULL); + + if ((c < 0x7f && !(strchr(nick_lc_chars, c) || + strchr(nick_uc_chars, c))) || + !g_unichar_isgraph(c)) { return FALSE; } p = n; } - } - else - { - for( s = nick; *s; s ++ ) - if( !strchr( nick_lc_chars, *s ) && !strchr( nick_uc_chars, *s ) ) + } else { + for (s = nick; *s; s++) { + if (!strchr(nick_lc_chars, *s) && !strchr(nick_uc_chars, *s)) { return FALSE; + } + } } - + return TRUE; } -int nick_lc( irc_t *irc, char *nick ) +int nick_lc(irc_t *irc, char *nick) { static char tab[128] = { 0 }; int i; - - if( tab['A'] == 0 ) - for( i = 0; nick_lc_chars[i]; i ++ ) - { - tab[(int)nick_uc_chars[i]] = nick_lc_chars[i]; - tab[(int)nick_lc_chars[i]] = nick_lc_chars[i]; + + if (tab['A'] == 0) { + for (i = 0; nick_lc_chars[i]; i++) { + tab[(int) nick_uc_chars[i]] = nick_lc_chars[i]; + tab[(int) nick_lc_chars[i]] = nick_lc_chars[i]; } - - if( irc && ( irc->status & IRC_UTF8_NICKS ) ) - { - gchar *down = g_utf8_strdown( nick, -1 ); - if( strlen( down ) > strlen( nick ) ) - { - truncate_utf8( down, strlen( nick ) ); + } + + if (irc && (irc->status & IRC_UTF8_NICKS)) { + gchar *down = g_utf8_strdown(nick, -1); + if (strlen(down) > strlen(nick)) { + truncate_utf8(down, strlen(nick)); } - strcpy( nick, down ); - g_free( down ); + strcpy(nick, down); + g_free(down); } - - for( i = 0; nick[i]; i ++ ) - if( ((guchar)nick[i]) < 0x7f ) - nick[i] = tab[(guchar)nick[i]]; - - return nick_ok( irc, nick ); + + for (i = 0; nick[i]; i++) { + if (((guchar) nick[i]) < 0x7f) { + nick[i] = tab[(guchar) nick[i]]; + } + } + + return nick_ok(irc, nick); } -int nick_cmp( irc_t *irc, const char *a, const char *b ) +int nick_cmp(irc_t *irc, const char *a, const char *b) { char aa[1024] = "", bb[1024] = ""; - - strncpy( aa, a, sizeof( aa ) - 1 ); - strncpy( bb, b, sizeof( bb ) - 1 ); - if( nick_lc( irc, aa ) && nick_lc( irc, bb ) ) - { - return( strcmp( aa, bb ) ); - } - else - { - return( -1 ); /* Hmm... Not a clear answer.. :-/ */ + + strncpy(aa, a, sizeof(aa) - 1); + strncpy(bb, b, sizeof(bb) - 1); + if (nick_lc(irc, aa) && nick_lc(irc, bb)) { + return(strcmp(aa, bb)); + } else { + return(-1); /* Hmm... Not a clear answer.. :-/ */ } } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -23,17 +23,17 @@ Fifth Floor, Boston, MA 02110-1301 USA */ -void nick_set_raw( account_t *acc, const char *handle, const char *nick ); -void nick_set( bee_user_t *bu, const char *nick ); -char *nick_get( bee_user_t *bu ); -char *nick_gen( bee_user_t *bu ); -void nick_dedupe( bee_user_t *bu, char nick[MAX_NICK_LENGTH+1] ); -int nick_saved( bee_user_t *bu ); -void nick_del( bee_user_t *bu ); +void nick_set_raw(account_t *acc, const char *handle, const char *nick); +void nick_set(bee_user_t *bu, const char *nick); +char *nick_get(bee_user_t *bu); +char *nick_gen(bee_user_t *bu); +void nick_dedupe(bee_user_t * bu, char nick[MAX_NICK_LENGTH + 1]); +int nick_saved(bee_user_t *bu); +void nick_del(bee_user_t *bu); -void nick_strip( irc_t *irc, char *nick ); -gboolean nick_ok( irc_t *irc, const char *nick ); -int nick_lc( irc_t *irc, char *nick ); -int nick_uc( irc_t *irc, char *nick ); -int nick_cmp( irc_t *irc, const char *a, const char *b ); -char *nick_dup( const char *nick ); +void nick_strip(irc_t *irc, char *nick); +gboolean nick_ok(irc_t *irc, const char *nick); +int nick_lc(irc_t *irc, char *nick); +int nick_uc(irc_t *irc, char *nick); +int nick_cmp(irc_t *irc, const char *a, const char *b); +char *nick_dup(const char *nick); @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -6,15 +6,15 @@ /* OTR support (cf. http://www.cypherpunks.ca/otr/) - + (c) 2008-2011,2013 Sven Moritz Hallberg <pesco@khjk.org> funded by stonedcoder.org - + files used to store OTR data: <configdir>/<nick>.otr_keys <configdir>/<nick>.otr_fprints <configdir>/<nick>.otr_instags <- don't copy this one between hosts - + top-level todos: (search for TODO for more ;-)) integrate otr_load/otr_save with existing storage backends per-account policy settings @@ -56,13 +56,13 @@ OtrlPolicy op_policy(void *opdata, ConnContext *context); void op_create_privkey(void *opdata, const char *accountname, const char *protocol); int op_is_logged_in(void *opdata, const char *accountname, const char *protocol, - const char *recipient); + const char *recipient); void op_inject_message(void *opdata, const char *accountname, const char *protocol, - const char *recipient, const char *message); + const char *recipient, const char *message); void op_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, - const char *protocol, const char *username, unsigned char fingerprint[20]); + const char *protocol, const char *username, unsigned char fingerprint[20]); void op_write_fingerprints(void *opdata); @@ -81,17 +81,17 @@ const char *op_account_name(void *opdata, const char *account, const char *proto void op_create_instag(void *opdata, const char *account, const char *protocol); void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, - char **dst, const char *src); + char **dst, const char *src); void op_convert_free(void *opdata, ConnContext *ctx, char *msg); void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, - unsigned short percent, char *question); + unsigned short percent, char *question); void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, - const char *message, gcry_error_t err); + const char *message, gcry_error_t err); const char *op_otr_error_message(void *opdata, ConnContext *ctx, - OtrlErrorCode err_code); + OtrlErrorCode err_code); /** otr sub-command handlers: **/ @@ -122,7 +122,7 @@ const command_t otr_commands[] = { typedef struct { void *fst; void *snd; -} pair_t; +} pair_t; static OtrlMessageAppOps otr_ops; /* collects interface functions required by OTR */ @@ -158,7 +158,7 @@ gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond); /* helper to make sure accountname and protocol match the incoming "opdata" */ struct im_connection *check_imc(void *opdata, const char *accountname, - const char *protocol); + const char *protocol); /* determine the nick for a given handle/protocol pair returns "handle/protocol" if not found */ @@ -179,7 +179,7 @@ void log_otr_message(void *opdata, const char *fmt, ...); /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, - const char *secret); + const char *secret); /* update flags within the irc_user structure to reflect OTR status of context */ void otr_update_uflags(ConnContext *context, irc_user_t *u); @@ -225,7 +225,7 @@ static const struct irc_plugin otr_plugin; void init_plugin(void) { OTRL_INIT; - + /* fill global OtrlMessageAppOps */ otr_ops.policy = &op_policy; otr_ops.create_privkey = &op_create_privkey; @@ -252,31 +252,31 @@ void init_plugin(void) otr_ops.create_instag = &op_create_instag; otr_ops.convert_msg = &op_convert_msg; otr_ops.convert_free = &op_convert_free; - otr_ops.timer_control = NULL; /* we just poll */ - - root_command_add( "otr", 1, cmd_otr, 0 ); - register_irc_plugin( &otr_plugin ); + otr_ops.timer_control = NULL; /* we just poll */ + + root_command_add("otr", 1, cmd_otr, 0); + register_irc_plugin(&otr_plugin); } gboolean otr_irc_new(irc_t *irc) { set_t *s; GSList *l; - + irc->otr = g_new0(otr_t, 1); irc->otr->us = otrl_userstate_create(); - - s = set_add( &irc->b->set, "otr_color_encrypted", "true", set_eval_bool, irc ); - - s = set_add( &irc->b->set, "otr_policy", "opportunistic", 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 = set_add(&irc->b->set, "otr_color_encrypted", "true", set_eval_bool, irc); + + s = set_add(&irc->b->set, "otr_policy", "opportunistic", 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; - s = set_add( &irc->b->set, "otr_does_html", "true", set_eval_bool, irc ); - + s = set_add(&irc->b->set, "otr_does_html", "true", set_eval_bool, irc); + /* regularly call otrl_message_poll */ gint definterval = otrl_message_poll_get_default_interval(irc->otr->us); irc->otr->timer = b_timeout_add(definterval, ev_message_poll, irc->otr); @@ -287,19 +287,22 @@ gboolean otr_irc_new(irc_t *irc) void otr_irc_free(irc_t *irc) { otr_t *otr = irc->otr; + otr_disconnect_all(irc); b_event_remove(otr->timer); otrl_userstate_free(otr->us); - if(otr->keygen) { + if (otr->keygen) { kill(otr->keygen, SIGTERM); waitpid(otr->keygen, NULL, 0); /* TODO: remove stale keygen tempfiles */ } - if(otr->to) + if (otr->to) { fclose(otr->to); - if(otr->from) + } + if (otr->from) { fclose(otr->from); - while(otr->todo) { + } + while (otr->todo) { kg_t *p = otr->todo; otr->todo = p->next; g_free(p); @@ -313,38 +316,38 @@ void otr_load(irc_t *irc) account_t *a; gcry_error_t e; gcry_error_t enoent = gcry_error_from_errno(ENOENT); - int kg=0; + int kg = 0; - if(strsane(irc->user->nick)) { + if (strsane(irc->user->nick)) { g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->user->nick); e = otrl_privkey_read(irc->otr->us, s); - if(e && e!=enoent) { + if (e && e != enoent) { irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); } g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); - if(e && e!=enoent) { + if (e && e != enoent) { irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); } g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, irc->user->nick); e = otrl_instag_read(irc->otr->us, s); - if(e && e!=enoent) { + if (e && e != enoent) { irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); } } - + /* check for otr keys on all accounts */ - for(a=irc->b->accounts; a; a=a->next) { + for (a = irc->b->accounts; a; a = a->next) { kg = otr_check_for_key(a) || kg; } - if(kg) { + if (kg) { irc_rootmsg(irc, "Notice: " - "The accounts above do not have OTR encryption keys associated with them, yet. " - "These keys are now being generated in the background. " - "You will be notified as they are completed. " - "It is not necessary to wait; " - "BitlBee can be used normally during key generation. " - "You may safely ignore this message if you don't know what OTR is. ;)"); + "The accounts above do not have OTR encryption keys associated with them, yet. " + "These keys are now being generated in the background. " + "You will be notified as they are completed. " + "It is not necessary to wait; " + "BitlBee can be used normally during key generation. " + "You may safely ignore this message if you don't know what OTR is. ;)"); } } @@ -353,10 +356,10 @@ void otr_save(irc_t *irc) char s[512]; gcry_error_t e; - if(strsane(irc->user->nick)) { + if (strsane(irc->user->nick)) { g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); e = otrl_privkey_write_fingerprints(irc->otr->us, s); - if(e) { + if (e) { irc_rootmsg(irc, "otr save: %s: %s", s, gcry_strerror(e)); } chmod(s, 0600); @@ -366,8 +369,8 @@ void otr_save(irc_t *irc) void otr_remove(const char *nick) { char s[512]; - - if(strsane(nick)) { + + if (strsane(nick)) { g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, nick); unlink(s); g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, nick); @@ -378,14 +381,14 @@ void otr_remove(const char *nick) void otr_rename(const char *onick, const char *nnick) { char s[512], t[512]; - - if(strsane(nnick) && strsane(onick)) { + + if (strsane(nnick) && strsane(onick)) { g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, onick); g_snprintf(t, 511, "%s%s.otr_keys", global.conf->configdir, nnick); - rename(s,t); + rename(s, t); g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, onick); g_snprintf(t, 511, "%s%s.otr_fprints", global.conf->configdir, nnick); - rename(s,t); + rename(s, t); } } @@ -393,17 +396,18 @@ int otr_check_for_key(account_t *a) { irc_t *irc = a->bee->ui_data; OtrlPrivKey *k; - + /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ - if(a->prpl->options & OPT_NOOTR) { + if (a->prpl->options & OPT_NOOTR) { return 0; } - + k = otrl_privkey_find(irc->otr->us, a->user, a->prpl->name); - if(k) { + if (k) { irc_rootmsg(irc, "otr: %s/%s ready", a->user, a->prpl->name); return 0; - } if(keygen_in_progress(irc, a->user, a->prpl->name)) { + } + if (keygen_in_progress(irc, a->user, a->prpl->name)) { irc_rootmsg(irc, "otr: keygen for %s/%s already in progress", a->user, a->prpl->name); return 0; } else { @@ -420,20 +424,20 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) OtrlTLV *tlvs = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; - + /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ - if(ic->acc->prpl->options & OPT_NOOTR) { + if (ic->acc->prpl->options & OPT_NOOTR) { return msg; } - + ignore_msg = otrl_message_receiving(irc->otr->us, &otr_ops, ic, - ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg, - &tlvs, NULL, NULL, NULL); + ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg, + &tlvs, NULL, NULL, NULL); - if(ignore_msg) { + if (ignore_msg) { /* this was an internal OTR protocol message */ return NULL; - } else if(!newmsg) { + } else if (!newmsg) { /* this was a non-OTR message */ return msg; } else { @@ -443,36 +447,37 @@ char *otr_filter_msg_in(irc_user_t *iu, char *msg, int flags) } char *otr_filter_msg_out(irc_user_t *iu, char *msg, int flags) -{ +{ int st; char *otrmsg = NULL; ConnContext *ctx = NULL; irc_t *irc = iu->irc; struct im_connection *ic = iu->bu->ic; otrl_instag_t instag = OTRL_INSTAG_BEST; // XXX? + /* NB: in libotr 4.0.0 OTRL_INSTAG_RECENT will cause a null-pointer deref * in otrl_message_sending with newly-added OTR contexts. */ /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ - if(ic->acc->prpl->options & OPT_NOOTR) { + if (ic->acc->prpl->options & OPT_NOOTR) { return msg; } st = otrl_message_sending(irc->otr->us, &otr_ops, ic, - ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, - msg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &ctx, NULL, NULL); + ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, + msg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL_BUT_LAST, &ctx, NULL, NULL); - if(otrmsg && otrmsg != msg) { + if (otrmsg && otrmsg != msg) { /* libotr wants us to replace our message */ /* NB: caller will free old msg */ msg = g_strdup(otrmsg); otrl_message_free(otrmsg); } - - if(st) { + + if (st) { irc_usernotice(iu, "otr: error handling outgoing message: %d", st); - msg = NULL; /* do not send plaintext! */ + msg = NULL; /* do not send plaintext! */ } return msg; @@ -492,31 +497,34 @@ static const struct irc_plugin otr_plugin = static void cmd_otr(irc_t *irc, char **args) { const command_t *cmd; - - if(!args[0]) + + if (!args[0]) { return; - - if(!args[1]) + } + + if (!args[1]) { return; - - for(cmd=otr_commands; cmd->command; cmd++) { - if(strcmp(cmd->command, args[1]) == 0) + } + + for (cmd = otr_commands; cmd->command; cmd++) { + if (strcmp(cmd->command, args[1]) == 0) { break; + } } - - if(!cmd->command) { + + if (!cmd->command) { irc_rootmsg(irc, "%s: unknown subcommand \"%s\", see \x02help otr\x02", - args[0], args[1]); + args[0], args[1]); return; } - - if(!args[cmd->required_parameters+1]) { + + if (!args[cmd->required_parameters + 1]) { irc_rootmsg(irc, "%s %s: not enough arguments (%d req.)", - args[0], args[1], cmd->required_parameters); + args[0], args[1], cmd->required_parameters); return; } - - cmd->execute(irc, args+1); + + cmd->execute(irc, args + 1); } @@ -527,56 +535,62 @@ OtrlPolicy op_policy(void *opdata, ConnContext *context) struct im_connection *ic = check_imc(opdata, context->accountname, context->protocol); irc_t *irc = ic->bee->ui_data; const char *p; - + /* policy override during keygen: if we're missing the key for context but are currently generating it, then that's as much as we can do. => temporarily return NEVER. */ - if(keygen_in_progress(irc, context->accountname, context->protocol) && - !otrl_privkey_find(irc->otr->us, context->accountname, context->protocol)) + if (keygen_in_progress(irc, context->accountname, context->protocol) && + !otrl_privkey_find(irc->otr->us, context->accountname, context->protocol)) { return OTRL_POLICY_NEVER; + } p = set_getstr(&ic->bee->set, "otr_policy"); - if(!strcmp(p, "never")) + if (!strcmp(p, "never")) { return OTRL_POLICY_NEVER; - if(!strcmp(p, "opportunistic")) + } + if (!strcmp(p, "opportunistic")) { return OTRL_POLICY_OPPORTUNISTIC; - if(!strcmp(p, "manual")) + } + if (!strcmp(p, "manual")) { return OTRL_POLICY_MANUAL; - if(!strcmp(p, "always")) + } + if (!strcmp(p, "always")) { return OTRL_POLICY_ALWAYS; - + } + return OTRL_POLICY_OPPORTUNISTIC; } void op_create_privkey(void *opdata, const char *accountname, - const char *protocol) + const char *protocol) { struct im_connection *ic = check_imc(opdata, accountname, protocol); irc_t *irc = ic->bee->ui_data; - + /* will fail silently if keygen already in progress */ otr_keygen(irc, accountname, protocol); } int op_is_logged_in(void *opdata, const char *accountname, - const char *protocol, const char *recipient) + const char *protocol, const char *recipient) { struct im_connection *ic = check_imc(opdata, accountname, protocol); bee_user_t *bu; /* lookup the irc_user_t for the given recipient */ bu = bee_user_by_handle(ic->bee, ic, recipient); - if(bu) { - if(bu->flags & BEE_USER_ONLINE) + if (bu) { + if (bu->flags & BEE_USER_ONLINE) { return 1; - else + } else { return 0; + } } else { return -1; } } void op_inject_message(void *opdata, const char *accountname, - const char *protocol, const char *recipient, const char *message) + const char *protocol, const char *recipient, const char *message) { struct im_connection *ic = check_imc(opdata, accountname, protocol); irc_t *irc = ic->bee->ui_data; @@ -587,33 +601,33 @@ void op_inject_message(void *opdata, const char *accountname, } else { /* need to drop some consts here :-( */ /* TODO: get flags into op_inject_message?! */ - ic->acc->prpl->buddy_msg(ic, (char *)recipient, (char *)message, 0); + ic->acc->prpl->buddy_msg(ic, (char *) recipient, (char *) message, 0); /* ignoring return value :-/ */ } } void op_new_fingerprint(void *opdata, OtrlUserState us, - const char *accountname, const char *protocol, - const char *username, unsigned char fingerprint[20]) + const char *accountname, const char *protocol, + const char *username, unsigned char fingerprint[20]) { struct im_connection *ic = check_imc(opdata, accountname, protocol); irc_t *irc = ic->bee->ui_data; irc_user_t *u = peeruser(irc, username, protocol); - char hunam[45]; /* anybody looking? ;-) */ - + char hunam[45]; /* anybody looking? ;-) */ + otrl_privkey_hash_to_human(hunam, fingerprint); - if(u) { + if (u) { irc_usernotice(u, "new fingerprint: %s", hunam); } else { /* this case shouldn't normally happen */ irc_rootmsg(irc, "new fingerprint for %s/%s: %s", - username, protocol, hunam); + username, protocol, hunam); } } void op_write_fingerprints(void *opdata) { - struct im_connection *ic = (struct im_connection *)opdata; + struct im_connection *ic = (struct im_connection *) opdata; irc_t *irc = ic->bee->ui_data; otr_save(irc); @@ -622,20 +636,20 @@ void op_write_fingerprints(void *opdata) void op_gone_secure(void *opdata, ConnContext *context) { struct im_connection *ic = - check_imc(opdata, context->accountname, context->protocol); + check_imc(opdata, context->accountname, context->protocol); irc_user_t *u; irc_t *irc = ic->bee->ui_data; u = peeruser(irc, context->username, context->protocol); - if(!u) { + if (!u) { log_message(LOGLVL_ERROR, - "BUG: otr.c: op_gone_secure: irc_user_t for %s/%s/%s not found!", - context->username, context->protocol, context->accountname); + "BUG: otr.c: op_gone_secure: irc_user_t for %s/%s/%s not found!", + context->username, context->protocol, context->accountname); return; } - + otr_update_uflags(context, u); - if(!otr_update_modeflags(irc, u)) { + if (!otr_update_modeflags(irc, u)) { char *trust = u->flags & IRC_USER_OTR_TRUSTED ? "trusted" : "untrusted!"; irc_usernotice(u, "conversation is now off the record (%s)", trust); } @@ -644,39 +658,40 @@ void op_gone_secure(void *opdata, ConnContext *context) void op_gone_insecure(void *opdata, ConnContext *context) { struct im_connection *ic = - check_imc(opdata, context->accountname, context->protocol); + check_imc(opdata, context->accountname, context->protocol); irc_t *irc = ic->bee->ui_data; irc_user_t *u; u = peeruser(irc, context->username, context->protocol); - if(!u) { + if (!u) { log_message(LOGLVL_ERROR, - "BUG: otr.c: op_gone_insecure: irc_user_t for %s/%s/%s not found!", - context->username, context->protocol, context->accountname); + "BUG: otr.c: op_gone_insecure: irc_user_t for %s/%s/%s not found!", + context->username, context->protocol, context->accountname); return; } otr_update_uflags(context, u); - if(!otr_update_modeflags(irc, u)) + if (!otr_update_modeflags(irc, u)) { irc_usernotice(u, "conversation is now in cleartext"); + } } void op_still_secure(void *opdata, ConnContext *context, int is_reply) { struct im_connection *ic = - check_imc(opdata, context->accountname, context->protocol); + check_imc(opdata, context->accountname, context->protocol); irc_t *irc = ic->bee->ui_data; irc_user_t *u; u = peeruser(irc, context->username, context->protocol); - if(!u) { + if (!u) { log_message(LOGLVL_ERROR, - "BUG: otr.c: op_still_secure: irc_user_t for %s/%s/%s not found!", - context->username, context->protocol, context->accountname); + "BUG: otr.c: op_still_secure: irc_user_t for %s/%s/%s not found!", + context->username, context->protocol, context->accountname); return; } otr_update_uflags(context, u); - if(!otr_update_modeflags(irc, u)) { + if (!otr_update_modeflags(irc, u)) { char *trust = u->flags & IRC_USER_OTR_TRUSTED ? "trusted" : "untrusted!"; irc_usernotice(u, "otr connection has been refreshed (%s)", trust); } @@ -685,14 +700,14 @@ void op_still_secure(void *opdata, ConnContext *context, int is_reply) int op_max_message_size(void *opdata, ConnContext *context) { struct im_connection *ic = - check_imc(opdata, context->accountname, context->protocol); - + 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) { - struct im_connection *ic = (struct im_connection *)opdata; + struct im_connection *ic = (struct im_connection *) opdata; irc_t *irc = ic->bee->ui_data; return peernick(irc, account, protocol); @@ -701,74 +716,75 @@ const char *op_account_name(void *opdata, const char *account, const char *proto void op_create_instag(void *opdata, const char *account, const char *protocol) { struct im_connection *ic = - check_imc(opdata, account, protocol); + check_imc(opdata, account, protocol); irc_t *irc = ic->bee->ui_data; gcry_error_t e; char s[512]; - + g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, - irc->user->nick); + irc->user->nick); e = otrl_instag_generate(irc->otr->us, s, account, protocol); - if(e) { + if (e) { irc_rootmsg(irc, "otr: %s/%s: otrl_instag_generate failed: %s", - account, protocol, gcry_strerror(e)); + account, protocol, gcry_strerror(e)); } } void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, - char **dst, const char *src) + char **dst, const char *src) { struct im_connection *ic = - check_imc(opdata, ctx->accountname, ctx->protocol); + check_imc(opdata, ctx->accountname, ctx->protocol); irc_t *irc = ic->bee->ui_data; irc_user_t *iu = peeruser(irc, ctx->username, ctx->protocol); - if(typ == OTRL_CONVERT_RECEIVING) { + if (typ == OTRL_CONVERT_RECEIVING) { char *msg = g_strdup(src); char *buf = msg; /* HTML decoding */ - if(set_getbool(&ic->bee->set, "otr_does_html") && - !(ic->flags & OPT_DOES_HTML) && - set_getbool(&ic->bee->set, "strip_html")) { + if (set_getbool(&ic->bee->set, "otr_does_html") && + !(ic->flags & OPT_DOES_HTML) && + set_getbool(&ic->bee->set, "strip_html")) { strip_html(msg); *dst = msg; } /* coloring */ - if(set_getbool(&ic->bee->set, "otr_color_encrypted")) { + if (set_getbool(&ic->bee->set, "otr_color_encrypted")) { int color; /* color according to f'print trust */ - char *pre="", *sep=""; /* optional parts */ + char *pre = "", *sep = ""; /* optional parts */ const char *trust = ctx->active_fingerprint->trust; - if(trust && trust[0] != '\0') - color=3; /* green */ - else - color=5; /* red */ + if (trust && trust[0] != '\0') { + color = 3; /* green */ + } else { + color = 5; /* red */ + } /* in a query window, keep "/me " uncolored at the beginning */ - if(g_strncasecmp(msg, "/me ", 4) == 0 - && irc_user_msgdest(iu) == irc->user->nick) { + if (g_strncasecmp(msg, "/me ", 4) == 0 + && irc_user_msgdest(iu) == irc->user->nick) { msg += 4; /* skip */ pre = "/me "; } /* comma in first place could mess with the color code */ - if(msg[0] == ',') { - /* insert a space between color spec and message */ - sep = " "; + if (msg[0] == ',') { + /* insert a space between color spec and message */ + sep = " "; } *dst = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, - color, sep, msg); + color, sep, msg); g_free(buf); } } else { /* HTML encoding */ /* consider OTR plaintext to be HTML if otr_does_html is set */ - if(ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED && - set_getbool(&ic->bee->set, "otr_does_html") && - (g_strncasecmp(src, "<html>", 6) != 0)) { + if (ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED && + set_getbool(&ic->bee->set, "otr_does_html") && + (g_strncasecmp(src, "<html>", 6) != 0)) { *dst = escape_html(src); } } @@ -778,34 +794,36 @@ void op_convert_free(void *opdata, ConnContext *ctx, char *msg) { g_free(msg); } - + /* Socialist Millionaires' Protocol */ void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, - unsigned short percent, char *question) + unsigned short percent, char *question) { struct im_connection *ic = - check_imc(opdata, ctx->accountname, ctx->protocol); + check_imc(opdata, ctx->accountname, ctx->protocol); irc_t *irc = ic->bee->ui_data; OtrlUserState us = irc->otr->us; irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); - if(!u) return; + if (!u) { + return; + } - switch(ev) { + switch (ev) { case OTRL_SMPEVENT_ASK_FOR_SECRET: irc_rootmsg(irc, "smp: initiated by %s" - " - respond with \x02otr smp %s <secret>\x02", - u->nick, u->nick); + " - respond with \x02otr smp %s <secret>\x02", + u->nick, u->nick); break; case OTRL_SMPEVENT_ASK_FOR_ANSWER: irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, - question); + question); irc_rootmsg(irc, "smp: respond with \x02otr smp %s <answer>\x02", - u->nick); + u->nick); break; case OTRL_SMPEVENT_CHEATED: irc_rootmsg(irc, "smp %s: opponent violated protocol, aborting", - u->nick); + u->nick); otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); otrl_sm_state_free(ctx->smstate); break; @@ -814,32 +832,32 @@ void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, case OTRL_SMPEVENT_IN_PROGRESS: break; case OTRL_SMPEVENT_SUCCESS: - if(ctx->smstate->received_question) { + if (ctx->smstate->received_question) { irc_rootmsg(irc, "smp %s: correct answer, you are trusted", - u->nick); + u->nick); } else { irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", - u->nick); + u->nick); } otrl_sm_state_free(ctx->smstate); break; case OTRL_SMPEVENT_FAILURE: - if(ctx->smstate->received_question) { + if (ctx->smstate->received_question) { irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", - u->nick); + u->nick); } else { irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", - u->nick); + u->nick); } otrl_sm_state_free(ctx->smstate); break; case OTRL_SMPEVENT_ABORT: - irc_rootmsg(irc, "smp: received abort from %s", u->nick); + irc_rootmsg(irc, "smp: received abort from %s", u->nick); otrl_sm_state_free(ctx->smstate); break; case OTRL_SMPEVENT_ERROR: irc_rootmsg(irc, "smp %s: protocol error, aborting", - u->nick); + u->nick); otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); otrl_sm_state_free(ctx->smstate); break; @@ -847,73 +865,73 @@ void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, } void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, - const char *message, gcry_error_t err) + const char *message, gcry_error_t err) { - switch(ev) { + switch (ev) { case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: display_otr_message(opdata, ctx, - "policy requires encryption - message not sent"); + "policy requires encryption - message not sent"); break; case OTRL_MSGEVENT_ENCRYPTION_ERROR: display_otr_message(opdata, ctx, - "error during encryption - message not sent"); + "error during encryption - message not sent"); break; case OTRL_MSGEVENT_CONNECTION_ENDED: display_otr_message(opdata, ctx, - "other end has disconnected OTR - " - "close connection or reconnect!"); + "other end has disconnected OTR - " + "close connection or reconnect!"); break; case OTRL_MSGEVENT_SETUP_ERROR: display_otr_message(opdata, ctx, - "OTR connection failed: %s", gcry_strerror(err)); + "OTR connection failed: %s", gcry_strerror(err)); break; case OTRL_MSGEVENT_MSG_REFLECTED: display_otr_message(opdata, ctx, - "received our own OTR message (!?)"); + "received our own OTR message (!?)"); break; case OTRL_MSGEVENT_MSG_RESENT: display_otr_message(opdata, ctx, - "the previous message was resent"); + "the previous message was resent"); break; case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: display_otr_message(opdata, ctx, - "unexpected encrypted message received"); + "unexpected encrypted message received"); break; case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: display_otr_message(opdata, ctx, - "unreadable encrypted message received"); + "unreadable encrypted message received"); break; case OTRL_MSGEVENT_RCVDMSG_MALFORMED: display_otr_message(opdata, ctx, - "malformed OTR message received"); + "malformed OTR message received"); break; case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: - if(global.conf->verbose) { + if (global.conf->verbose) { log_otr_message(opdata, "%s/%s: heartbeat received", - ctx->accountname, ctx->protocol); + ctx->accountname, ctx->protocol); } break; case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: - if(global.conf->verbose) { + if (global.conf->verbose) { log_otr_message(opdata, "%s/%s: heartbeat sent", - ctx->accountname, ctx->protocol); + ctx->accountname, ctx->protocol); } break; case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: display_otr_message(opdata, ctx, - "OTR error message received: %s", message); + "OTR error message received: %s", message); break; case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED: display_otr_message(opdata, ctx, - "unencrypted message received: %s", message); + "unencrypted message received: %s", message); break; case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: display_otr_message(opdata, ctx, - "unrecognized OTR message received"); + "unrecognized OTR message received"); break; case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: display_otr_message(opdata, ctx, - "OTR message for a different instance received"); + "OTR message for a different instance received"); break; default: /* shouldn't happen */ @@ -922,9 +940,9 @@ void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, } const char *op_otr_error_message(void *opdata, ConnContext *ctx, - OtrlErrorCode err_code) + OtrlErrorCode err_code) { - switch(err_code) { + switch (err_code) { case OTRL_ERRCODE_ENCRYPTION_ERROR: return "i failed to encrypt a message"; case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE: @@ -952,15 +970,16 @@ void cmd_otr_disconnect(irc_t *irc, char **args) { irc_user_t *u; - if(!strcmp("*", args[1])) { + if (!strcmp("*", args[1])) { otr_disconnect_all(irc); irc_rootmsg(irc, "all conversations are now in cleartext"); } else { u = irc_user_by_name(irc, args[1]); - if(otr_disconnect_user(irc, u)) + if (otr_disconnect_user(irc, u)) { irc_usernotice(u, "conversation is now in cleartext"); - else + } else { irc_rootmsg(irc, "%s: unknown user", args[1]); + } } } @@ -970,32 +989,33 @@ void cmd_otr_connect(irc_t *irc, char **args) char *msg, *query = "?OTR?"; u = irc_user_by_name(irc, args[1]); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", args[1]); return; } - if(!(u->bu->flags & BEE_USER_ONLINE)) { + if (!(u->bu->flags & BEE_USER_ONLINE)) { irc_rootmsg(irc, "%s is offline", args[1]); return; } - + /* passing this through the filter so it goes through libotr which * will replace the simple query string with a proper one */ msg = otr_filter_msg_out(u, query, 0); /* send the message */ - if(msg) { + if (msg) { u->bu->ic->acc->prpl->buddy_msg(u->bu->ic, u->bu->handle, msg, 0); /* XXX flags? */ /* XXX error message? */ - if(msg != query) + if (msg != query) { g_free(msg); + } } } void cmd_otr_smp(irc_t *irc, char **args) { - otr_smp_or_smpq(irc, args[1], NULL, args[2]); /* no question */ + otr_smp_or_smpq(irc, args[1], NULL, args[2]); /* no question */ } void cmd_otr_smpq(irc_t *irc, char **args) @@ -1009,105 +1029,108 @@ void cmd_otr_trust(irc_t *irc, char **args) ConnContext *ctx; unsigned char raw[20]; Fingerprint *fp; - int i,j; - + int i, j; + u = irc_user_by_name(irc, args[1]); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", args[1]); return; } - + ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - if(!ctx) { + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, + NULL); + if (!ctx) { irc_rootmsg(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; + 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_rootmsg(irc, "failed: truncated fingerprint block %d", i+1); + + if (!*p || !*q) { + irc_rootmsg(irc, "failed: truncated fingerprint block %d", i + 1); return; } - + x = hexval(*p); y = hexval(*q); - if(x<0) { - irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+1, i+1); + if (x < 0) { + irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2 * j + 1, i + 1); return; } - if(y<0) { - irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2*j+2, i+1); + if (y < 0) { + irc_rootmsg(irc, "failed: %d. hex digit of block %d out of range", 2 * j + 2, i + 1); return; } - raw[i*4+j] = x*16 + y; + raw[i * 4 + j] = x * 16 + y; } } fp = otrl_context_find_fingerprint(ctx, raw, 0, NULL); - if(!fp) { + if (!fp) { irc_rootmsg(irc, "failed: no such fingerprint for %s", args[1]); } else { char *trust = args[7] ? args[7] : "affirmed"; otrl_context_set_trust(fp, trust); irc_rootmsg(irc, "fingerprint match, trust set to \"%s\"", trust); - if(u->flags & IRC_USER_OTR_ENCRYPTED) + if (u->flags & IRC_USER_OTR_ENCRYPTED) { u->flags |= IRC_USER_OTR_TRUSTED; + } otr_update_modeflags(irc, u); } } void cmd_otr_info(irc_t *irc, char **args) { - if(!args[1]) { + if (!args[1]) { show_general_otr_info(irc); } else { char *arg = g_strdup(args[1]); - char *myhandle, *handle=NULL, *protocol; + char *myhandle, *handle = NULL, *protocol; ConnContext *ctx; - + /* interpret arg as 'user/protocol/account' if possible */ protocol = strchr(arg, '/'); myhandle = NULL; - if(protocol) { + if (protocol) { *(protocol++) = '\0'; myhandle = strchr(protocol, '/'); } - if(protocol && myhandle) { + if (protocol && myhandle) { *(myhandle++) = '\0'; handle = arg; - ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - if(!ctx) { + ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, OTRL_INSTAG_MASTER, 0, NULL, + NULL, NULL); + if (!ctx) { irc_rootmsg(irc, "no such context"); g_free(arg); return; } } else { irc_user_t *u = irc_user_by_name(irc, args[1]); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", args[1]); g_free(arg); return; } ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - if(!ctx) { + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); + if (!ctx) { irc_rootmsg(irc, "no otr context with %s", args[1]); g_free(arg); return; } } - + /* show how we resolved the (nick) argument, if we did */ - if(handle!=arg) { + if (handle != arg) { irc_rootmsg(irc, "%s is %s/%s; we are %s/%s to them", args[1], - ctx->username, ctx->protocol, ctx->accountname, ctx->protocol); + ctx->username, ctx->protocol, ctx->accountname, ctx->protocol); } show_otr_context_info(irc, ctx); g_free(arg); @@ -1117,18 +1140,18 @@ void cmd_otr_info(irc_t *irc, char **args) void cmd_otr_keygen(irc_t *irc, char **args) { account_t *a; - + if ((a = account_get(irc->b, args[1])) == NULL) { irc_rootmsg(irc, "Could not find account `%s'.", args[1]); return; } - - if(keygen_in_progress(irc, a->user, a->prpl->name)) { + + if (keygen_in_progress(irc, a->user, a->prpl->name)) { irc_rootmsg(irc, "keygen for account `%s' already in progress", a->tag); return; } - - if(otrl_privkey_find(irc->otr->us, a->user, a->prpl->name)) { + + if (otrl_privkey_find(irc->otr->us, a->user, a->prpl->name)) { char *s = g_strdup_printf("account `%s' already has a key, replace it?", a->tag); query_add(irc, NULL, s, yes_keygen, NULL, NULL, a); g_free(s); @@ -1139,45 +1162,46 @@ void cmd_otr_keygen(irc_t *irc, char **args) void yes_forget_fingerprint(void *data) { - pair_t *p = (pair_t *)data; - irc_t *irc = (irc_t *)p->fst; - Fingerprint *fp = (Fingerprint *)p->snd; + pair_t *p = (pair_t *) data; + irc_t *irc = (irc_t *) p->fst; + Fingerprint *fp = (Fingerprint *) p->snd; g_free(p); - - if(fp == fp->context->active_fingerprint) { + + if (fp == fp->context->active_fingerprint) { irc_rootmsg(irc, "that fingerprint is active, terminate otr connection first"); return; } - + otrl_context_forget_fingerprint(fp, 0); } void yes_forget_context(void *data) { - pair_t *p = (pair_t *)data; - irc_t *irc = (irc_t *)p->fst; - ConnContext *ctx = (ConnContext *)p->snd; + pair_t *p = (pair_t *) data; + irc_t *irc = (irc_t *) p->fst; + ConnContext *ctx = (ConnContext *) p->snd; g_free(p); // XXX forget all contexts - - if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + + if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "active otr connection with %s, terminate it first", - peernick(irc, ctx->username, ctx->protocol)); + peernick(irc, ctx->username, ctx->protocol)); return; } - - if(ctx->msgstate == OTRL_MSGSTATE_FINISHED) + + if (ctx->msgstate == OTRL_MSGSTATE_FINISHED) { otrl_context_force_plaintext(ctx); + } otrl_context_forget(ctx); } void yes_forget_key(void *data) { - OtrlPrivKey *key = (OtrlPrivKey *)data; - + OtrlPrivKey *key = (OtrlPrivKey *) data; + otrl_privkey_forget(key); /* Hm, libotr doesn't seem to offer a function for explicitly /writing/ keyfiles. So the key will be back on the next load... */ @@ -1186,113 +1210,105 @@ void yes_forget_key(void *data) void cmd_otr_forget(irc_t *irc, char **args) { - if(!strcmp(args[1], "fingerprint")) - { + if (!strcmp(args[1], "fingerprint")) { irc_user_t *u; ConnContext *ctx; Fingerprint *fp; char human[54]; char *s; pair_t *p; - - if(!args[3]) { + + if (!args[3]) { irc_rootmsg(irc, "otr %s %s: not enough arguments (2 req.)", args[0], args[1]); return; } - + /* TODO: allow context specs ("user/proto/account") in 'otr forget fingerprint'? */ u = irc_user_by_name(irc, args[2]); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", args[2]); return; } - + ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - if(!ctx) { + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); + if (!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; } - - fp = match_fingerprint(irc, ctx, ((const char **)args)+3); - if(!fp) { + + fp = match_fingerprint(irc, ctx, ((const char **) args) + 3); + if (!fp) { /* match_fingerprint does error messages */ return; } - - if(fp == ctx->active_fingerprint) { + + if (fp == ctx->active_fingerprint) { irc_rootmsg(irc, "that fingerprint is active, terminate otr connection first"); return; } - + otrl_privkey_hash_to_human(human, fp->fingerprint); s = g_strdup_printf("about to forget fingerprint %s, are you sure?", human); p = g_malloc(sizeof(pair_t)); - if(!p) + if (!p) { return; + } p->fst = irc; p->snd = fp; query_add(irc, NULL, s, yes_forget_fingerprint, NULL, NULL, p); g_free(s); - } - - else if(!strcmp(args[1], "context")) - { + } else if (!strcmp(args[1], "context")) { irc_user_t *u; ConnContext *ctx; char *s; pair_t *p; - + /* TODO: allow context specs ("user/proto/account") in 'otr forget contex'? */ u = irc_user_by_name(irc, args[2]); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", args[2]); return; } - + ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, - u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); - if(!ctx) { + u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); + if (!ctx) { irc_rootmsg(irc, "no otr context with %s", args[2]); return; } - - if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + + if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "active otr connection with %s, terminate it first", args[2]); return; } - + s = g_strdup_printf("about to forget otr data about %s, are you sure?", args[2]); p = g_malloc(sizeof(pair_t)); - if(!p) + if (!p) { return; + } p->fst = irc; p->snd = ctx; query_add(irc, NULL, s, yes_forget_context, NULL, NULL, p); g_free(s); - } - - else if(!strcmp(args[1], "key")) - { + } else if (!strcmp(args[1], "key")) { OtrlPrivKey *key; char *s; - - key = match_privkey(irc, ((const char **)args)+2); - if(!key) { + + key = match_privkey(irc, ((const char **) args) + 2); + if (!key) { /* match_privkey does error messages */ return; } - + s = g_strdup_printf("about to forget the private key for %s/%s, are you sure?", - key->accountname, key->protocol); + key->accountname, key->protocol); query_add(irc, NULL, s, yes_forget_key, NULL, NULL, key); g_free(s); - } - - else - { + } else { irc_rootmsg(irc, "otr %s: unknown subcommand \"%s\", see \x02help otr forget\x02", - args[0], args[1]); + args[0], args[1]); } } @@ -1306,14 +1322,14 @@ void log_otr_message(void *opdata, const char *fmt, ...) va_start(va, fmt); char *msg = g_strdup_vprintf(fmt, va); va_end(va); - + log_message(LOGLVL_INFO, "otr: %s", msg); } void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...) { struct im_connection *ic = - check_imc(opdata, ctx->accountname, ctx->protocol); + check_imc(opdata, ctx->accountname, ctx->protocol); irc_t *irc = ic->bee->ui_data; irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); va_list va; @@ -1322,7 +1338,7 @@ void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...) char *msg = g_strdup_vprintf(fmt, va); va_end(va); - if(u) { + if (u) { /* display as a notice from this particular user */ irc_usernotice(u, "%s", msg); } else { @@ -1334,59 +1350,59 @@ void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...) /* combined handler for the 'otr smp' and 'otr smpq' commands */ void otr_smp_or_smpq(irc_t *irc, const char *nick, const char *question, - const char *secret) + const char *secret) { irc_user_t *u; ConnContext *ctx; otrl_instag_t instag = OTRL_INSTAG_BEST; // XXX u = irc_user_by_name(irc, nick); - if(!u || !u->bu || !u->bu->ic) { + if (!u || !u->bu || !u->bu->ic) { irc_rootmsg(irc, "%s: unknown user", nick); return; } - if(!(u->bu->flags & BEE_USER_ONLINE)) { + if (!(u->bu->flags & BEE_USER_ONLINE)) { irc_rootmsg(irc, "%s is offline", nick); return; } - + ctx = otrl_context_find(irc->otr->us, u->bu->handle, - u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, instag, 0, NULL, NULL, NULL); - if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { + u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, instag, 0, NULL, NULL, NULL); + if (!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" - " %s\x02", nick, nick); + " %s\x02", nick, nick); return; } - if(ctx->smstate->nextExpected != OTRL_SMP_EXPECT1) { + if (ctx->smstate->nextExpected != OTRL_SMP_EXPECT1) { log_message(LOGLVL_INFO, - "SMP already in phase %d, sending abort before reinitiating", - ctx->smstate->nextExpected+1); + "SMP already in phase %d, sending abort before reinitiating", + ctx->smstate->nextExpected + 1); otrl_message_abort_smp(irc->otr->us, &otr_ops, u->bu->ic, ctx); otrl_sm_state_free(ctx->smstate); } - if(question) { + if (question) { /* this was 'otr smpq', just initiate */ irc_rootmsg(irc, "smp: initiating with %s...", u->nick); otrl_message_initiate_smp_q(irc->otr->us, &otr_ops, u->bu->ic, ctx, - question, (unsigned char *)secret, strlen(secret)); + question, (unsigned char *) secret, strlen(secret)); /* smp is now in EXPECT2 */ } else { /* this was 'otr smp', initiate or reply */ /* warning: the following assumes that smstates are cleared whenever an SMP - is completed or aborted! */ - if(ctx->smstate->secret == NULL) { + is completed or aborted! */ + if (ctx->smstate->secret == NULL) { irc_rootmsg(irc, "smp: initiating with %s...", u->nick); otrl_message_initiate_smp(irc->otr->us, &otr_ops, - u->bu->ic, ctx, (unsigned char *)secret, strlen(secret)); + u->bu->ic, ctx, (unsigned char *) secret, strlen(secret)); /* 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_rootmsg(irc, "smp: responding to %s...", u->nick); otrl_message_respond_smp(irc->otr->us, &otr_ops, - u->bu->ic, ctx, (unsigned char *)secret, strlen(secret)); + u->bu->ic, ctx, (unsigned char *) secret, strlen(secret)); /* smp is now in EXPECT3 */ } } @@ -1397,87 +1413,93 @@ gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond) { otr_t *otr = data; - if(otr && otr->us) + if (otr && otr->us) { otrl_message_poll(otr->us, &otr_ops, NULL); + } - return TRUE; /* cycle timer */ + return TRUE; /* cycle timer */ } /* helper to assert that account and protocol names given to ops below always match the im_connection passed through as opdata */ struct im_connection *check_imc(void *opdata, const char *accountname, - const char *protocol) + const char *protocol) { - struct im_connection *ic = (struct im_connection *)opdata; + struct im_connection *ic = (struct im_connection *) opdata; /* libotr 4.0.0 has a bug where it doesn't set opdata, so we catch * that and try to find the desired connection in the global list. */ - if(!ic) { + if (!ic) { GSList *l; - for(l=get_connections(); l; l=l->next) { + for (l = get_connections(); l; l = l->next) { ic = l->data; - if(strcmp(accountname, ic->acc->user) == 0 && - strcmp(protocol, ic->acc->prpl->name) == 0) + if (strcmp(accountname, ic->acc->user) == 0 && + strcmp(protocol, ic->acc->prpl->name) == 0) { break; + } } assert(l != NULL); /* a match should always be found */ - if(!l) + if (!l) { return NULL; + } } if (strcmp(accountname, ic->acc->user) != 0) { log_message(LOGLVL_WARNING, - "otr: internal account name mismatch: '%s' vs '%s'", - accountname, ic->acc->user); + "otr: internal account name mismatch: '%s' vs '%s'", + accountname, ic->acc->user); } if (strcmp(protocol, ic->acc->prpl->name) != 0) { log_message(LOGLVL_WARNING, - "otr: internal protocol name mismatch: '%s' vs '%s'", - protocol, ic->acc->prpl->name); + "otr: internal protocol name mismatch: '%s' vs '%s'", + protocol, ic->acc->prpl->name); } - + return ic; } irc_user_t *peeruser(irc_t *irc, const char *handle, const char *protocol) { GSList *l; - - for(l=irc->b->users; l; l = l->next) { + + for (l = irc->b->users; l; l = l->next) { bee_user_t *bu = l->data; struct prpl *prpl; - if(!bu->ui_data || !bu->ic || !bu->handle) + if (!bu->ui_data || !bu->ic || !bu->handle) { continue; + } prpl = bu->ic->acc->prpl; - if(strcmp(prpl->name, protocol) == 0 - && prpl->handle_cmp(bu->handle, handle) == 0) { + if (strcmp(prpl->name, protocol) == 0 + && prpl->handle_cmp(bu->handle, handle) == 0) { return bu->ui_data; } } - + return NULL; } int hexval(char a) { - int x=g_ascii_tolower(a); - - if(x>='a' && x<='f') + int x = g_ascii_tolower(a); + + if (x >= 'a' && x <= 'f') { x = x - 'a' + 10; - else if(x>='0' && x<='9') + } else if (x >= '0' && x <= '9') { x = x - '0'; - else + } else { return -1; - + } + return x; } const char *peernick(irc_t *irc, const char *handle, const char *protocol) { static char fallback[512]; - + irc_user_t *u = peeruser(irc, handle, protocol); - if(u) { + + if (u) { return u->nick; } else { g_snprintf(fallback, 511, "%s/%s", handle, protocol); @@ -1489,14 +1511,15 @@ void otr_update_uflags(ConnContext *context, irc_user_t *u) { const char *trust; - if(context->active_fingerprint) { + if (context->active_fingerprint) { u->flags |= IRC_USER_OTR_ENCRYPTED; trust = context->active_fingerprint->trust; - if(trust && trust[0]) + if (trust && trust[0]) { u->flags |= IRC_USER_OTR_TRUSTED; - else + } else { u->flags &= ~IRC_USER_OTR_TRUSTED; + } } else { u->flags &= ~IRC_USER_OTR_ENCRYPTED; } @@ -1512,26 +1535,28 @@ void show_fingerprints(irc_t *irc, ConnContext *ctx) char human[45]; Fingerprint *fp; const char *trust; - int count=0; - - for(fp=&ctx->fingerprint_root; fp; fp=fp->next) { - if(!fp->fingerprint) + int count = 0; + + for (fp = &ctx->fingerprint_root; fp; fp = fp->next) { + if (!fp->fingerprint) { continue; + } count++; otrl_privkey_hash_to_human(human, fp->fingerprint); - if(!fp->trust || fp->trust[0] == '\0') { - trust="untrusted"; + if (!fp->trust || fp->trust[0] == '\0') { + trust = "untrusted"; } else { - trust=fp->trust; + trust = fp->trust; } - if(fp == ctx->active_fingerprint) { + if (fp == ctx->active_fingerprint) { irc_rootmsg(irc, " \x02%s (%s)\x02", human, trust); } else { irc_rootmsg(irc, " %s (%s)", human, trust); } } - if(count==0) + if (count == 0) { irc_rootmsg(irc, " (none)"); + } } Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) @@ -1540,61 +1565,66 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args) char human[45]; char prefix[45], *p; int n; - int i,j; - + int i, j; + /* assemble the args into a prefix in standard "human" form */ - n=0; - p=prefix; - for(i=0; args[i]; i++) { - for(j=0; args[i][j]; j++) { + n = 0; + p = prefix; + for (i = 0; args[i]; i++) { + for (j = 0; args[i][j]; j++) { char c = g_ascii_toupper(args[i][j]); - - if(n>=40) { + + if (n >= 40) { irc_rootmsg(irc, "too many fingerprint digits given, expected at most 40"); return NULL; } - - if( (c>='A' && c<='F') || (c>='0' && c<='9') ) { + + if ((c >= 'A' && c <= 'F') || (c >= '0' && c <= '9')) { *(p++) = c; } else { - irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); + irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i + 1); return NULL; } - + n++; - if(n%8 == 0) + if (n % 8 == 0) { *(p++) = ' '; + } } } *p = '\0'; - + /* find first fingerprint with the given prefix */ n = strlen(prefix); - for(fp=&ctx->fingerprint_root; fp; fp=fp->next) { - if(!fp->fingerprint) + for (fp = &ctx->fingerprint_root; fp; fp = fp->next) { + if (!fp->fingerprint) { continue; + } otrl_privkey_hash_to_human(human, fp->fingerprint); - if(!strncmp(prefix, human, n)) + if (!strncmp(prefix, human, n)) { break; + } } - if(!fp) { + if (!fp) { irc_rootmsg(irc, "%s: no match", prefix); return NULL; } - + /* make sure the match, if any, is unique */ - for(fp2=fp->next; fp2; fp2=fp2->next) { - if(!fp2->fingerprint) + for (fp2 = fp->next; fp2; fp2 = fp2->next) { + if (!fp2->fingerprint) { continue; + } otrl_privkey_hash_to_human(human, fp2->fingerprint); - if(!strncmp(prefix, human, n)) + if (!strncmp(prefix, human, n)) { break; + } } - if(fp2) { + if (fp2) { irc_rootmsg(irc, "%s: multiple matches", prefix); return NULL; } - + return fp; } @@ -1604,61 +1634,66 @@ OtrlPrivKey *match_privkey(irc_t *irc, const char **args) char human[45]; char prefix[45], *p; int n; - int i,j; - + int i, j; + /* assemble the args into a prefix in standard "human" form */ - n=0; - p=prefix; - for(i=0; args[i]; i++) { - for(j=0; args[i][j]; j++) { + n = 0; + p = prefix; + for (i = 0; args[i]; i++) { + for (j = 0; args[i][j]; j++) { char c = g_ascii_toupper(args[i][j]); - - if(n>=40) { + + if (n >= 40) { irc_rootmsg(irc, "too many fingerprint digits given, expected at most 40"); return NULL; } - - if( (c>='A' && c<='F') || (c>='0' && c<='9') ) { + + if ((c >= 'A' && c <= 'F') || (c >= '0' && c <= '9')) { *(p++) = c; } else { - irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i+1); + irc_rootmsg(irc, "invalid hex digit '%c' in block %d", args[i][j], i + 1); return NULL; } - + n++; - if(n%8 == 0) + if (n % 8 == 0) { *(p++) = ' '; + } } } *p = '\0'; - + /* find first key which matches the given prefix */ n = strlen(prefix); - for(k=irc->otr->us->privkey_root; k; k=k->next) { + for (k = irc->otr->us->privkey_root; k; k = k->next) { p = otrl_privkey_fingerprint(irc->otr->us, human, k->accountname, k->protocol); - if(!p) /* gah! :-P */ + if (!p) { /* gah! :-P */ continue; - if(!strncmp(prefix, human, n)) + } + if (!strncmp(prefix, human, n)) { break; + } } - if(!k) { + if (!k) { irc_rootmsg(irc, "%s: no match", prefix); return NULL; } - + /* make sure the match, if any, is unique */ - for(k2=k->next; k2; k2=k2->next) { + for (k2 = k->next; k2; k2 = k2->next) { p = otrl_privkey_fingerprint(irc->otr->us, human, k2->accountname, k2->protocol); - if(!p) /* gah! :-P */ + if (!p) { /* gah! :-P */ continue; - if(!strncmp(prefix, human, n)) + } + if (!strncmp(prefix, human, n)) { break; + } } - if(k2) { + if (k2) { irc_rootmsg(irc, "%s: multiple matches", prefix); return NULL; } - + return k; } @@ -1671,73 +1706,77 @@ void show_general_otr_info(irc_t *irc) /* list all privkeys (including ones being generated) */ irc_rootmsg(irc, "\x1fprivate keys:\x1f"); - for(key=irc->otr->us->privkey_root; key; key=key->next) { + for (key = irc->otr->us->privkey_root; key; key = key->next) { const char *hash; - - switch(key->pubkey_type) { + + switch (key->pubkey_type) { case OTRL_PUBKEY_TYPE_DSA: irc_rootmsg(irc, " %s/%s - DSA", key->accountname, key->protocol); break; default: irc_rootmsg(irc, " %s/%s - type %d", key->accountname, key->protocol, - key->pubkey_type); + key->pubkey_type); } /* No, it doesn't make much sense to search for the privkey again by account/protocol, but libotr currently doesn't provide a direct routine for hashing a given 'OtrlPrivKey'... */ hash = otrl_privkey_fingerprint(irc->otr->us, human, key->accountname, key->protocol); - if(hash) /* should always succeed */ + if (hash) { /* should always succeed */ irc_rootmsg(irc, " %s", human); + } } - if(irc->otr->sent_accountname) { + if (irc->otr->sent_accountname) { irc_rootmsg(irc, " %s/%s - DSA", irc->otr->sent_accountname, - irc->otr->sent_protocol); + irc->otr->sent_protocol); irc_rootmsg(irc, " (being generated)"); } - for(kg=irc->otr->todo; kg; kg=kg->next) { + for (kg = irc->otr->todo; kg; kg = kg->next) { irc_rootmsg(irc, " %s/%s - DSA", kg->accountname, kg->protocol); irc_rootmsg(irc, " (queued)"); } - if(key == irc->otr->us->privkey_root && - !irc->otr->sent_accountname && - kg == irc->otr->todo) + if (key == irc->otr->us->privkey_root && + !irc->otr->sent_accountname && + kg == irc->otr->todo) { irc_rootmsg(irc, " (none)"); + } /* list all contexts */ /* XXX remove this, or split off as its own command */ /* XXX show instags? */ irc_rootmsg(irc, "%s", ""); irc_rootmsg(irc, "\x1f" "connection contexts:\x1f (bold=currently encrypted)"); - for(ctx=irc->otr->us->context_root; ctx; ctx=ctx->next) {\ + for (ctx = irc->otr->us->context_root; ctx; ctx = ctx->next) { \ irc_user_t *u; char *userstring; - + u = peeruser(irc, ctx->username, ctx->protocol); - if(u) + if (u) { userstring = g_strdup_printf("%s/%s/%s (%s)", - ctx->username, ctx->protocol, ctx->accountname, u->nick); - else + ctx->username, ctx->protocol, ctx->accountname, u->nick); + } else { userstring = g_strdup_printf("%s/%s/%s", - ctx->username, ctx->protocol, ctx->accountname); - - if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + ctx->username, ctx->protocol, ctx->accountname); + } + + if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { irc_rootmsg(irc, " \x02%s\x02", userstring); } else { irc_rootmsg(irc, " %s", userstring); } - + g_free(userstring); } - if(ctx == irc->otr->us->context_root) + if (ctx == irc->otr->us->context_root) { irc_rootmsg(irc, " (none)"); + } } void show_otr_context_info(irc_t *irc, ConnContext *ctx) { // XXX show all instags/subcontexts - switch(ctx->otr_offer) { + switch (ctx->otr_offer) { case OFFER_NOT: irc_rootmsg(irc, " otr offer status: none sent"); break; @@ -1754,7 +1793,7 @@ void show_otr_context_info(irc_t *irc, ConnContext *ctx) irc_rootmsg(irc, " otr offer status: %d", ctx->otr_offer); } - switch(ctx->msgstate) { + switch (ctx->msgstate) { case OTRL_MSGSTATE_PLAINTEXT: irc_rootmsg(irc, " connection state: cleartext"); break; @@ -1768,70 +1807,74 @@ void show_otr_context_info(irc_t *irc, ConnContext *ctx) irc_rootmsg(irc, " connection state: %d", ctx->msgstate); } - irc_rootmsg(irc, " fingerprints: (bold=active)"); + irc_rootmsg(irc, " fingerprints: (bold=active)"); show_fingerprints(irc, ctx); } int keygen_in_progress(irc_t *irc, const char *handle, const char *protocol) { kg_t *kg; - - if(!irc->otr->sent_accountname || !irc->otr->sent_protocol) + + if (!irc->otr->sent_accountname || !irc->otr->sent_protocol) { return 0; + } /* are we currently working on this key? */ - if(!strcmp(handle, irc->otr->sent_accountname) && - !strcmp(protocol, irc->otr->sent_protocol)) + if (!strcmp(handle, irc->otr->sent_accountname) && + !strcmp(protocol, irc->otr->sent_protocol)) { return 1; - + } + /* do we have it queued for later? */ - for(kg=irc->otr->todo; kg; kg=kg->next) { - if(!strcmp(handle, kg->accountname) && - !strcmp(protocol, kg->protocol)) + for (kg = irc->otr->todo; kg; kg = kg->next) { + if (!strcmp(handle, kg->accountname) && + !strcmp(protocol, kg->protocol)) { return 1; + } } - + return 0; } void otr_keygen(irc_t *irc, const char *handle, const char *protocol) { /* do nothing if a key for the requested account is already being generated */ - if(keygen_in_progress(irc, handle, protocol)) + if (keygen_in_progress(irc, handle, protocol)) { return; + } /* see if we already have a keygen child running. if not, start one and put a handler on its output. */ - if(!irc->otr->keygen || waitpid(irc->otr->keygen, NULL, WNOHANG)) { + if (!irc->otr->keygen || waitpid(irc->otr->keygen, NULL, WNOHANG)) { pid_t p; int to[2], from[2]; FILE *tof, *fromf; - - if(pipe(to) < 0 || pipe(from) < 0) { + + if (pipe(to) < 0 || pipe(from) < 0) { irc_rootmsg(irc, "otr keygen: couldn't create pipe: %s", strerror(errno)); return; } - + tof = fdopen(to[1], "w"); fromf = fdopen(from[0], "r"); - if(!tof || !fromf) { + if (!tof || !fromf) { irc_rootmsg(irc, "otr keygen: couldn't streamify pipe: %s", strerror(errno)); return; } - + p = fork(); - if(p<0) { + if (p < 0) { irc_rootmsg(irc, "otr keygen: couldn't fork: %s", strerror(errno)); return; } - - if(!p) { + + if (!p) { /* child process */ signal(SIGTERM, exit); keygen_child_main(irc->otr->us, to[0], from[1]); exit(0); } - + irc->otr->keygen = p; irc->otr->to = tof; irc->otr->from = fromf; @@ -1840,13 +1883,14 @@ void otr_keygen(irc_t *irc, const char *handle, const char *protocol) irc->otr->todo = NULL; b_input_add(from[0], B_EV_IO_READ, keygen_finish_handler, irc); } - + /* is the keygen slave currently working? */ - if(irc->otr->sent_accountname) { + if (irc->otr->sent_accountname) { /* enqueue our job for later transmission */ kg_t **kg = &irc->otr->todo; - while(*kg) - kg=&((*kg)->next); + while (*kg) { + kg = &((*kg)->next); + } *kg = g_new0(kg_t, 1); (*kg)->accountname = g_strdup(handle); (*kg)->protocol = g_strdup(protocol); @@ -1865,20 +1909,20 @@ void keygen_child_main(OtrlUserState us, int infd, int outfd) char filename[128], accountname[512], protocol[512]; gcry_error_t e; int tempfd; - + input = fdopen(infd, "r"); output = fdopen(outfd, "w"); - - while(!feof(input) && !ferror(input) && !feof(output) && !ferror(output)) { + + while (!feof(input) && !ferror(input) && !feof(output) && !ferror(output)) { myfgets(accountname, 512, input); myfgets(protocol, 512, input); - + strncpy(filename, "/tmp/bitlbee-XXXXXX", 128); tempfd = mkstemp(filename); close(tempfd); e = otrl_privkey_generate(us, filename, accountname, protocol); - if(e) { + if (e) { fprintf(output, "\n"); /* this means failure */ fprintf(output, "otr keygen: %s\n", gcry_strerror(e)); unlink(filename); @@ -1888,27 +1932,27 @@ void keygen_child_main(OtrlUserState us, int infd, int outfd) } fflush(output); } - + fclose(input); fclose(output); } gboolean keygen_finish_handler(gpointer data, gint fd, b_input_condition cond) { - irc_t *irc = (irc_t *)data; + irc_t *irc = (irc_t *) data; char filename[512], msg[512]; myfgets(filename, 512, irc->otr->from); myfgets(msg, 512, irc->otr->from); - + irc_rootmsg(irc, "%s", msg); - if(filename[0]) { - if(strsane(irc->user->nick)) { + if (filename[0]) { + if (strsane(irc->user->nick)) { char *kf = g_strdup_printf("%s%s.otr_keys", global.conf->configdir, irc->user->nick); char *tmp = g_strdup_printf("%s.new", kf); copyfile(filename, tmp); unlink(filename); - rename(tmp,kf); + rename(tmp, kf); otrl_privkey_read(irc->otr->us, kf); g_free(kf); g_free(tmp); @@ -1917,15 +1961,15 @@ gboolean keygen_finish_handler(gpointer data, gint fd, b_input_condition cond) unlink(filename); } } - + /* forget this job */ g_free(irc->otr->sent_accountname); g_free(irc->otr->sent_protocol); irc->otr->sent_accountname = NULL; irc->otr->sent_protocol = NULL; - + /* see if there are any more in the queue */ - if(irc->otr->todo) { + if (irc->otr->todo) { kg_t *p = irc->otr->todo; /* send the next one over */ fprintf(irc->otr->to, "%s\n%s\n", p->accountname, p->protocol); @@ -1952,39 +1996,41 @@ void copyfile(const char *a, const char *b) int fda, fdb; int n; char buf[1024]; - + fda = open(a, O_RDONLY); fdb = open(b, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - while((n=read(fda, buf, 1024)) > 0) + + while ((n = read(fda, buf, 1024)) > 0) { write(fdb, buf, n); - + } + close(fda); - close(fdb); + close(fdb); } void myfgets(char *s, int size, FILE *stream) { - if(!fgets(s, size, stream)) { + if (!fgets(s, size, stream)) { s[0] = '\0'; } else { int n = strlen(s); - if(n>0 && s[n-1] == '\n') - s[n-1] = '\0'; + if (n > 0 && s[n - 1] == '\n') { + s[n - 1] = '\0'; + } } } void yes_keygen(void *data) { - account_t *acc = (account_t *)data; + account_t *acc = (account_t *) data; irc_t *irc = acc->bee->ui_data; - - if(keygen_in_progress(irc, acc->user, acc->prpl->name)) { + + if (keygen_in_progress(irc, acc->user, acc->prpl->name)) { irc_rootmsg(irc, "keygen for %s/%s already in progress", - acc->user, acc->prpl->name); + acc->user, acc->prpl->name); } else { irc_rootmsg(irc, "starting background keygen for %s/%s", - acc->user, acc->prpl->name); + acc->user, acc->prpl->name); irc_rootmsg(irc, "you will be notified when it completes"); otr_keygen(irc, acc->user, acc->prpl->name); } @@ -1999,13 +2045,15 @@ int strsane(const char *s) /* close the OTR connection with the given buddy */ gboolean otr_disconnect_user(irc_t *irc, irc_user_t *u) { - if(!u || !u->bu || !u->bu->ic) + if (!u || !u->bu || !u->bu->ic) { return FALSE; + } /* XXX we disconnect all instances; is that what we want? */ otrl_message_disconnect_all_instances(irc->otr->us, &otr_ops, - u->bu->ic, u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, u->bu->handle); - + u->bu->ic, u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, + u->bu->handle); + u->flags &= ~IRC_USER_OTR_TRUSTED; u->flags &= ~IRC_USER_OTR_ENCRYPTED; otr_update_modeflags(irc, u); @@ -2019,8 +2067,8 @@ void otr_disconnect_all(irc_t *irc) irc_user_t *u; ConnContext *ctx; - for(ctx=irc->otr->us->context_root; ctx; ctx=ctx->next) { - if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { + for (ctx = irc->otr->us->context_root; ctx; ctx = ctx->next) { + if (ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { u = peeruser(irc, ctx->username, ctx->protocol); (void) otr_disconnect_user(irc, u); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2008 Wilmer van der Gaast and others * @@ -6,7 +6,7 @@ /* OTR support (cf. http://www.cypherpunks.ca/otr/) - + (c) 2008,2013 Sven Moritz Hallberg <pesco@khjk.org> funded by stonedcoder.org */ @@ -48,7 +48,7 @@ struct account; typedef struct kg { char *accountname; char *protocol; - + struct kg *next; } kg_t; @@ -58,11 +58,11 @@ typedef struct otr { pid_t keygen; /* pid of keygen slave (0 if none) */ FILE *to; /* pipe to keygen slave */ FILE *from; /* pipe from keygen slave */ - + /* active keygen job (NULL if none) */ char *sent_accountname; char *sent_protocol; - + /* keygen jobs waiting to be sent to slave */ kg_t *todo; diff --git a/protocols/account.c b/protocols/account.c index 234b9de2..e1025a53 100644 --- a/protocols/account.c +++ b/protocols/account.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -31,450 +31,446 @@ static const char* account_protocols_local[] = { "gg", "whatsapp", NULL }; -static char *set_eval_nick_source( set_t *set, char *value ); +static char *set_eval_nick_source(set_t *set, char *value); -account_t *account_add( bee_t *bee, struct prpl *prpl, char *user, char *pass ) +account_t *account_add(bee_t *bee, struct prpl *prpl, char *user, char *pass) { account_t *a; set_t *s; - char tag[strlen(prpl->name)+10]; - - if( bee->accounts ) - { - for( a = bee->accounts; a->next; a = a->next ); - a = a->next = g_new0( account_t, 1 ); - } - else - { - bee->accounts = a = g_new0 ( account_t, 1 ); + char tag[strlen(prpl->name) + 10]; + + if (bee->accounts) { + for (a = bee->accounts; a->next; a = a->next) { + ; + } + a = a->next = g_new0(account_t, 1); + } else { + bee->accounts = a = g_new0(account_t, 1); } - + a->prpl = prpl; - a->user = g_strdup( user ); - a->pass = g_strdup( pass ); + a->user = g_strdup(user); + a->pass = g_strdup(pass); a->auto_connect = 1; a->bee = bee; - - s = set_add( &a->set, "auto_connect", "true", set_eval_account, a ); + + s = set_add(&a->set, "auto_connect", "true", set_eval_account, a); s->flags |= SET_NOSAVE; - - s = set_add( &a->set, "auto_reconnect", "true", set_eval_bool, a ); - - s = set_add( &a->set, "nick_format", NULL, NULL, a ); + + s = set_add(&a->set, "auto_reconnect", "true", set_eval_bool, a); + + s = set_add(&a->set, "nick_format", NULL, NULL, a); s->flags |= SET_NULL_OK; - - s = set_add( &a->set, "nick_source", "handle", set_eval_nick_source, a ); + + s = set_add(&a->set, "nick_source", "handle", set_eval_nick_source, a); s->flags |= SET_NOSAVE; /* Just for bw compatibility! */ - - s = set_add( &a->set, "password", NULL, set_eval_account, a ); + + s = set_add(&a->set, "password", NULL, set_eval_account, a); s->flags |= SET_NOSAVE | SET_NULL_OK | SET_PASSWORD; - - s = set_add( &a->set, "tag", NULL, set_eval_account, a ); + + s = set_add(&a->set, "tag", NULL, set_eval_account, a); s->flags |= SET_NOSAVE; - - s = set_add( &a->set, "username", NULL, set_eval_account, a ); + + s = set_add(&a->set, "username", NULL, set_eval_account, a); s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; - set_setstr( &a->set, "username", user ); - + set_setstr(&a->set, "username", user); + /* Hardcode some more clever tag guesses. */ - strcpy( tag, prpl->name ); - if( strcmp( prpl->name, "oscar" ) == 0 ) - { - if( g_ascii_isdigit( a->user[0] ) ) - strcpy( tag, "icq" ); - else - strcpy( tag, "aim" ); - } - else if( strcmp( prpl->name, "jabber" ) == 0 ) - { - if( strstr( a->user, "@gmail.com" ) || - strstr( a->user, "@googlemail.com" ) ) - strcpy( tag, "gtalk" ); - else if( strstr( a->user, "@chat.facebook.com" ) ) - strcpy( tag, "fb" ); + strcpy(tag, prpl->name); + if (strcmp(prpl->name, "oscar") == 0) { + if (g_ascii_isdigit(a->user[0])) { + strcpy(tag, "icq"); + } else { + strcpy(tag, "aim"); + } + } else if (strcmp(prpl->name, "jabber") == 0) { + if (strstr(a->user, "@gmail.com") || + strstr(a->user, "@googlemail.com")) { + strcpy(tag, "gtalk"); + } else if (strstr(a->user, "@chat.facebook.com")) { + strcpy(tag, "fb"); + } } - - if( account_by_tag( bee, tag ) ) - { - char *numpos = tag + strlen( tag ); + + if (account_by_tag(bee, tag)) { + char *numpos = tag + strlen(tag); int i; - for( i = 2; i < 10000; i ++ ) - { - sprintf( numpos, "%d", i ); - if( !account_by_tag( bee, tag ) ) + for (i = 2; i < 10000; i++) { + sprintf(numpos, "%d", i); + if (!account_by_tag(bee, tag)) { break; + } } } - set_setstr( &a->set, "tag", tag ); - - a->nicks = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free ); - + set_setstr(&a->set, "tag", tag); + + a->nicks = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + /* This function adds some more settings (and might want to do more things that have to be done now, although I can't think of anything. */ - if( prpl->init ) - prpl->init( a ); - - s = set_add( &a->set, "away", NULL, set_eval_account, a ); + if (prpl->init) { + prpl->init(a); + } + + s = set_add(&a->set, "away", NULL, set_eval_account, a); s->flags |= SET_NULL_OK; - - if( a->flags & ACC_FLAG_STATUS_MESSAGE ) - { - s = set_add( &a->set, "status", NULL, set_eval_account, a ); + + if (a->flags & ACC_FLAG_STATUS_MESSAGE) { + s = set_add(&a->set, "status", NULL, set_eval_account, a); s->flags |= SET_NULL_OK; } - + return a; } -char *set_eval_account( set_t *set, char *value ) +char *set_eval_account(set_t *set, char *value) { account_t *acc = set->data; - + /* Double-check: We refuse to edit on-line accounts. */ - if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic ) + if (set->flags & ACC_SET_OFFLINE_ONLY && acc->ic) { return SET_INVALID; - - if( strcmp( set->key, "server" ) == 0 ) - { - g_free( acc->server ); - if( value && *value ) - { - acc->server = g_strdup( value ); + } + + if (strcmp(set->key, "server") == 0) { + g_free(acc->server); + if (value && *value) { + acc->server = g_strdup(value); return value; + } else { + acc->server = g_strdup(set->def); + return g_strdup(set->def); } - else - { - acc->server = g_strdup( set->def ); - return g_strdup( set->def ); - } - } - else if( strcmp( set->key, "username" ) == 0 ) - { - g_free( acc->user ); - acc->user = g_strdup( value ); + } else if (strcmp(set->key, "username") == 0) { + g_free(acc->user); + acc->user = g_strdup(value); return value; - } - else if( strcmp( set->key, "password" ) == 0 ) - { + } else if (strcmp(set->key, "password") == 0) { /* set -del allows /oper to be used to change the password or, iff oauth is enabled, reset the oauth credential magic. */ - if( !value ) { - if ( set_getbool( &(acc->set), "oauth" ) ) { + if (!value) { + if (set_getbool(&(acc->set), "oauth")) { value = ""; } else { value = PASSWORD_PENDING; - ((irc_t *)acc->bee->ui_data)->status |= OPER_HACK_ACCOUNT_PASSWORD; - irc_rootmsg((irc_t *)acc->bee->ui_data, "You may now use /OPER to set the password"); + ((irc_t *) acc->bee->ui_data)->status |= OPER_HACK_ACCOUNT_PASSWORD; + irc_rootmsg((irc_t *) acc->bee->ui_data, "You may now use /OPER to set the password"); } } - - g_free( acc->pass ); - acc->pass = g_strdup( value ); - return NULL; /* password shouldn't be visible in plaintext! */ - } - else if( strcmp( set->key, "tag" ) == 0 ) - { + + g_free(acc->pass); + acc->pass = g_strdup(value); + return NULL; /* password shouldn't be visible in plaintext! */ + } else if (strcmp(set->key, "tag") == 0) { account_t *oa; - + /* Enforce uniqueness. */ - if( ( oa = account_by_tag( acc->bee, value ) ) && oa != acc ) + if ((oa = account_by_tag(acc->bee, value)) && oa != acc) { return SET_INVALID; - - g_free( acc->tag ); - acc->tag = g_strdup( value ); + } + + g_free(acc->tag); + acc->tag = g_strdup(value); return value; - } - else if( strcmp( set->key, "auto_connect" ) == 0 ) - { - if( !is_bool( value ) ) + } else if (strcmp(set->key, "auto_connect") == 0) { + if (!is_bool(value)) { return SET_INVALID; - - acc->auto_connect = bool2int( value ); + } + + acc->auto_connect = bool2int(value); return value; - } - else if( strcmp( set->key, "away" ) == 0 || - strcmp( set->key, "status" ) == 0 ) - { - if( acc->ic && acc->ic->flags & OPT_LOGGED_IN ) - { + } else if (strcmp(set->key, "away") == 0 || + strcmp(set->key, "status") == 0) { + if (acc->ic && acc->ic->flags & OPT_LOGGED_IN) { /* If we're currently on-line, set the var now already (bit of a hack) and send an update. */ - g_free( set->value ); - set->value = g_strdup( value ); - - imc_away_send_update( acc->ic ); + g_free(set->value); + set->value = g_strdup(value); + + imc_away_send_update(acc->ic); } - + return value; } - + return SET_INVALID; } /* For bw compatibility, have this write-only setting. */ -static char *set_eval_nick_source( set_t *set, char *value ) +static char *set_eval_nick_source(set_t *set, char *value) { account_t *a = set->data; - - if( strcmp( value, "full_name" ) == 0 ) - set_setstr( &a->set, "nick_format", "%full_name" ); - else if( strcmp( value, "first_name" ) == 0 ) - set_setstr( &a->set, "nick_format", "%first_name" ); - else - set_setstr( &a->set, "nick_format", "%-@nick" ); - + + if (strcmp(value, "full_name") == 0) { + set_setstr(&a->set, "nick_format", "%full_name"); + } else if (strcmp(value, "first_name") == 0) { + set_setstr(&a->set, "nick_format", "%first_name"); + } else { + set_setstr(&a->set, "nick_format", "%-@nick"); + } + return value; } -account_t *account_get( bee_t *bee, const char *id ) +account_t *account_get(bee_t *bee, const char *id) { account_t *a, *ret = NULL; char *handle, *s; int nr; - + /* Tags get priority above anything else. */ - if( ( a = account_by_tag( bee, id ) ) ) + if ((a = account_by_tag(bee, id))) { return a; - + } + /* This checks if the id string ends with (...) */ - if( ( handle = strchr( id, '(' ) ) && ( s = strchr( handle, ')' ) ) && s[1] == 0 ) - { + if ((handle = strchr(id, '(')) && (s = strchr(handle, ')')) && s[1] == 0) { struct prpl *proto; - + *s = *handle = 0; - handle ++; - - if( ( proto = find_protocol( id ) ) ) - { - for( a = bee->accounts; a; a = a->next ) - if( a->prpl == proto && - a->prpl->handle_cmp( handle, a->user ) == 0 ) + handle++; + + if ((proto = find_protocol(id))) { + for (a = bee->accounts; a; a = a->next) { + if (a->prpl == proto && + a->prpl->handle_cmp(handle, a->user) == 0) { ret = a; + } + } } - + /* Restore the string. */ - handle --; + handle--; *handle = '('; *s = ')'; - - if( ret ) + + if (ret) { return ret; + } } - - if( sscanf( id, "%d", &nr ) == 1 && nr < 1000 ) - { - for( a = bee->accounts; a; a = a->next ) - if( ( nr-- ) == 0 ) - return( a ); - - return( NULL ); + + if (sscanf(id, "%d", &nr) == 1 && nr < 1000) { + for (a = bee->accounts; a; a = a->next) { + if ((nr--) == 0) { + return(a); + } + } + + return(NULL); } - - for( a = bee->accounts; a; a = a->next ) - { - if( g_strcasecmp( id, a->prpl->name ) == 0 ) - { - if( !ret ) + + for (a = bee->accounts; a; a = a->next) { + if (g_strcasecmp(id, a->prpl->name) == 0) { + if (!ret) { ret = a; - else - return( NULL ); /* We don't want to match more than one... */ - } - else if( strstr( a->user, id ) ) - { - if( !ret ) + } else { + return(NULL); /* We don't want to match more than one... */ + } + } else if (strstr(a->user, id)) { + if (!ret) { ret = a; - else - return( NULL ); + } else { + return(NULL); + } } } - - return( ret ); + + return(ret); } -account_t *account_by_tag( bee_t *bee, const char *tag ) +account_t *account_by_tag(bee_t *bee, const char *tag) { account_t *a; - - for( a = bee->accounts; a; a = a->next ) - if( a->tag && g_strcasecmp( tag, a->tag ) == 0 ) + + for (a = bee->accounts; a; a = a->next) { + if (a->tag && g_strcasecmp(tag, a->tag) == 0) { return a; - + } + } + return NULL; } -void account_del( bee_t *bee, account_t *acc ) +void account_del(bee_t *bee, account_t *acc) { account_t *a, *l = NULL; - - if( acc->ic ) + + if (acc->ic) { /* Caller should have checked, accounts still in use can't be deleted. */ return; - - for( a = bee->accounts; a; a = (l=a)->next ) - if( a == acc ) - { - if( l ) + } + + for (a = bee->accounts; a; a = (l = a)->next) { + if (a == acc) { + if (l) { l->next = a->next; - else + } else { bee->accounts = a->next; - + } + /** FIXME for( c = bee->chatrooms; c; c = nc ) { - nc = c->next; - if( acc == c->acc ) - chat_del( bee, c ); + nc = c->next; + if( acc == c->acc ) + chat_del( bee, c ); } */ - - while( a->set ) - set_del( &a->set, a->set->key ); - - g_hash_table_destroy( a->nicks ); - - g_free( a->tag ); - g_free( a->user ); - g_free( a->pass ); - g_free( a->server ); - if( a->reconnect ) /* This prevents any reconnect still queued to happen */ - cancel_auto_reconnect( a ); - g_free( a ); - + + while (a->set) { + set_del(&a->set, a->set->key); + } + + g_hash_table_destroy(a->nicks); + + g_free(a->tag); + g_free(a->user); + g_free(a->pass); + g_free(a->server); + if (a->reconnect) { /* This prevents any reconnect still queued to happen */ + cancel_auto_reconnect(a); + } + g_free(a); + break; } + } } -static gboolean account_on_timeout( gpointer d, gint fd, b_input_condition cond ); +static gboolean account_on_timeout(gpointer d, gint fd, b_input_condition cond); -void account_on( bee_t *bee, account_t *a ) +void account_on(bee_t *bee, account_t *a) { - if( a->ic ) - { + if (a->ic) { /* Trying to enable an already-enabled account */ return; } - - cancel_auto_reconnect( a ); - + + cancel_auto_reconnect(a); + a->reconnect = 0; - a->prpl->login( a ); - - if( a->ic && !( a->ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) ) - a->ic->keepalive = b_timeout_add( 120000, account_on_timeout, a->ic ); + a->prpl->login(a); + + if (a->ic && !(a->ic->flags & (OPT_SLOW_LOGIN | OPT_LOGGED_IN))) { + a->ic->keepalive = b_timeout_add(120000, account_on_timeout, a->ic); + } } -void account_off( bee_t *bee, account_t *a ) +void account_off(bee_t *bee, account_t *a) { - imc_logout( a->ic, FALSE ); + imc_logout(a->ic, FALSE); a->ic = NULL; - if( a->reconnect ) - { + if (a->reconnect) { /* Shouldn't happen */ - cancel_auto_reconnect( a ); + cancel_auto_reconnect(a); } } -static gboolean account_on_timeout( gpointer d, gint fd, b_input_condition cond ) +static gboolean account_on_timeout(gpointer d, gint fd, b_input_condition cond) { struct im_connection *ic = d; - - if( !( ic->flags & ( OPT_SLOW_LOGIN | OPT_LOGGED_IN ) ) ) - { - imcb_error( ic, "Connection timeout" ); - imc_logout( ic, TRUE ); + + if (!(ic->flags & (OPT_SLOW_LOGIN | OPT_LOGGED_IN))) { + imcb_error(ic, "Connection timeout"); + imc_logout(ic, TRUE); } - + return FALSE; } -struct account_reconnect_delay -{ +struct account_reconnect_delay { int start; char op; int step; int max; }; -int account_reconnect_delay_parse( char *value, struct account_reconnect_delay *p ) +int account_reconnect_delay_parse(char *value, struct account_reconnect_delay *p) { - memset( p, 0, sizeof( *p ) ); + memset(p, 0, sizeof(*p)); /* A whole day seems like a sane "maximum maximum". */ p->max = 86400; - + /* Format: /[0-9]+([*+][0-9]+(<[0-9+])?)?/ */ - while( *value && g_ascii_isdigit( *value ) ) + while (*value && g_ascii_isdigit(*value)) { p->start = p->start * 10 + *value++ - '0'; - + } + /* Sure, call me evil for implementing my own fscanf here, but it's dead simple and I immediately know where to continue parsing. */ - - if( *value == 0 ) + + if (*value == 0) { /* If the string ends now, the delay is constant. */ return 1; - else if( *value != '+' && *value != '*' ) + } else if (*value != '+' && *value != '*') { /* Otherwise allow either a + or a * */ return 0; - + } + p->op = *value++; - + /* + or * the delay by this number every time. */ - while( *value && g_ascii_isdigit( *value ) ) + while (*value && g_ascii_isdigit(*value)) { p->step = p->step * 10 + *value++ - '0'; - - if( *value == 0 ) + } + + if (*value == 0) { /* Use the default maximum (one day). */ return 1; - else if( *value != '<' ) + } else if (*value != '<') { return 0; - + } + p->max = 0; - value ++; - while( *value && g_ascii_isdigit( *value ) ) + value++; + while (*value && g_ascii_isdigit(*value)) { p->max = p->max * 10 + *value++ - '0'; - + } + return p->max > 0; } -char *set_eval_account_reconnect_delay( set_t *set, char *value ) +char *set_eval_account_reconnect_delay(set_t *set, char *value) { struct account_reconnect_delay p; - - return account_reconnect_delay_parse( value, &p ) ? value : SET_INVALID; + + return account_reconnect_delay_parse(value, &p) ? value : SET_INVALID; } -int account_reconnect_delay( account_t *a ) +int account_reconnect_delay(account_t *a) { - char *setting = set_getstr( &a->bee->set, "auto_reconnect_delay" ); + char *setting = set_getstr(&a->bee->set, "auto_reconnect_delay"); struct account_reconnect_delay p; - - if( account_reconnect_delay_parse( setting, &p ) ) - { - if( a->auto_reconnect_delay == 0 ) + + if (account_reconnect_delay_parse(setting, &p)) { + if (a->auto_reconnect_delay == 0) { a->auto_reconnect_delay = p.start; - else if( p.op == '+' ) + } else if (p.op == '+') { a->auto_reconnect_delay += p.step; - else if( p.op == '*' ) + } else if (p.op == '*') { a->auto_reconnect_delay *= p.step; - - if( a->auto_reconnect_delay > p.max ) + } + + if (a->auto_reconnect_delay > p.max) { a->auto_reconnect_delay = p.max; - } - else - { + } + } else { a->auto_reconnect_delay = 0; } - + return a->auto_reconnect_delay; } -int protocol_account_islocal( const char* protocol ) +int protocol_account_islocal(const char* protocol) { const char** p = account_protocols_local; + do { - if( strcmp( *p, protocol ) == 0 ) + if (strcmp(*p, protocol) == 0) { return 1; - } while( *( ++p ) ); + } + } while (*(++p)); return 0; } diff --git a/protocols/account.h b/protocols/account.h index d3e93504..0e118680 100644 --- a/protocols/account.h +++ b/protocols/account.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -26,48 +26,45 @@ #ifndef _ACCOUNT_H #define _ACCOUNT_H -typedef struct account -{ +typedef struct account { struct prpl *prpl; char *user; char *pass; char *server; char *tag; - + int auto_connect; int auto_reconnect_delay; int reconnect; int flags; - + set_t *set; GHashTable *nicks; - + struct bee *bee; struct im_connection *ic; struct account *next; } account_t; -account_t *account_add( bee_t *bee, struct prpl *prpl, char *user, char *pass ); -account_t *account_get( bee_t *bee, const char *id ); -account_t *account_by_tag( bee_t *bee, const char *tag ); -void account_del( bee_t *bee, account_t *acc ); -void account_on( bee_t *bee, account_t *a ); -void account_off( bee_t *bee, account_t *a ); +account_t *account_add(bee_t *bee, struct prpl *prpl, char *user, char *pass); +account_t *account_get(bee_t *bee, const char *id); +account_t *account_by_tag(bee_t *bee, const char *tag); +void account_del(bee_t *bee, account_t *acc); +void account_on(bee_t *bee, account_t *a); +void account_off(bee_t *bee, account_t *a); -char *set_eval_account( set_t *set, char *value ); -char *set_eval_account_reconnect_delay( set_t *set, char *value ); -int account_reconnect_delay( account_t *a ); +char *set_eval_account(set_t *set, char *value); +char *set_eval_account_reconnect_delay(set_t *set, char *value); +int account_reconnect_delay(account_t *a); -int protocol_account_islocal( const char* protocol ); +int protocol_account_islocal(const char* protocol); -typedef enum -{ +typedef enum { ACC_SET_OFFLINE_ONLY = 0x02, /* Allow changes only if the acct is offline. */ ACC_SET_ONLINE_ONLY = 0x04, /* Allow changes only if the acct is online. */ } account_set_flag_t; -typedef enum -{ +typedef enum { ACC_FLAG_AWAY_MESSAGE = 0x01, /* Supports away messages instead of just states. */ ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */ ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */ diff --git a/protocols/bee.c b/protocols/bee.c index 887d1560..3a7dbbad 100644 --- a/protocols/bee.c +++ b/protocols/bee.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -26,71 +26,73 @@ #define BITLBEE_CORE #include "bitlbee.h" -static char *set_eval_away_status( set_t *set, char *value ); +static char *set_eval_away_status(set_t *set, char *value); bee_t *bee_new() { - bee_t *b = g_new0( bee_t, 1 ); + bee_t *b = g_new0(bee_t, 1); set_t *s; - - s = set_add( &b->set, "auto_connect", "true", set_eval_bool, b ); - s = set_add( &b->set, "auto_reconnect", "true", set_eval_bool, b ); - s = set_add( &b->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, b ); - s = set_add( &b->set, "away", NULL, set_eval_away_status, b ); + + s = set_add(&b->set, "auto_connect", "true", set_eval_bool, b); + s = set_add(&b->set, "auto_reconnect", "true", set_eval_bool, b); + s = set_add(&b->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, b); + s = set_add(&b->set, "away", NULL, set_eval_away_status, b); s->flags |= SET_NULL_OK | SET_HIDDEN; - s = set_add( &b->set, "debug", "false", set_eval_bool, b ); - s = set_add( &b->set, "mobile_is_away", "false", set_eval_bool, b ); - s = set_add( &b->set, "save_on_quit", "true", set_eval_bool, b ); - s = set_add( &b->set, "status", NULL, set_eval_away_status, b ); + s = set_add(&b->set, "debug", "false", set_eval_bool, b); + s = set_add(&b->set, "mobile_is_away", "false", set_eval_bool, b); + s = set_add(&b->set, "save_on_quit", "true", set_eval_bool, b); + s = set_add(&b->set, "status", NULL, set_eval_away_status, b); s->flags |= SET_NULL_OK; - s = set_add( &b->set, "strip_html", "true", NULL, b ); - - b->user = g_malloc( 1 ); - + s = set_add(&b->set, "strip_html", "true", NULL, b); + + b->user = g_malloc(1); + return b; } -void bee_free( bee_t *b ) +void bee_free(bee_t *b) { - while( b->accounts ) - { - if( b->accounts->ic ) - imc_logout( b->accounts->ic, FALSE ); - else if( b->accounts->reconnect ) - cancel_auto_reconnect( b->accounts ); - - if( b->accounts->ic == NULL ) - account_del( b, b->accounts ); - else + while (b->accounts) { + if (b->accounts->ic) { + imc_logout(b->accounts->ic, FALSE); + } else if (b->accounts->reconnect) { + cancel_auto_reconnect(b->accounts); + } + + if (b->accounts->ic == NULL) { + account_del(b, b->accounts); + } else { /* Nasty hack, but account_del() doesn't work in this case and we don't want infinite loops, do we? ;-) */ b->accounts = b->accounts->next; + } + } + + while (b->set) { + set_del(&b->set, b->set->key); } - - while( b->set ) - set_del( &b->set, b->set->key ); - - bee_group_free( b ); - - g_free( b->user ); - g_free( b ); + + bee_group_free(b); + + g_free(b->user); + g_free(b); } -static char *set_eval_away_status( set_t *set, char *value ) +static char *set_eval_away_status(set_t *set, char *value) { bee_t *bee = set->data; account_t *a; - - g_free( set->value ); - set->value = g_strdup( value ); - - for( a = bee->accounts; a; a = a->next ) - { + + g_free(set->value); + set->value = g_strdup(value); + + for (a = bee->accounts; a; a = a->next) { struct im_connection *ic = a->ic; - - if( ic && ic->flags & OPT_LOGGED_IN ) - imc_away_send_update( ic ); + + if (ic && ic->flags & OPT_LOGGED_IN) { + imc_away_send_update(ic); + } } - + return value; } diff --git a/protocols/bee.h b/protocols/bee.h index 567b8415..d90c3760 100644 --- a/protocols/bee.h +++ b/protocols/bee.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -29,35 +29,33 @@ struct bee_ui_funcs; struct groupchat; -typedef struct bee -{ +typedef struct bee { /* Settings. See set.h for how these work. The UI can add its own settings here. */ struct set *set; - + GSList *users; /* struct bee_user */ GSList *groups; /* struct bee_group */ struct account *accounts; /* TODO(wilmer): Use GSList here too? */ - + /* Symbolic, to refer to the local user (who has no real bee_user object). Not to be used by anything except so far imcb_chat_add/ remove_buddy(). */ struct bee_user *user; - + /* Fill in the callbacks for events you care about. */ const struct bee_ui_funcs *ui; - + /* And this one will be passed to every callback for any state the UI may want to keep. */ void *ui_data; } bee_t; bee_t *bee_new(); -void bee_free( bee_t *b ); +void bee_free(bee_t *b); /* TODO(wilmer): Kill at least the OPT_ flags that have an equivalent here. */ -typedef enum -{ +typedef enum { BEE_USER_ONLINE = 1, /* Compatibility with old OPT_LOGGED_IN flag */ BEE_USER_AWAY = 4, /* Compatibility with old OPT_AWAY flag */ BEE_USER_MOBILE = 8, /* Compatibility with old OPT_MOBILE flag */ @@ -65,8 +63,7 @@ typedef enum BEE_USER_SPECIAL = 512, /* Denotes a user as being special */ } bee_user_flags_t; -typedef struct bee_user -{ +typedef struct bee_user { struct im_connection *ic; char *handle; char *fullname; @@ -76,10 +73,10 @@ typedef struct bee_user bee_user_flags_t flags; char *status; /* NULL means available, anything else is an away state. */ char *status_msg; /* Status and/or away message. */ - + /* Set using imcb_buddy_times(). */ time_t login_time, idle_time; - + bee_t *bee; void *ui_data; void *data; /* Can be used by the IM module. */ @@ -87,64 +84,63 @@ typedef struct bee_user /* This one's mostly used so save space and make it easier (cheaper) to compare groups of contacts, etc. */ -typedef struct bee_group -{ +typedef struct bee_group { char *key; /* Lower case version of the name. */ char *name; } bee_group_t; -typedef struct bee_ui_funcs -{ - void (*imc_connected)( struct im_connection *ic ); - void (*imc_disconnected)( struct im_connection *ic ); - - gboolean (*user_new)( bee_t *bee, struct bee_user *bu ); - gboolean (*user_free)( bee_t *bee, struct bee_user *bu ); +typedef struct bee_ui_funcs { + void (*imc_connected)(struct im_connection *ic); + void (*imc_disconnected)(struct im_connection *ic); + + gboolean (*user_new)(bee_t *bee, struct bee_user *bu); + gboolean (*user_free)(bee_t *bee, struct bee_user *bu); /* Set the fullname first, then call this one to notify the UI. */ - gboolean (*user_fullname)( bee_t *bee, bee_user_t *bu ); - gboolean (*user_nick_hint)( bee_t *bee, bee_user_t *bu, const char *hint ); + gboolean (*user_fullname)(bee_t *bee, bee_user_t *bu); + gboolean (*user_nick_hint)(bee_t *bee, bee_user_t *bu, const char *hint); /* Notify the UI when an existing user is moved between groups. */ - gboolean (*user_group)( bee_t *bee, bee_user_t *bu ); + gboolean (*user_group)(bee_t *bee, bee_user_t *bu); /* State info is already updated, old is provided in case the UI needs a diff. */ - gboolean (*user_status)( bee_t *bee, struct bee_user *bu, struct bee_user *old ); + gboolean (*user_status)(bee_t *bee, struct bee_user *bu, struct bee_user *old); /* On every incoming message. sent_at = 0 means unknown. */ - gboolean (*user_msg)( bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at ); + gboolean (*user_msg)(bee_t *bee, bee_user_t *bu, const char *msg, time_t sent_at); /* Flags currently defined (OPT_TYPING/THINKING) in nogaim.h. */ - gboolean (*user_typing)( bee_t *bee, bee_user_t *bu, guint32 flags ); + gboolean (*user_typing)(bee_t *bee, bee_user_t *bu, guint32 flags); /* CTCP-like stuff (buddy action) response */ - gboolean (*user_action_response)( bee_t *bee, bee_user_t *bu, const char *action, char * const args[], void *data ); - + gboolean (*user_action_response)(bee_t *bee, bee_user_t *bu, const char *action, char * const args[], + void *data); + /* Called at creation time. Don't show to the user until s/he is added using chat_add_user(). UI state can be stored via c->data. */ - gboolean (*chat_new)( bee_t *bee, struct groupchat *c ); - gboolean (*chat_free)( bee_t *bee, struct groupchat *c ); + gboolean (*chat_new)(bee_t *bee, struct groupchat *c); + gboolean (*chat_free)(bee_t *bee, struct groupchat *c); /* System messages of any kind. */ - gboolean (*chat_log)( bee_t *bee, struct groupchat *c, const char *text ); - gboolean (*chat_msg)( bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at ); - gboolean (*chat_add_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu ); - gboolean (*chat_remove_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu ); - gboolean (*chat_topic)( bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu ); - gboolean (*chat_name_hint)( bee_t *bee, struct groupchat *c, const char *name ); - gboolean (*chat_invite)( bee_t *bee, bee_user_t *bu, const char *name, const char *msg ); - - struct file_transfer* (*ft_in_start)( bee_t *bee, bee_user_t *bu, const char *file_name, size_t file_size ); - gboolean (*ft_out_start)( struct im_connection *ic, struct file_transfer *ft ); - void (*ft_close)( struct im_connection *ic, struct file_transfer *ft ); - void (*ft_finished)( struct im_connection *ic, struct file_transfer *ft ); + gboolean (*chat_log)(bee_t *bee, struct groupchat *c, const char *text); + gboolean (*chat_msg)(bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at); + gboolean (*chat_add_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu); + gboolean (*chat_remove_user)(bee_t *bee, struct groupchat *c, bee_user_t *bu); + gboolean (*chat_topic)(bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu); + gboolean (*chat_name_hint)(bee_t *bee, struct groupchat *c, const char *name); + gboolean (*chat_invite)(bee_t *bee, bee_user_t *bu, const char *name, const char *msg); + + struct file_transfer* (*ft_in_start)(bee_t * bee, bee_user_t * bu, const char *file_name, size_t file_size); + gboolean (*ft_out_start)(struct im_connection *ic, struct file_transfer *ft); + void (*ft_close)(struct im_connection *ic, struct file_transfer *ft); + void (*ft_finished)(struct im_connection *ic, struct file_transfer *ft); } bee_ui_funcs_t; /* bee.c */ bee_t *bee_new(); -void bee_free( bee_t *b ); +void bee_free(bee_t *b); /* bee_user.c */ -bee_user_t *bee_user_new( bee_t *bee, struct im_connection *ic, const char *handle, bee_user_flags_t flags ); -int bee_user_free( bee_t *bee, bee_user_t *bu ); -bee_user_t *bee_user_by_handle( bee_t *bee, struct im_connection *ic, const char *handle ); -int bee_user_msg( bee_t *bee, bee_user_t *bu, const char *msg, int flags ); -bee_group_t *bee_group_by_name( bee_t *bee, const char *name, gboolean creat ); -void bee_group_free( bee_t *bee ); +bee_user_t *bee_user_new(bee_t *bee, struct im_connection *ic, const char *handle, bee_user_flags_t flags); +int bee_user_free(bee_t *bee, bee_user_t *bu); +bee_user_t *bee_user_by_handle(bee_t *bee, struct im_connection *ic, const char *handle); +int bee_user_msg(bee_t *bee, bee_user_t *bu, const char *msg, int flags); +bee_group_t *bee_group_by_name(bee_t *bee, const char *name, gboolean creat); +void bee_group_free(bee_t *bee); /* Callbacks from IM modules to core: */ /* Buddy activity */ @@ -152,33 +148,35 @@ void bee_group_free( bee_t *bee ); * - flags can be |='d with OPT_* constants. You will need at least: * OPT_LOGGED_IN and OPT_AWAY. * - 'state' and 'message' can be NULL */ -G_MODULE_EXPORT void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ); -G_MODULE_EXPORT void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message ); -G_MODULE_EXPORT void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ); +G_MODULE_EXPORT void imcb_buddy_status(struct im_connection *ic, const char *handle, int flags, const char *state, + const char *message); +G_MODULE_EXPORT void imcb_buddy_status_msg(struct im_connection *ic, const char *handle, const char *message); +G_MODULE_EXPORT void imcb_buddy_times(struct im_connection *ic, const char *handle, time_t login, time_t idle); /* Call when a handle says something. 'flags' and 'sent_at may be just 0. */ -G_MODULE_EXPORT void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, guint32 flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_buddy_msg(struct im_connection *ic, const char *handle, char *msg, guint32 flags, + time_t sent_at); /* bee_chat.c */ /* These two functions are to create a group chat. * - imcb_chat_new(): the 'handle' parameter identifies the chat, like the * channel name on IRC. - * - After you have a groupchat pointer, you should add the handles, finally + * - After you have a groupchat pointer, you should add the handles, finally * the user her/himself. At that point the group chat will be visible to the * user, too. */ -G_MODULE_EXPORT struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ); -G_MODULE_EXPORT void imcb_chat_name_hint( struct groupchat *c, const char *name ); -G_MODULE_EXPORT void imcb_chat_free( struct groupchat *c ); +G_MODULE_EXPORT struct groupchat *imcb_chat_new(struct im_connection *ic, const char *handle); +G_MODULE_EXPORT void imcb_chat_name_hint(struct groupchat *c, const char *name); +G_MODULE_EXPORT void imcb_chat_free(struct groupchat *c); /* To tell BitlBee 'who' said 'msg' in 'c'. 'flags' and 'sent_at' can be 0. */ -G_MODULE_EXPORT void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at ); +G_MODULE_EXPORT void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, guint32 flags, time_t sent_at); /* System messages specific to a groupchat, so they can be displayed in the right context. */ -G_MODULE_EXPORT void imcb_chat_log( struct groupchat *c, char *format, ... ); +G_MODULE_EXPORT void imcb_chat_log(struct groupchat *c, char *format, ...); /* To tell BitlBee 'who' changed the topic of 'c' to 'topic'. */ -G_MODULE_EXPORT void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ); -G_MODULE_EXPORT void imcb_chat_add_buddy( struct groupchat *c, const char *handle ); +G_MODULE_EXPORT void imcb_chat_topic(struct groupchat *c, char *who, char *topic, time_t set_at); +G_MODULE_EXPORT void imcb_chat_add_buddy(struct groupchat *c, const char *handle); /* To remove a handle from a group chat. Reason can be NULL. */ -G_MODULE_EXPORT void imcb_chat_remove_buddy( struct groupchat *c, const char *handle, const char *reason ); -G_MODULE_EXPORT int bee_chat_msg( bee_t *bee, struct groupchat *c, const char *msg, int flags ); -G_MODULE_EXPORT struct groupchat *bee_chat_by_title( bee_t *bee, struct im_connection *ic, const char *title ); -G_MODULE_EXPORT void imcb_chat_invite( struct im_connection *ic, const char *name, const char *who, const char *msg ); +G_MODULE_EXPORT void imcb_chat_remove_buddy(struct groupchat *c, const char *handle, const char *reason); +G_MODULE_EXPORT int bee_chat_msg(bee_t *bee, struct groupchat *c, const char *msg, int flags); +G_MODULE_EXPORT struct groupchat *bee_chat_by_title(bee_t *bee, struct im_connection *ic, const char *title); +G_MODULE_EXPORT void imcb_chat_invite(struct im_connection *ic, const char *name, const char *who, const char *msg); #endif /* __BEE_H__ */ diff --git a/protocols/bee_chat.c b/protocols/bee_chat.c index e1d07925..be193405 100644 --- a/protocols/bee_chat.c +++ b/protocols/bee_chat.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -26,230 +26,251 @@ #define BITLBEE_CORE #include "bitlbee.h" -struct groupchat *imcb_chat_new( struct im_connection *ic, const char *handle ) +struct groupchat *imcb_chat_new(struct im_connection *ic, const char *handle) { - struct groupchat *c = g_new0( struct groupchat, 1 ); + struct groupchat *c = g_new0(struct groupchat, 1); bee_t *bee = ic->bee; - + /* This one just creates the conversation structure, user won't see anything yet until s/he is joined to the conversation. (This allows you to add other already present participants first.) */ - - ic->groupchats = g_slist_prepend( ic->groupchats, c ); + + ic->groupchats = g_slist_prepend(ic->groupchats, c); c->ic = ic; - c->title = g_strdup( handle ); - c->topic = g_strdup_printf( "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", c->title ); - - if( set_getbool( &ic->bee->set, "debug" ) ) - imcb_log( ic, "Creating new conversation: (id=%p,handle=%s)", c, handle ); - - if( bee->ui->chat_new ) - bee->ui->chat_new( bee, c ); - + c->title = g_strdup(handle); + c->topic = g_strdup_printf( + "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", + c->title); + + if (set_getbool(&ic->bee->set, "debug")) { + imcb_log(ic, "Creating new conversation: (id=%p,handle=%s)", c, handle); + } + + if (bee->ui->chat_new) { + bee->ui->chat_new(bee, c); + } + return c; } -void imcb_chat_name_hint( struct groupchat *c, const char *name ) +void imcb_chat_name_hint(struct groupchat *c, const char *name) { bee_t *bee = c->ic->bee; - - if( bee->ui->chat_name_hint ) - bee->ui->chat_name_hint( bee, c, name ); + + if (bee->ui->chat_name_hint) { + bee->ui->chat_name_hint(bee, c, name); + } } -void imcb_chat_free( struct groupchat *c ) +void imcb_chat_free(struct groupchat *c) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; GList *ir; - - if( bee->ui->chat_free ) - bee->ui->chat_free( bee, c ); - - if( set_getbool( &ic->bee->set, "debug" ) ) - imcb_log( ic, "You were removed from conversation %p", c ); - - ic->groupchats = g_slist_remove( ic->groupchats, c ); - - for( ir = c->in_room; ir; ir = ir->next ) - g_free( ir->data ); - g_list_free( c->in_room ); - g_free( c->title ); - g_free( c->topic ); - g_free( c ); + + if (bee->ui->chat_free) { + bee->ui->chat_free(bee, c); + } + + if (set_getbool(&ic->bee->set, "debug")) { + imcb_log(ic, "You were removed from conversation %p", c); + } + + ic->groupchats = g_slist_remove(ic->groupchats, c); + + for (ir = c->in_room; ir; ir = ir->next) { + g_free(ir->data); + } + g_list_free(c->in_room); + g_free(c->title); + g_free(c->topic); + g_free(c); } -static gboolean handle_is_self( struct im_connection *ic, const char *handle ) +static gboolean handle_is_self(struct im_connection *ic, const char *handle) { - return ( ic->acc->prpl->handle_is_self ) ? - ic->acc->prpl->handle_is_self( ic, handle ) : - ( ic->acc->prpl->handle_cmp( ic->acc->user, handle ) == 0 ); + return (ic->acc->prpl->handle_is_self) ? + ic->acc->prpl->handle_is_self(ic, handle) : + (ic->acc->prpl->handle_cmp(ic->acc->user, handle) == 0); } -void imcb_chat_msg( struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at ) +void imcb_chat_msg(struct groupchat *c, const char *who, char *msg, uint32_t flags, time_t sent_at) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; bee_user_t *bu; gboolean temp; char *s; - + /* Gaim sends own messages through this too. IRC doesn't want this, so kill them */ - if( handle_is_self( ic, who ) ) + if (handle_is_self(ic, who)) { return; - - bu = bee_user_by_handle( bee, ic, who ); - temp = ( bu == NULL ); - - if( temp ) - bu = bee_user_new( bee, ic, who, BEE_USER_ONLINE ); - - s = set_getstr( &ic->bee->set, "strip_html" ); - if( ( g_strcasecmp( s, "always" ) == 0 ) || - ( ( ic->flags & OPT_DOES_HTML ) && s ) ) - strip_html( msg ); - - if( bee->ui->chat_msg ) - bee->ui->chat_msg( bee, c, bu, msg, sent_at ); - - if( temp ) - bee_user_free( bee, bu ); + } + + bu = bee_user_by_handle(bee, ic, who); + temp = (bu == NULL); + + if (temp) { + bu = bee_user_new(bee, ic, who, BEE_USER_ONLINE); + } + + s = set_getstr(&ic->bee->set, "strip_html"); + if ((g_strcasecmp(s, "always") == 0) || + ((ic->flags & OPT_DOES_HTML) && s)) { + strip_html(msg); + } + + if (bee->ui->chat_msg) { + bee->ui->chat_msg(bee, c, bu, msg, sent_at); + } + + if (temp) { + bee_user_free(bee, bu); + } } -void imcb_chat_log( struct groupchat *c, char *format, ... ) +void imcb_chat_log(struct groupchat *c, char *format, ...) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; va_list params; char *text; - - if( !bee->ui->chat_log ) + + if (!bee->ui->chat_log) { return; - - va_start( params, format ); - text = g_strdup_vprintf( format, params ); - va_end( params ); - - bee->ui->chat_log( bee, c, text ); - g_free( text ); + } + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + bee->ui->chat_log(bee, c, text); + g_free(text); } -void imcb_chat_topic( struct groupchat *c, char *who, char *topic, time_t set_at ) +void imcb_chat_topic(struct groupchat *c, char *who, char *topic, time_t set_at) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; bee_user_t *bu; - - if( !bee->ui->chat_topic ) + + if (!bee->ui->chat_topic) { return; - - if( who == NULL) + } + + if (who == NULL) { bu = NULL; - else if( handle_is_self( ic, who ) ) + } else if (handle_is_self(ic, who)) { bu = bee->user; - else - bu = bee_user_by_handle( bee, ic, who ); - - if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || - ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) - strip_html( topic ); - - bee->ui->chat_topic( bee, c, topic, bu ); + } else { + bu = bee_user_by_handle(bee, ic, who); + } + + if ((g_strcasecmp(set_getstr(&ic->bee->set, "strip_html"), "always") == 0) || + ((ic->flags & OPT_DOES_HTML) && set_getbool(&ic->bee->set, "strip_html"))) { + strip_html(topic); + } + + bee->ui->chat_topic(bee, c, topic, bu); } -void imcb_chat_add_buddy( struct groupchat *c, const char *handle ) +void imcb_chat_add_buddy(struct groupchat *c, const char *handle) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; - bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); + bee_user_t *bu = bee_user_by_handle(bee, ic, handle); gboolean me; - - if( set_getbool( &c->ic->bee->set, "debug" ) ) - imcb_log( c->ic, "User %s added to conversation %p", handle, c ); - - me = handle_is_self( ic, handle ); - + + if (set_getbool(&c->ic->bee->set, "debug")) { + imcb_log(c->ic, "User %s added to conversation %p", handle, c); + } + + me = handle_is_self(ic, handle); + /* Most protocols allow people to join, even when they're not in your contact list. Try to handle that here */ - if( !me && !bu ) - bu = bee_user_new( bee, ic, handle, BEE_USER_LOCAL ); - + if (!me && !bu) { + bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL); + } + /* Add the handle to the room userlist */ /* TODO: Use bu instead of a string */ - c->in_room = g_list_append( c->in_room, g_strdup( handle ) ); - - if( bee->ui->chat_add_user ) - bee->ui->chat_add_user( bee, c, me ? bee->user : bu ); - - if( me ) + c->in_room = g_list_append(c->in_room, g_strdup(handle)); + + if (bee->ui->chat_add_user) { + bee->ui->chat_add_user(bee, c, me ? bee->user : bu); + } + + if (me) { c->joined = 1; + } } -void imcb_chat_remove_buddy( struct groupchat *c, const char *handle, const char *reason ) +void imcb_chat_remove_buddy(struct groupchat *c, const char *handle, const char *reason) { struct im_connection *ic = c->ic; bee_t *bee = ic->bee; bee_user_t *bu = NULL; - - if( set_getbool( &bee->set, "debug" ) ) - imcb_log( ic, "User %s removed from conversation %p (%s)", handle, c, reason ? reason : "" ); - + + if (set_getbool(&bee->set, "debug")) { + imcb_log(ic, "User %s removed from conversation %p (%s)", handle, c, reason ? reason : ""); + } + /* It might be yourself! */ - if( handle_is_self( ic, handle ) ) - { - if( c->joined == 0 ) + if (handle_is_self(ic, handle)) { + if (c->joined == 0) { return; - + } + bu = bee->user; c->joined = 0; + } else { + bu = bee_user_by_handle(bee, ic, handle); } - else - { - bu = bee_user_by_handle( bee, ic, handle ); + + if (bee->ui->chat_remove_user && bu) { + bee->ui->chat_remove_user(bee, c, bu); } - - if( bee->ui->chat_remove_user && bu ) - bee->ui->chat_remove_user( bee, c, bu ); } -int bee_chat_msg( bee_t *bee, struct groupchat *c, const char *msg, int flags ) +int bee_chat_msg(bee_t *bee, struct groupchat *c, const char *msg, int flags) { struct im_connection *ic = c->ic; char *buf = NULL; - - if( ( ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) - { - buf = escape_html( msg ); + + if ((ic->flags & OPT_DOES_HTML) && (g_strncasecmp(msg, "<html>", 6) != 0)) { + buf = escape_html(msg); msg = buf; + } else { + buf = g_strdup(msg); } - else - buf = g_strdup( msg ); - - ic->acc->prpl->chat_msg( c, buf, flags ); - g_free( buf ); - + + ic->acc->prpl->chat_msg(c, buf, flags); + g_free(buf); + return 1; } -struct groupchat *bee_chat_by_title( bee_t *bee, struct im_connection *ic, const char *title ) +struct groupchat *bee_chat_by_title(bee_t *bee, struct im_connection *ic, const char *title) { struct groupchat *c; GSList *l; - - for( l = ic->groupchats; l; l = l->next ) - { + + for (l = ic->groupchats; l; l = l->next) { c = l->data; - if( strcmp( c->title, title ) == 0 ) + if (strcmp(c->title, title) == 0) { return c; + } } - + return NULL; } -void imcb_chat_invite( struct im_connection *ic, const char *name, const char *who, const char *msg ) +void imcb_chat_invite(struct im_connection *ic, const char *name, const char *who, const char *msg) { - bee_user_t *bu = bee_user_by_handle( ic->bee, ic, who ); - - if( bu && ic->bee->ui->chat_invite ) - ic->bee->ui->chat_invite( ic->bee, bu, name, msg ); + bee_user_t *bu = bee_user_by_handle(ic->bee, ic, who); + + if (bu && ic->bee->ui->chat_invite) { + ic->bee->ui->chat_invite(ic->bee, bu, name, msg); + } } diff --git a/protocols/bee_ft.c b/protocols/bee_ft.c index 71299e99..27fd4eac 100644 --- a/protocols/bee_ft.c +++ b/protocols/bee_ft.c @@ -25,42 +25,47 @@ #include "bitlbee.h" #include "ft.h" -file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *handle, char *file_name, size_t file_size ) +file_transfer_t *imcb_file_send_start(struct im_connection *ic, char *handle, char *file_name, size_t file_size) { - bee_t *bee = ic->bee; - bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); - - if( bee->ui->ft_in_start ) - return bee->ui->ft_in_start( bee, bu, file_name, file_size ); - else + bee_t *bee = ic->bee; + bee_user_t *bu = bee_user_by_handle(bee, ic, handle); + + if (bee->ui->ft_in_start) { + return bee->ui->ft_in_start(bee, bu, file_name, file_size); + } else { return NULL; + } } -gboolean imcb_file_recv_start( struct im_connection *ic, file_transfer_t *ft ) +gboolean imcb_file_recv_start(struct im_connection *ic, file_transfer_t *ft) { bee_t *bee = ic->bee; - - if( bee->ui->ft_out_start ) - return bee->ui->ft_out_start( ic, ft ); - else + + if (bee->ui->ft_out_start) { + return bee->ui->ft_out_start(ic, ft); + } else { return FALSE; + } } -void imcb_file_canceled( struct im_connection *ic, file_transfer_t *file, char *reason ) +void imcb_file_canceled(struct im_connection *ic, file_transfer_t *file, char *reason) { bee_t *bee = ic->bee; - - if( file->canceled ) - file->canceled( file, reason ); - - if( bee->ui->ft_close ) - bee->ui->ft_close( ic, file ); + + if (file->canceled) { + file->canceled(file, reason); + } + + if (bee->ui->ft_close) { + bee->ui->ft_close(ic, file); + } } -void imcb_file_finished( struct im_connection *ic, file_transfer_t *file ) +void imcb_file_finished(struct im_connection *ic, file_transfer_t *file) { bee_t *bee = ic->bee; - - if( bee->ui->ft_finished ) - bee->ui->ft_finished( ic, file ); + + if (bee->ui->ft_finished) { + bee->ui->ft_finished(ic, file); + } } diff --git a/protocols/bee_user.c b/protocols/bee_user.c index 4169744f..ea1be3db 100644 --- a/protocols/bee_user.c +++ b/protocols/bee_user.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -26,263 +26,263 @@ #define BITLBEE_CORE #include "bitlbee.h" -bee_user_t *bee_user_new( bee_t *bee, struct im_connection *ic, const char *handle, bee_user_flags_t flags ) +bee_user_t *bee_user_new(bee_t *bee, struct im_connection *ic, const char *handle, bee_user_flags_t flags) { bee_user_t *bu; - - if( bee_user_by_handle( bee, ic, handle ) != NULL ) + + if (bee_user_by_handle(bee, ic, handle) != NULL) { return NULL; - - bu = g_new0( bee_user_t, 1 ); + } + + bu = g_new0(bee_user_t, 1); bu->bee = bee; bu->ic = ic; bu->flags = flags; - bu->handle = g_strdup( handle ); - bee->users = g_slist_prepend( bee->users, bu ); - - if( bee->ui->user_new ) - bee->ui->user_new( bee, bu ); - if( ic->acc->prpl->buddy_data_add ) - ic->acc->prpl->buddy_data_add( bu ); - + bu->handle = g_strdup(handle); + bee->users = g_slist_prepend(bee->users, bu); + + if (bee->ui->user_new) { + bee->ui->user_new(bee, bu); + } + if (ic->acc->prpl->buddy_data_add) { + ic->acc->prpl->buddy_data_add(bu); + } + /* Offline by default. This will set the right flags. */ - imcb_buddy_status( ic, handle, 0, NULL, NULL ); - + imcb_buddy_status(ic, handle, 0, NULL, NULL); + return bu; } -int bee_user_free( bee_t *bee, bee_user_t *bu ) +int bee_user_free(bee_t *bee, bee_user_t *bu) { - if( !bu ) + if (!bu) { return 0; - - if( bee->ui->user_free ) - bee->ui->user_free( bee, bu ); - if( bu->ic->acc->prpl->buddy_data_free ) - bu->ic->acc->prpl->buddy_data_free( bu ); - - g_free( bu->handle ); - g_free( bu->fullname ); - g_free( bu->nick ); - g_free( bu->status ); - g_free( bu->status_msg ); - g_free( bu ); - - bee->users = g_slist_remove( bee->users, bu ); - + } + + if (bee->ui->user_free) { + bee->ui->user_free(bee, bu); + } + if (bu->ic->acc->prpl->buddy_data_free) { + bu->ic->acc->prpl->buddy_data_free(bu); + } + + g_free(bu->handle); + g_free(bu->fullname); + g_free(bu->nick); + g_free(bu->status); + g_free(bu->status_msg); + g_free(bu); + + bee->users = g_slist_remove(bee->users, bu); + return 1; } -bee_user_t *bee_user_by_handle( bee_t *bee, struct im_connection *ic, const char *handle ) +bee_user_t *bee_user_by_handle(bee_t *bee, struct im_connection *ic, const char *handle) { GSList *l; - - for( l = bee->users; l; l = l->next ) - { + + for (l = bee->users; l; l = l->next) { bee_user_t *bu = l->data; - - if( bu->ic == ic && ic->acc->prpl->handle_cmp( bu->handle, handle ) == 0 ) + + if (bu->ic == ic && ic->acc->prpl->handle_cmp(bu->handle, handle) == 0) { return bu; + } } - + return NULL; } -int bee_user_msg( bee_t *bee, bee_user_t *bu, const char *msg, int flags ) +int bee_user_msg(bee_t *bee, bee_user_t *bu, const char *msg, int flags) { char *buf = NULL; int st; - - if( ( bu->ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) - { - buf = escape_html( msg ); + + if ((bu->ic->flags & OPT_DOES_HTML) && (g_strncasecmp(msg, "<html>", 6) != 0)) { + buf = escape_html(msg); msg = buf; + } else { + buf = g_strdup(msg); } - else - buf = g_strdup( msg ); - - st = bu->ic->acc->prpl->buddy_msg( bu->ic, bu->handle, buf, flags ); - g_free( buf ); - + + st = bu->ic->acc->prpl->buddy_msg(bu->ic, bu->handle, buf, flags); + g_free(buf); + return st; } /* Groups */ -static bee_group_t *bee_group_new( bee_t *bee, const char *name ) +static bee_group_t *bee_group_new(bee_t *bee, const char *name) { - bee_group_t *bg = g_new0( bee_group_t, 1 ); - - bg->name = g_strdup( name ); - bg->key = g_utf8_casefold( name, -1 ); - bee->groups = g_slist_prepend( bee->groups, bg ); - + bee_group_t *bg = g_new0(bee_group_t, 1); + + bg->name = g_strdup(name); + bg->key = g_utf8_casefold(name, -1); + bee->groups = g_slist_prepend(bee->groups, bg); + return bg; } -bee_group_t *bee_group_by_name( bee_t *bee, const char *name, gboolean creat ) +bee_group_t *bee_group_by_name(bee_t *bee, const char *name, gboolean creat) { GSList *l; char *key; - - if( name == NULL ) + + if (name == NULL) { return NULL; - - key = g_utf8_casefold( name, -1 ); - for( l = bee->groups; l; l = l->next ) - { + } + + key = g_utf8_casefold(name, -1); + for (l = bee->groups; l; l = l->next) { bee_group_t *bg = l->data; - if( strcmp( bg->key, key ) == 0 ) + if (strcmp(bg->key, key) == 0) { break; + } } - g_free( key ); - - if( !l ) - return creat ? bee_group_new( bee, name ) : NULL; - else + g_free(key); + + if (!l) { + return creat ? bee_group_new(bee, name) : NULL; + } else { return l->data; + } } -void bee_group_free( bee_t *bee ) +void bee_group_free(bee_t *bee) { - while( bee->groups ) - { + while (bee->groups) { bee_group_t *bg = bee->groups->data; - g_free( bg->name ); - g_free( bg->key ); - g_free( bg ); - bee->groups = g_slist_remove( bee->groups, bee->groups->data ); + g_free(bg->name); + g_free(bg->key); + g_free(bg); + bee->groups = g_slist_remove(bee->groups, bee->groups->data); } } /* IM->UI callbacks */ -void imcb_buddy_status( struct im_connection *ic, const char *handle, int flags, const char *state, const char *message ) +void imcb_buddy_status(struct im_connection *ic, const char *handle, int flags, const char *state, const char *message) { bee_t *bee = ic->bee; bee_user_t *bu, *old; - - if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) - { - if( g_strcasecmp( set_getstr( &ic->bee->set, "handle_unknown" ), "add" ) == 0 ) - { - bu = bee_user_new( bee, ic, handle, BEE_USER_LOCAL ); - } - else - { - if( g_strcasecmp( set_getstr( &ic->bee->set, "handle_unknown" ), "ignore" ) != 0 ) - { - imcb_log( ic, "imcb_buddy_status() for unknown handle %s:\n" - "flags = %d, state = %s, message = %s", handle, flags, - state ? state : "NULL", message ? message : "NULL" ); + + if (!(bu = bee_user_by_handle(bee, ic, handle))) { + if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "add") == 0) { + bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL); + } else { + if (g_strcasecmp(set_getstr(&ic->bee->set, "handle_unknown"), "ignore") != 0) { + imcb_log(ic, "imcb_buddy_status() for unknown handle %s:\n" + "flags = %d, state = %s, message = %s", handle, flags, + state ? state : "NULL", message ? message : "NULL"); } - + return; } } - + /* May be nice to give the UI something to compare against. */ - old = g_memdup( bu, sizeof( bee_user_t ) ); - + old = g_memdup(bu, sizeof(bee_user_t)); + /* TODO(wilmer): OPT_AWAY, or just state == NULL ? */ bu->flags = flags; - bu->status_msg = g_strdup( message ); - if( state && *state ) - bu->status = g_strdup( state ); - else if( flags & OPT_AWAY ) - bu->status = g_strdup( "Away" ); - else + bu->status_msg = g_strdup(message); + if (state && *state) { + bu->status = g_strdup(state); + } else if (flags & OPT_AWAY) { + bu->status = g_strdup("Away"); + } else { bu->status = NULL; - - if( bu->status == NULL && ( flags & OPT_MOBILE ) && - set_getbool( &bee->set, "mobile_is_away" ) ) - { + } + + if (bu->status == NULL && (flags & OPT_MOBILE) && + set_getbool(&bee->set, "mobile_is_away")) { bu->flags |= BEE_USER_AWAY; - bu->status = g_strdup( "Mobile" ); + bu->status = g_strdup("Mobile"); + } + + if (bee->ui->user_status) { + bee->ui->user_status(bee, bu, old); } - - if( bee->ui->user_status ) - bee->ui->user_status( bee, bu, old ); - - g_free( old->status_msg ); - g_free( old->status ); - g_free( old ); + + g_free(old->status_msg); + g_free(old->status); + g_free(old); } /* Same, but only change the away/status message, not any away/online state info. */ -void imcb_buddy_status_msg( struct im_connection *ic, const char *handle, const char *message ) +void imcb_buddy_status_msg(struct im_connection *ic, const char *handle, const char *message) { bee_t *bee = ic->bee; bee_user_t *bu, *old; - - if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) - { + + if (!(bu = bee_user_by_handle(bee, ic, handle))) { return; } - - old = g_memdup( bu, sizeof( bee_user_t ) ); - - bu->status_msg = message && *message ? g_strdup( message ) : NULL; - - if( bee->ui->user_status ) - bee->ui->user_status( bee, bu, old ); - - g_free( old->status_msg ); - g_free( old ); + + old = g_memdup(bu, sizeof(bee_user_t)); + + bu->status_msg = message && *message ? g_strdup(message) : NULL; + + if (bee->ui->user_status) { + bee->ui->user_status(bee, bu, old); + } + + g_free(old->status_msg); + g_free(old); } -void imcb_buddy_times( struct im_connection *ic, const char *handle, time_t login, time_t idle ) +void imcb_buddy_times(struct im_connection *ic, const char *handle, time_t login, time_t idle) { bee_t *bee = ic->bee; bee_user_t *bu; - - if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) + + if (!(bu = bee_user_by_handle(bee, ic, handle))) { return; - + } + bu->login_time = login; bu->idle_time = idle; } -void imcb_buddy_msg( struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at ) +void imcb_buddy_msg(struct im_connection *ic, const char *handle, char *msg, uint32_t flags, time_t sent_at) { bee_t *bee = ic->bee; bee_user_t *bu; - - bu = bee_user_by_handle( bee, ic, handle ); - - if( !bu && !( ic->flags & OPT_LOGGING_OUT ) ) - { - char *h = set_getstr( &bee->set, "handle_unknown" ); - - if( g_strcasecmp( h, "ignore" ) == 0 ) - { + + bu = bee_user_by_handle(bee, ic, handle); + + if (!bu && !(ic->flags & OPT_LOGGING_OUT)) { + char *h = set_getstr(&bee->set, "handle_unknown"); + + if (g_strcasecmp(h, "ignore") == 0) { return; - } - else if( g_strncasecmp( h, "add", 3 ) == 0 ) - { - bu = bee_user_new( bee, ic, handle, BEE_USER_LOCAL ); + } else if (g_strncasecmp(h, "add", 3) == 0) { + bu = bee_user_new(bee, ic, handle, BEE_USER_LOCAL); } } - - if( bee->ui->user_msg && bu ) - bee->ui->user_msg( bee, bu, msg, sent_at ); - else - imcb_log( ic, "Message from unknown handle %s:\n%s", handle, msg ); + + if (bee->ui->user_msg && bu) { + bee->ui->user_msg(bee, bu, msg, sent_at); + } else { + imcb_log(ic, "Message from unknown handle %s:\n%s", handle, msg); + } } -void imcb_buddy_typing( struct im_connection *ic, const char *handle, uint32_t flags ) +void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags) { bee_user_t *bu; - - if( ic->bee->ui->user_typing && - ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) ) - { - ic->bee->ui->user_typing( ic->bee, bu, flags ); + + if (ic->bee->ui->user_typing && + (bu = bee_user_by_handle(ic->bee, ic, handle))) { + ic->bee->ui->user_typing(ic->bee, bu, flags); } } -void imcb_buddy_action_response( bee_user_t *bu, const char *action, char * const args[], void *data ) +void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data) { - if( bu->bee->ui->user_action_response ) - bu->bee->ui->user_action_response( bu->bee, bu, action, args, data ); + if (bu->bee->ui->user_action_response) { + bu->bee->ui->user_action_response(bu->bee, bu, action, args, data); + } } diff --git a/protocols/ft.h b/protocols/ft.h index 65877c7d..fd6ef92a 100644 --- a/protocols/ft.h +++ b/protocols/ft.h @@ -34,11 +34,11 @@ #define FT_BUFFER_SIZE 2048 typedef enum { - FT_STATUS_LISTENING = 1, - FT_STATUS_TRANSFERRING = 2, - FT_STATUS_FINISHED = 4, - FT_STATUS_CANCELED = 8, - FT_STATUS_CONNECTING = 16 + FT_STATUS_LISTENING = 1, + FT_STATUS_TRANSFERRING = 2, + FT_STATUS_FINISHED = 4, + FT_STATUS_CANCELED = 8, + FT_STATUS_CONNECTING = 16 } file_status_t; /* @@ -74,14 +74,14 @@ typedef struct file_transfer { /* * The current status of this file transfer. - */ + */ file_status_t status; - + /* * file size */ size_t file_size; - + /* * Number of bytes that have been successfully transferred. */ @@ -107,42 +107,42 @@ typedef struct file_transfer { */ gpointer data; struct im_connection *ic; - + /* * Private data. */ gpointer priv; - + /* * If set, called after succesful connection setup. */ - void (*accept) ( struct file_transfer *file ); - + void (*accept)(struct file_transfer *file); + /* * If set, called when the transfer is canceled or finished. * Subsequently, this structure will be freed. * */ - void (*free) ( struct file_transfer *file ); - + void (*free)(struct file_transfer *file); + /* * If set, called when the transfer is finished and successful. */ - void (*finished) ( struct file_transfer *file ); - + void (*finished)(struct file_transfer *file); + /* * If set, called when the transfer is canceled. * ( canceled either by the transfer implementation or by * a call to imcb_file_canceled ) */ - void (*canceled) ( struct file_transfer *file, char *reason ); - + void (*canceled)(struct file_transfer *file, char *reason); + /* * called by the sending side to indicate that it is writable. - * The callee should check if data is available and call the + * The callee should check if data is available and call the * function(as seen below) if that is the case. */ - gboolean (*write_request) ( struct file_transfer *file ); + gboolean (*write_request)(struct file_transfer *file); /* * When sending files, protocols register this function to receive data. @@ -150,7 +150,7 @@ typedef struct file_transfer { * should not read more data until write_request is called again. This technique * avoids buffering. */ - gboolean (*write) (struct file_transfer *file, char *buffer, unsigned int len ); + gboolean (*write)(struct file_transfer *file, char *buffer, unsigned int len); /* The send buffer associated with this transfer. * Since receivers always wait for a write_request call one is enough. @@ -162,15 +162,15 @@ typedef struct file_transfer { /* * This starts a file transfer from bitlbee to the user. */ -file_transfer_t *imcb_file_send_start( struct im_connection *ic, char *user_nick, char *file_name, size_t file_size ); +file_transfer_t *imcb_file_send_start(struct im_connection *ic, char *user_nick, char *file_name, size_t file_size); /* * This should be called by a protocol when the transfer is canceled. Note that * the canceled() and free() callbacks given in file will be called by this function. */ -void imcb_file_canceled( struct im_connection *ic, file_transfer_t *file, char *reason ); +void imcb_file_canceled(struct im_connection *ic, file_transfer_t *file, char *reason); -gboolean imcb_file_recv_start( struct im_connection *ic, file_transfer_t *ft ); +gboolean imcb_file_recv_start(struct im_connection *ic, file_transfer_t *ft); -void imcb_file_finished( struct im_connection *ic, file_transfer_t *file ); +void imcb_file_finished(struct im_connection *ic, file_transfer_t *file); #endif diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index c8930f83..7435358a 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -24,51 +24,50 @@ #include "jabber.h" #include "sha1.h" -static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -struct groupchat *jabber_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password ) +struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password) { struct jabber_chat *jc; struct xt_node *node; struct groupchat *c; char *roomjid; - - roomjid = g_strdup_printf( "%s/%s", room, nick ); - node = xt_new_node( "x", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_MUC ); - if( password ) - xt_add_child( node, xt_new_node( "password", password, NULL ) ); - node = jabber_make_packet( "presence", NULL, roomjid, node ); - jabber_cache_add( ic, node, jabber_chat_join_failed ); - - if( !jabber_write_packet( ic, node ) ) - { - g_free( roomjid ); + + roomjid = g_strdup_printf("%s/%s", room, nick); + node = xt_new_node("x", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_MUC); + if (password) { + xt_add_child(node, xt_new_node("password", password, NULL)); + } + node = jabber_make_packet("presence", NULL, roomjid, node); + jabber_cache_add(ic, node, jabber_chat_join_failed); + + if (!jabber_write_packet(ic, node)) { + g_free(roomjid); return NULL; } - - jc = g_new0( struct jabber_chat, 1 ); - jc->name = jabber_normalize( room ); - - if( ( jc->me = jabber_buddy_add( ic, roomjid ) ) == NULL ) - { - g_free( roomjid ); - g_free( jc->name ); - g_free( jc ); + + jc = g_new0(struct jabber_chat, 1); + jc->name = jabber_normalize(room); + + if ((jc->me = jabber_buddy_add(ic, roomjid)) == NULL) { + g_free(roomjid); + g_free(jc->name); + g_free(jc); return NULL; } - + /* roomjid isn't normalized yet, and we need an original version of the nick to send a proper presence update. */ jc->my_full_jid = roomjid; - - c = imcb_chat_new( ic, room ); + + c = imcb_chat_new(ic, room); c->data = jc; - + return c; } -struct groupchat *jabber_chat_with( struct im_connection *ic, char *who ) +struct groupchat *jabber_chat_with(struct im_connection *ic, char *who) { struct jabber_data *jd = ic->proto_data; struct jabber_chat *jc; @@ -76,357 +75,356 @@ struct groupchat *jabber_chat_with( struct im_connection *ic, char *who ) sha1_state_t sum; double now = gettime(); char *uuid, *rjid, *cserv; - - sha1_init( &sum ); - sha1_append( &sum, (uint8_t*) ic->acc->user, strlen( ic->acc->user ) ); - sha1_append( &sum, (uint8_t*) &now, sizeof( now ) ); - sha1_append( &sum, (uint8_t*) who, strlen( who ) ); - uuid = sha1_random_uuid( &sum ); - - if( jd->flags & JFLAG_GTALK ) - cserv = g_strdup( "groupchat.google.com" ); - else + + sha1_init(&sum); + sha1_append(&sum, (uint8_t *) ic->acc->user, strlen(ic->acc->user)); + sha1_append(&sum, (uint8_t *) &now, sizeof(now)); + sha1_append(&sum, (uint8_t *) who, strlen(who)); + uuid = sha1_random_uuid(&sum); + + if (jd->flags & JFLAG_GTALK) { + cserv = g_strdup("groupchat.google.com"); + } else { /* Guess... */ - cserv = g_strdup_printf( "conference.%s", jd->server ); - - rjid = g_strdup_printf( "private-chat-%s@%s", uuid, cserv ); - g_free( uuid ); - g_free( cserv ); - - c = jabber_chat_join( ic, rjid, jd->username, NULL ); - g_free( rjid ); - if( c == NULL ) + cserv = g_strdup_printf("conference.%s", jd->server); + } + + rjid = g_strdup_printf("private-chat-%s@%s", uuid, cserv); + g_free(uuid); + g_free(cserv); + + c = jabber_chat_join(ic, rjid, jd->username, NULL); + g_free(rjid); + if (c == NULL) { return NULL; - + } + jc = c->data; - jc->invite = g_strdup( who ); - + jc->invite = g_strdup(who); + return c; } -static xt_status jabber_chat_join_failed( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_chat_join_failed(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct jabber_error *err; struct jabber_buddy *bud; char *room; - - room = xt_find_attr( orig, "to" ); - bud = jabber_buddy_by_jid( ic, room, 0 ); - err = jabber_error_parse( xt_find_node( node->children, "error" ), XMLNS_STANZA_ERROR ); - if( err ) - { - imcb_error( ic, "Error joining groupchat %s: %s%s%s", room, err->code, - err->text ? ": " : "", err->text ? err->text : "" ); - jabber_error_free( err ); + + room = xt_find_attr(orig, "to"); + bud = jabber_buddy_by_jid(ic, room, 0); + err = jabber_error_parse(xt_find_node(node->children, "error"), XMLNS_STANZA_ERROR); + if (err) { + imcb_error(ic, "Error joining groupchat %s: %s%s%s", room, err->code, + err->text ? ": " : "", err->text ? err->text : ""); + jabber_error_free(err); } - if( bud ) - jabber_chat_free( jabber_chat_by_jid( ic, bud->bare_jid ) ); - + if (bud) { + jabber_chat_free(jabber_chat_by_jid(ic, bud->bare_jid)); + } + return XT_HANDLED; } -struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name ) +struct groupchat *jabber_chat_by_jid(struct im_connection *ic, const char *name) { - char *normalized = jabber_normalize( name ); + char *normalized = jabber_normalize(name); GSList *l; struct groupchat *ret; struct jabber_chat *jc; - - for( l = ic->groupchats; l; l = l->next ) - { + + for (l = ic->groupchats; l; l = l->next) { ret = l->data; jc = ret->data; - if( strcmp( normalized, jc->name ) == 0 ) + if (strcmp(normalized, jc->name) == 0) { break; + } } - g_free( normalized ); - + g_free(normalized); + return l ? ret : NULL; } -void jabber_chat_free( struct groupchat *c ) +void jabber_chat_free(struct groupchat *c) { struct jabber_chat *jc = c->data; - - jabber_buddy_remove_bare( c->ic, jc->name ); - - g_free( jc->my_full_jid ); - g_free( jc->name ); - g_free( jc->invite ); - g_free( jc ); - - imcb_chat_free( c ); + + jabber_buddy_remove_bare(c->ic, jc->name); + + g_free(jc->my_full_jid); + g_free(jc->name); + g_free(jc->invite); + g_free(jc); + + imcb_chat_free(c); } -int jabber_chat_msg( struct groupchat *c, char *message, int flags ) +int jabber_chat_msg(struct groupchat *c, char *message, int flags) { struct im_connection *ic = c->ic; struct jabber_chat *jc = c->data; struct xt_node *node; - + jc->flags |= JCFLAG_MESSAGE_SENT; - - node = xt_new_node( "body", message, NULL ); - node = jabber_make_packet( "message", "groupchat", jc->name, node ); - - if( !jabber_write_packet( ic, node ) ) - { - xt_free_node( node ); + + node = xt_new_node("body", message, NULL); + node = jabber_make_packet("message", "groupchat", jc->name, node); + + if (!jabber_write_packet(ic, node)) { + xt_free_node(node); return 0; } - xt_free_node( node ); - + xt_free_node(node); + return 1; } -int jabber_chat_topic( struct groupchat *c, char *topic ) +int jabber_chat_topic(struct groupchat *c, char *topic) { struct im_connection *ic = c->ic; struct jabber_chat *jc = c->data; struct xt_node *node; - - node = xt_new_node( "subject", topic, NULL ); - node = jabber_make_packet( "message", "groupchat", jc->name, node ); - - if( !jabber_write_packet( ic, node ) ) - { - xt_free_node( node ); + + node = xt_new_node("subject", topic, NULL); + node = jabber_make_packet("message", "groupchat", jc->name, node); + + if (!jabber_write_packet(ic, node)) { + xt_free_node(node); return 0; } - xt_free_node( node ); - + xt_free_node(node); + return 1; } -int jabber_chat_leave( struct groupchat *c, const char *reason ) +int jabber_chat_leave(struct groupchat *c, const char *reason) { struct im_connection *ic = c->ic; struct jabber_chat *jc = c->data; struct xt_node *node; - - node = xt_new_node( "x", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_MUC ); - node = jabber_make_packet( "presence", "unavailable", jc->my_full_jid, node ); - - if( !jabber_write_packet( ic, node ) ) - { - xt_free_node( node ); + + node = xt_new_node("x", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_MUC); + node = jabber_make_packet("presence", "unavailable", jc->my_full_jid, node); + + if (!jabber_write_packet(ic, node)) { + xt_free_node(node); return 0; } - xt_free_node( node ); - + xt_free_node(node); + return 1; } -void jabber_chat_invite( struct groupchat *c, char *who, char *message ) +void jabber_chat_invite(struct groupchat *c, char *who, char *message) { struct xt_node *node; struct im_connection *ic = c->ic; struct jabber_chat *jc = c->data; - node = xt_new_node( "reason", message, NULL ); + node = xt_new_node("reason", message, NULL); + + node = xt_new_node("invite", NULL, node); + xt_add_attr(node, "to", who); - node = xt_new_node( "invite", NULL, node ); - xt_add_attr( node, "to", who ); + node = xt_new_node("x", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_MUC_USER); - node = xt_new_node( "x", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_MUC_USER ); - - node = jabber_make_packet( "message", NULL, jc->name, node ); + node = jabber_make_packet("message", NULL, jc->name, node); - jabber_write_packet( ic, node ); + jabber_write_packet(ic, node); - xt_free_node( node ); + xt_free_node(node); } /* Not really the same syntax as the normal pkt_ functions, but this isn't called by the xmltree parser directly and this way I can add some extra parameters so we won't have to repeat too many things done by the caller already. */ -void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) +void jabber_chat_pkt_presence(struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node) { struct groupchat *chat; struct xt_node *c; - char *type = xt_find_attr( node, "type" ); + char *type = xt_find_attr(node, "type"); struct jabber_data *jd = ic->proto_data; struct jabber_chat *jc; char *s; - - if( ( chat = jabber_chat_by_jid( ic, bud->bare_jid ) ) == NULL ) - { + + if ((chat = jabber_chat_by_jid(ic, bud->bare_jid)) == NULL) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ return; } - + jc = chat->data; - - if( type == NULL && !( bud->flags & JBFLAG_IS_CHATROOM ) ) - { + + if (type == NULL && !(bud->flags & JBFLAG_IS_CHATROOM)) { bud->flags |= JBFLAG_IS_CHATROOM; /* If this one wasn't set yet, this buddy just joined the chat. Slightly hackish way of finding out eh? ;-) */ - + /* This is pretty messy... Here it sets ext_jid to the real JID of the participant. Works for non-anonymized channels. Might break if someone joins a chat twice, though. */ - for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) - if( ( s = xt_find_attr( c, "xmlns" ) ) && - ( strcmp( s, XMLNS_MUC_USER ) == 0 ) ) - { + for (c = node->children; (c = xt_find_node(c, "x")); c = c->next) { + if ((s = xt_find_attr(c, "xmlns")) && + (strcmp(s, XMLNS_MUC_USER) == 0)) { struct xt_node *item; - - item = xt_find_node( c->children, "item" ); - if( ( s = xt_find_attr( item, "jid" ) ) ) - { + + item = xt_find_node(c->children, "item"); + if ((s = xt_find_attr(item, "jid"))) { /* Yay, found what we need. :-) */ - bud->ext_jid = jabber_normalize( s ); + bud->ext_jid = jabber_normalize(s); break; } } - + } + /* Make up some other handle, if necessary. */ - if( bud->ext_jid == NULL ) - { - if( bud == jc->me ) - { - bud->ext_jid = g_strdup( jd->me ); - } - else - { + if (bud->ext_jid == NULL) { + if (bud == jc->me) { + bud->ext_jid = g_strdup(jd->me); + } else { int i; - + /* Don't want the nick to be at the end, so let's think of some slightly different notation to use for anonymous groupchat participants in BitlBee. */ - bud->ext_jid = g_strdup_printf( "%s=%s", bud->resource, bud->bare_jid ); - + bud->ext_jid = g_strdup_printf("%s=%s", bud->resource, bud->bare_jid); + /* And strip any unwanted characters. */ - for( i = 0; bud->resource[i]; i ++ ) - if( bud->ext_jid[i] == '=' || bud->ext_jid[i] == '@' ) + for (i = 0; bud->resource[i]; i++) { + if (bud->ext_jid[i] == '=' || bud->ext_jid[i] == '@') { bud->ext_jid[i] = '_'; - + } + } + /* Some program-specific restrictions. */ - imcb_clean_handle( ic, bud->ext_jid ); + imcb_clean_handle(ic, bud->ext_jid); } bud->flags |= JBFLAG_IS_ANONYMOUS; } - - if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS ) - { + + if (bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS) { /* If JIDs are anonymized, add them to the local list for the duration of this chat. */ - imcb_add_buddy( ic, bud->ext_jid, NULL ); - imcb_buddy_nick_hint( ic, bud->ext_jid, bud->resource ); + imcb_add_buddy(ic, bud->ext_jid, NULL); + imcb_buddy_nick_hint(ic, bud->ext_jid, bud->resource); } - - if( bud == jc->me && jc->invite != NULL ) - { - char *msg = g_strdup_printf( "Please join me in room %s", jc->name ); - jabber_chat_invite( chat, jc->invite, msg ); - g_free( jc->invite ); - g_free( msg ); + + if (bud == jc->me && jc->invite != NULL) { + char *msg = g_strdup_printf("Please join me in room %s", jc->name); + jabber_chat_invite(chat, jc->invite, msg); + g_free(jc->invite); + g_free(msg); jc->invite = NULL; } - - s = strchr( bud->ext_jid, '/' ); - if( s ) *s = 0; /* Should NEVER be NULL, but who knows... */ - imcb_chat_add_buddy( chat, bud->ext_jid ); - if( s ) *s = '/'; - } - else if( type ) /* type can only be NULL or "unavailable" in this function */ - { - if( ( bud->flags & JBFLAG_IS_CHATROOM ) && bud->ext_jid ) - { - s = strchr( bud->ext_jid, '/' ); - if( s ) *s = 0; - imcb_chat_remove_buddy( chat, bud->ext_jid, NULL ); - if( bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS ) - imcb_remove_buddy( ic, bud->ext_jid, NULL ); - if( s ) *s = '/'; + + s = strchr(bud->ext_jid, '/'); + if (s) { + *s = 0; /* Should NEVER be NULL, but who knows... */ + } + imcb_chat_add_buddy(chat, bud->ext_jid); + if (s) { + *s = '/'; + } + } else if (type) { /* type can only be NULL or "unavailable" in this function */ + if ((bud->flags & JBFLAG_IS_CHATROOM) && bud->ext_jid) { + s = strchr(bud->ext_jid, '/'); + if (s) { + *s = 0; + } + imcb_chat_remove_buddy(chat, bud->ext_jid, NULL); + if (bud != jc->me && bud->flags & JBFLAG_IS_ANONYMOUS) { + imcb_remove_buddy(ic, bud->ext_jid, NULL); + } + if (s) { + *s = '/'; + } + } + + if (bud == jc->me) { + jabber_chat_free(chat); } - - if( bud == jc->me ) - jabber_chat_free( chat ); } } -void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ) +void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node) { - struct xt_node *subject = xt_find_node( node->children, "subject" ); - struct xt_node *body = xt_find_node( node->children, "body" ); - struct groupchat *chat = bud ? jabber_chat_by_jid( ic, bud->bare_jid ) : NULL; + struct xt_node *subject = xt_find_node(node->children, "subject"); + struct xt_node *body = xt_find_node(node->children, "body"); + struct groupchat *chat = bud ? jabber_chat_by_jid(ic, bud->bare_jid) : NULL; struct jabber_chat *jc = chat ? chat->data : NULL; char *s; - - if( subject && chat ) - { - s = bud ? strchr( bud->ext_jid, '/' ) : NULL; - if( s ) *s = 0; - imcb_chat_topic( chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ? - subject->text : NULL, jabber_get_timestamp( node ) ); - if( s ) *s = '/'; + + if (subject && chat) { + s = bud ? strchr(bud->ext_jid, '/') : NULL; + if (s) { + *s = 0; + } + imcb_chat_topic(chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ? + subject->text : NULL, jabber_get_timestamp(node)); + if (s) { + *s = '/'; + } } - - if( bud == NULL || ( jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me ) ) - { + + if (bud == NULL || (jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me)) { char *nick; - - if( body == NULL || body->text_len == 0 ) + + if (body == NULL || body->text_len == 0) { /* Meh. Empty messages aren't very interesting, no matter how much some servers love to send them. */ return; - - s = xt_find_attr( node, "from" ); /* pkt_message() already NULL-checked this one. */ - nick = strchr( s, '/' ); - if( nick ) - { + } + + s = xt_find_attr(node, "from"); /* pkt_message() already NULL-checked this one. */ + nick = strchr(s, '/'); + if (nick) { /* If this message included a resource/nick we don't know, we might still know the groupchat itself. */ *nick = 0; - chat = jabber_chat_by_jid( ic, s ); + chat = jabber_chat_by_jid(ic, s); *nick = '/'; - - nick ++; - } - else - { + + nick++; + } else { /* message.c uses the EXACT_JID option, so bud should always be NULL here for bare JIDs. */ - chat = jabber_chat_by_jid( ic, s ); + chat = jabber_chat_by_jid(ic, s); } - - if( nick == NULL ) - { + + if (nick == NULL) { /* This is fine, the groupchat itself isn't in jd->buddies. */ - if( chat ) - imcb_chat_log( chat, "From conference server: %s", body->text ); - else - imcb_log( ic, "System message from unknown groupchat %s: %s", s, body->text ); - } - else - { + if (chat) { + imcb_chat_log(chat, "From conference server: %s", body->text); + } else { + imcb_log(ic, "System message from unknown groupchat %s: %s", s, body->text); + } + } else { /* This can happen too, at least when receiving a backlog when just joining a channel. */ - if( chat ) - imcb_chat_log( chat, "Message from unknown participant %s: %s", nick, body->text ); - else - imcb_log( ic, "Groupchat message from unknown JID %s: %s", s, body->text ); + if (chat) { + imcb_chat_log(chat, "Message from unknown participant %s: %s", nick, body->text); + } else { + imcb_log(ic, "Groupchat message from unknown JID %s: %s", s, body->text); + } } - + return; - } - else if( chat == NULL ) - { + } else if (chat == NULL) { /* How could this happen?? We could do kill( self, 11 ) now or just wait for the OS to do it. :-) */ return; } - if( body && body->text_len > 0 ) - { - s = strchr( bud->ext_jid, '/' ); - if( s ) *s = 0; - imcb_chat_msg( chat, bud->ext_jid, body->text, 0, jabber_get_timestamp( node ) ); - if( s ) *s = '/'; + if (body && body->text_len > 0) { + s = strchr(bud->ext_jid, '/'); + if (s) { + *s = 0; + } + imcb_chat_msg(chat, bud->ext_jid, body->text, 0, jabber_get_timestamp(node)); + if (s) { + *s = '/'; + } } } diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c index a8f7d09f..48ba6b18 100644 --- a/protocols/jabber/io.c +++ b/protocols/jabber/io.c @@ -24,520 +24,488 @@ #include "jabber.h" #include "ssl_client.h" -static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ); -static gboolean jabber_write_queue( struct im_connection *ic ); +static gboolean jabber_write_callback(gpointer data, gint fd, b_input_condition cond); +static gboolean jabber_write_queue(struct im_connection *ic); -int jabber_write_packet( struct im_connection *ic, struct xt_node *node ) +int jabber_write_packet(struct im_connection *ic, struct xt_node *node) { char *buf; int st; - - buf = xt_to_string( node ); - st = jabber_write( ic, buf, strlen( buf ) ); - g_free( buf ); - + + buf = xt_to_string(node); + st = jabber_write(ic, buf, strlen(buf)); + g_free(buf); + return st; } -int jabber_write( struct im_connection *ic, char *buf, int len ) +int jabber_write(struct im_connection *ic, char *buf, int len) { struct jabber_data *jd = ic->proto_data; gboolean ret; - - if( jd->flags & JFLAG_XMLCONSOLE && !( ic->flags & OPT_LOGGING_OUT ) ) - { + + if (jd->flags & JFLAG_XMLCONSOLE && !(ic->flags & OPT_LOGGING_OUT)) { char *msg, *s; - - msg = g_strdup_printf( "TX: %s", buf ); + + msg = g_strdup_printf("TX: %s", buf); /* Don't include auth info in XML logs. */ - if( strncmp( msg, "TX: <auth ", 10 ) == 0 && ( s = strchr( msg, '>' ) ) ) - { + if (strncmp(msg, "TX: <auth ", 10) == 0 && (s = strchr(msg, '>'))) { s++; - while( *s && *s != '<' ) + while (*s && *s != '<') { *(s++) = '*'; + } } - imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 ); - g_free( msg ); + imcb_buddy_msg(ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0); + g_free(msg); } - - if( jd->tx_len == 0 ) - { + + if (jd->tx_len == 0) { /* If the queue is empty, allocate a new buffer. */ jd->tx_len = len; - jd->txq = g_memdup( buf, len ); - + jd->txq = g_memdup(buf, len); + /* Try if we can write it immediately so we don't have to do it via the event handler. If not, add the handler. (In most cases it probably won't be necessary.) */ - if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 ) - jd->w_inpa = b_input_add( jd->fd, B_EV_IO_WRITE, jabber_write_callback, ic ); - } - else - { + if ((ret = jabber_write_queue(ic)) && jd->tx_len > 0) { + jd->w_inpa = b_input_add(jd->fd, B_EV_IO_WRITE, jabber_write_callback, ic); + } + } else { /* Just add it to the buffer if it's already filled. The event handler is already set. */ - jd->txq = g_renew( char, jd->txq, jd->tx_len + len ); - memcpy( jd->txq + jd->tx_len, buf, len ); + jd->txq = g_renew(char, jd->txq, jd->tx_len + len); + memcpy(jd->txq + jd->tx_len, buf, len); jd->tx_len += len; - + /* The return value for write() doesn't necessarily mean that everything got sent, it mainly means that the connection (officially) still exists and can still be accessed without hitting SIGSEGV. IOW: */ ret = TRUE; } - + return ret; } /* Splitting up in two separate functions: One to use as a callback and one to use in the function above to escape from having to wait for the event handler to call us, if possible. - + Two different functions are necessary because of the return values: The callback should only return TRUE if the write was successful AND if the buffer is not empty yet (ie. if the handler has to be called again when the socket is ready for more data). */ -static gboolean jabber_write_callback( gpointer data, gint fd, b_input_condition cond ) +static gboolean jabber_write_callback(gpointer data, gint fd, b_input_condition cond) { - struct jabber_data *jd = ((struct im_connection *)data)->proto_data; - + struct jabber_data *jd = ((struct im_connection *) data)->proto_data; + return jd->fd != -1 && - jabber_write_queue( data ) && + jabber_write_queue(data) && jd->tx_len > 0; } -static gboolean jabber_write_queue( struct im_connection *ic ) +static gboolean jabber_write_queue(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; int st; - - if( jd->ssl ) - st = ssl_write( jd->ssl, jd->txq, jd->tx_len ); - else - st = write( jd->fd, jd->txq, jd->tx_len ); - - if( st == jd->tx_len ) - { + + if (jd->ssl) { + st = ssl_write(jd->ssl, jd->txq, jd->tx_len); + } else { + st = write(jd->fd, jd->txq, jd->tx_len); + } + + if (st == jd->tx_len) { /* We wrote everything, clear the buffer. */ - g_free( jd->txq ); + g_free(jd->txq); jd->txq = NULL; jd->tx_len = 0; - + return TRUE; - } - else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) - { + } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) { /* Set fd to -1 to make sure we won't write to it anymore. */ - closesocket( jd->fd ); /* Shouldn't be necessary after errors? */ + closesocket(jd->fd); /* Shouldn't be necessary after errors? */ jd->fd = -1; - - imcb_error( ic, "Short write() to server" ); - imc_logout( ic, TRUE ); + + imcb_error(ic, "Short write() to server"); + imc_logout(ic, TRUE); return FALSE; - } - else if( st > 0 ) - { + } else if (st > 0) { char *s; - - s = g_memdup( jd->txq + st, jd->tx_len - st ); + + s = g_memdup(jd->txq + st, jd->tx_len - st); jd->tx_len -= st; - g_free( jd->txq ); + g_free(jd->txq); jd->txq = s; - + return TRUE; - } - else - { + } else { /* Just in case we had EINPROGRESS/EAGAIN: */ - + return TRUE; } } -static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond ) +static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char buf[512]; int st; - - if( jd->fd == -1 ) + + if (jd->fd == -1) { return FALSE; - - if( jd->ssl ) - st = ssl_read( jd->ssl, buf, sizeof( buf ) ); - else - st = read( jd->fd, buf, sizeof( buf ) ); - - if( st > 0 ) - { + } + + if (jd->ssl) { + st = ssl_read(jd->ssl, buf, sizeof(buf)); + } else { + st = read(jd->fd, buf, sizeof(buf)); + } + + if (st > 0) { /* Parse. */ - if( xt_feed( jd->xt, buf, st ) < 0 ) - { - imcb_error( ic, "XML stream error" ); - imc_logout( ic, TRUE ); + if (xt_feed(jd->xt, buf, st) < 0) { + imcb_error(ic, "XML stream error"); + imc_logout(ic, TRUE); return FALSE; } - + /* Execute all handlers. */ - if( !xt_handle( jd->xt, NULL, 1 ) ) - { + if (!xt_handle(jd->xt, NULL, 1)) { /* Don't do anything, the handlers should have aborted the connection already. */ return FALSE; } - - if( jd->flags & JFLAG_STREAM_RESTART ) - { + + if (jd->flags & JFLAG_STREAM_RESTART) { jd->flags &= ~JFLAG_STREAM_RESTART; - jabber_start_stream( ic ); + jabber_start_stream(ic); } - + /* Garbage collection. */ - xt_cleanup( jd->xt, NULL, 1 ); - + xt_cleanup(jd->xt, NULL, 1); + /* This is a bit hackish, unfortunately. Although xmltree has nifty event handler stuff, it only calls handlers when nodes are complete. Since the server should only send an opening <stream:stream> tag, we have to check this by hand. :-( */ - if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root ) - { - if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 ) - { + if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) { + if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) { jd->flags |= JFLAG_STREAM_STARTED; - + /* If there's no version attribute, assume this is an old server that can't do SASL authentication. */ - if( !set_getbool( &ic->acc->set, "sasl") || !sasl_supported( ic ) ) - { + if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) { /* If there's no version= tag, we suppose this server does NOT implement: XMPP 1.0, SASL and TLS. */ - if( set_getbool( &ic->acc->set, "tls" ) ) - { - imcb_error( ic, "TLS is turned on for this " - "account, but is not supported by this server" ); - imc_logout( ic, FALSE ); + if (set_getbool(&ic->acc->set, "tls")) { + imcb_error(ic, "TLS is turned on for this " + "account, but is not supported by this server"); + imc_logout(ic, FALSE); return FALSE; - } - else - { - return jabber_init_iq_auth( ic ); + } else { + return jabber_init_iq_auth(ic); } } - } - else - { - imcb_error( ic, "XML stream error" ); - imc_logout( ic, TRUE ); + } else { + imcb_error(ic, "XML stream error"); + imc_logout(ic, TRUE); return FALSE; } } - } - else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) ) - { - closesocket( jd->fd ); + } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) { + closesocket(jd->fd); jd->fd = -1; - - imcb_error( ic, "Error while reading from server" ); - imc_logout( ic, TRUE ); + + imcb_error(ic, "Error while reading from server"); + imc_logout(ic, TRUE); return FALSE; } - - if( ssl_pending( jd->ssl ) ) + + if (ssl_pending(jd->ssl)) { /* OpenSSL empties the TCP buffers completely but may keep some data in its internap buffers. select() won't see that, but ssl_pending() does. */ - return jabber_read_callback( data, fd, cond ); - else + return jabber_read_callback(data, fd, cond); + } else { return TRUE; + } } -gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ) +gboolean jabber_connected_plain(gpointer data, gint source, b_input_condition cond) { struct im_connection *ic = data; - - if( g_slist_find( jabber_connections, ic ) == NULL ) + + if (g_slist_find(jabber_connections, ic) == NULL) { return FALSE; - - if( source == -1 ) - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); + } + + if (source == -1) { + imcb_error(ic, "Could not connect to server"); + imc_logout(ic, TRUE); return FALSE; } - - imcb_log( ic, "Connected to server, logging in" ); - - return jabber_start_stream( ic ); + + imcb_log(ic, "Connected to server, logging in"); + + return jabber_start_stream(ic); } -gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond ) +gboolean jabber_connected_ssl(gpointer data, int returncode, void *source, b_input_condition cond) { struct im_connection *ic = data; struct jabber_data *jd; - - if( g_slist_find( jabber_connections, ic ) == NULL ) + + if (g_slist_find(jabber_connections, ic) == NULL) { return FALSE; - + } + jd = ic->proto_data; - - if( source == NULL ) - { + + if (source == NULL) { /* The SSL connection will be cleaned up by the SSL lib already, set it to NULL here to prevent a double cleanup: */ jd->ssl = NULL; - - if( returncode != 0 ) - { - char *err = ssl_verify_strerror( returncode ); - imcb_error( ic, "Certificate verification problem 0x%x: %s", - returncode, err ? err : "Unknown" ); - g_free( err ); - imc_logout( ic, FALSE ); - } - else - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); + + if (returncode != 0) { + char *err = ssl_verify_strerror(returncode); + imcb_error(ic, "Certificate verification problem 0x%x: %s", + returncode, err ? err : "Unknown"); + g_free(err); + imc_logout(ic, FALSE); + } else { + imcb_error(ic, "Could not connect to server"); + imc_logout(ic, TRUE); } - + return FALSE; } - - imcb_log( ic, "Connected to server, logging in" ); - - return jabber_start_stream( ic ); + + imcb_log(ic, "Connected to server, logging in"); + + return jabber_start_stream(ic); } -static xt_status jabber_end_of_stream( struct xt_node *node, gpointer data ) +static xt_status jabber_end_of_stream(struct xt_node *node, gpointer data) { - imc_logout( data, TRUE ); + imc_logout(data, TRUE); return XT_ABORT; } -static xt_status jabber_pkt_features( struct xt_node *node, gpointer data ) +static xt_status jabber_pkt_features(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply; int trytls; - - trytls = g_strcasecmp( set_getstr( &ic->acc->set, "tls" ), "try" ) == 0; - c = xt_find_node( node->children, "starttls" ); - if( c && !jd->ssl ) - { + + trytls = g_strcasecmp(set_getstr(&ic->acc->set, "tls"), "try") == 0; + c = xt_find_node(node->children, "starttls"); + if (c && !jd->ssl) { /* If the server advertises the STARTTLS feature and if we're not in a secure connection already: */ - - c = xt_find_node( c->children, "required" ); - - if( c && ( !trytls && !set_getbool( &ic->acc->set, "tls" ) ) ) - { - imcb_error( ic, "Server requires TLS connections, but TLS is turned off for this account" ); - imc_logout( ic, FALSE ); - + + c = xt_find_node(c->children, "required"); + + if (c && (!trytls && !set_getbool(&ic->acc->set, "tls"))) { + imcb_error(ic, "Server requires TLS connections, but TLS is turned off for this account"); + imc_logout(ic, FALSE); + return XT_ABORT; } - + /* Only run this if the tls setting is set to true or try: */ - if( ( trytls || set_getbool( &ic->acc->set, "tls" ) ) ) - { - reply = xt_new_node( "starttls", NULL, NULL ); - xt_add_attr( reply, "xmlns", XMLNS_TLS ); - if( !jabber_write_packet( ic, reply ) ) - { - xt_free_node( reply ); + if ((trytls || set_getbool(&ic->acc->set, "tls"))) { + reply = xt_new_node("starttls", NULL, NULL); + xt_add_attr(reply, "xmlns", XMLNS_TLS); + if (!jabber_write_packet(ic, reply)) { + xt_free_node(reply); return XT_ABORT; } - xt_free_node( reply ); - + xt_free_node(reply); + return XT_HANDLED; } - } - else if( !c && !jd->ssl ) - { + } else if (!c && !jd->ssl) { /* If the server does not advertise the STARTTLS feature and we're not in a secure connection already: (Servers have a habit of not advertising <starttls/> anymore when already using SSL/TLS. */ - - if( !trytls && set_getbool( &ic->acc->set, "tls" ) ) - { - imcb_error( ic, "TLS is turned on for this account, but is not supported by this server" ); - imc_logout( ic, FALSE ); - + + if (!trytls && set_getbool(&ic->acc->set, "tls")) { + imcb_error(ic, "TLS is turned on for this account, but is not supported by this server"); + imc_logout(ic, FALSE); + return XT_ABORT; } } - + /* This one used to be in jabber_handlers[], but it has to be done from here to make sure the TLS session will be initialized properly before we attempt SASL authentication. */ - if( ( c = xt_find_node( node->children, "mechanisms" ) ) ) - { - if( sasl_pkt_mechanisms( c, data ) == XT_ABORT ) + if ((c = xt_find_node(node->children, "mechanisms"))) { + if (sasl_pkt_mechanisms(c, data) == XT_ABORT) { return XT_ABORT; + } } /* If the server *SEEMS* to support SASL authentication but doesn't support it after all, we should try to do authentication the other way. jabber.com doesn't seem to do SASL while it pretends to be XMPP 1.0 compliant! */ - else if( !( jd->flags & JFLAG_AUTHENTICATED ) && set_getbool( &ic->acc->set, "sasl") && sasl_supported( ic ) ) - { - if( !jabber_init_iq_auth( ic ) ) + else if (!(jd->flags & JFLAG_AUTHENTICATED) && set_getbool(&ic->acc->set, "sasl") && sasl_supported(ic)) { + if (!jabber_init_iq_auth(ic)) { return XT_ABORT; + } } - - if( ( c = xt_find_node( node->children, "bind" ) ) ) + + if ((c = xt_find_node(node->children, "bind"))) { jd->flags |= JFLAG_WANT_BIND; - - if( ( c = xt_find_node( node->children, "session" ) ) ) + } + + if ((c = xt_find_node(node->children, "session"))) { jd->flags |= JFLAG_WANT_SESSION; - - if( jd->flags & JFLAG_AUTHENTICATED ) - return jabber_pkt_bind_sess( ic, NULL, NULL ); - + } + + if (jd->flags & JFLAG_AUTHENTICATED) { + return jabber_pkt_bind_sess(ic, NULL, NULL); + } + return XT_HANDLED; } -static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data ) +static xt_status jabber_pkt_proceed_tls(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char *xmlns, *tlsname; - - xmlns = xt_find_attr( node, "xmlns" ); - + + xmlns = xt_find_attr(node, "xmlns"); + /* Just ignore it when it doesn't seem to be TLS-related (is that at all possible??). */ - if( !xmlns || strcmp( xmlns, XMLNS_TLS ) != 0 ) + if (!xmlns || strcmp(xmlns, XMLNS_TLS) != 0) { return XT_HANDLED; - + } + /* We don't want event handlers to touch our TLS session while it's still initializing! */ - b_event_remove( jd->r_inpa ); - if( jd->tx_len > 0 ) - { + b_event_remove(jd->r_inpa); + if (jd->tx_len > 0) { /* Actually the write queue should be empty here, but just to be sure... */ - b_event_remove( jd->w_inpa ); - g_free( jd->txq ); + b_event_remove(jd->w_inpa); + g_free(jd->txq); jd->txq = NULL; jd->tx_len = 0; } jd->w_inpa = jd->r_inpa = 0; - - imcb_log( ic, "Converting stream to TLS" ); - + + imcb_log(ic, "Converting stream to TLS"); + jd->flags |= JFLAG_STARTTLS_DONE; - /* If the user specified a server for the account, use this server as the - * hostname in the certificate verification. Else we use the domain from + /* If the user specified a server for the account, use this server as the + * hostname in the certificate verification. Else we use the domain from * the username. */ - if( ic->acc->server && *ic->acc->server ) + if (ic->acc->server && *ic->acc->server) { tlsname = ic->acc->server; - else + } else { tlsname = jd->server; - - jd->ssl = ssl_starttls( jd->fd, tlsname, set_getbool( &ic->acc->set, "tls_verify" ), - jabber_connected_ssl, ic ); - + } + + jd->ssl = ssl_starttls(jd->fd, tlsname, set_getbool(&ic->acc->set, "tls_verify"), + jabber_connected_ssl, ic); + return XT_HANDLED; } -static xt_status jabber_pkt_stream_error( struct xt_node *node, gpointer data ) +static xt_status jabber_pkt_stream_error(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; int allow_reconnect = TRUE; struct jabber_error *err; struct xt_node *host; - - if( !( ic->flags & OPT_LOGGED_IN ) && - ( host = xt_find_node( node->children, "see-other-host" ) ) && - host->text ) - { + + if (!(ic->flags & OPT_LOGGED_IN) && + (host = xt_find_node(node->children, "see-other-host")) && + host->text) { char *s; - int port = set_getint( &ic->acc->set, "port" ); - + int port = set_getint(&ic->acc->set, "port"); + /* Let's try to obey this request, if we're not logged in yet (i.e. not have too much state yet). */ - if( jd->ssl ) - ssl_disconnect( jd->ssl ); - closesocket( jd->fd ); - b_event_remove( jd->r_inpa ); - b_event_remove( jd->w_inpa ); - + if (jd->ssl) { + ssl_disconnect(jd->ssl); + } + closesocket(jd->fd); + b_event_remove(jd->r_inpa); + b_event_remove(jd->w_inpa); + jd->ssl = NULL; jd->r_inpa = jd->w_inpa = 0; jd->flags &= JFLAG_XMLCONSOLE; - - s = strchr( host->text, ':' ); - if( s != NULL ) - sscanf( s + 1, "%d", &port ); - - imcb_log( ic, "Redirected to %s", host->text ); - jd->fd = proxy_connect( host->text, port, jabber_connected_plain, ic ); - + + s = strchr(host->text, ':'); + if (s != NULL) { + sscanf(s + 1, "%d", &port); + } + + imcb_log(ic, "Redirected to %s", host->text); + jd->fd = proxy_connect(host->text, port, jabber_connected_plain, ic); + return XT_ABORT; } - - err = jabber_error_parse( node, XMLNS_STREAM_ERROR ); - + + err = jabber_error_parse(node, XMLNS_STREAM_ERROR); + /* Tssk... */ - if( err->code == NULL ) - { - imcb_error( ic, "Unknown stream error reported by server" ); - imc_logout( ic, allow_reconnect ); - jabber_error_free( err ); + if (err->code == NULL) { + imcb_error(ic, "Unknown stream error reported by server"); + imc_logout(ic, allow_reconnect); + jabber_error_free(err); return XT_ABORT; } - + /* We know that this is a fatal error. If it's a "conflict" error, we should turn off auto-reconnect to make sure we won't get some nasty infinite loop! */ - if( strcmp( err->code, "conflict" ) == 0 ) - { - imcb_error( ic, "Account and resource used from a different location" ); + if (strcmp(err->code, "conflict") == 0) { + imcb_error(ic, "Account and resource used from a different location"); allow_reconnect = FALSE; - } - else if( strcmp( err->code, "not-authorized" ) == 0 ) - { - imcb_error( ic, "Not authorized" ); + } else if (strcmp(err->code, "not-authorized") == 0) { + imcb_error(ic, "Not authorized"); allow_reconnect = FALSE; + } else { + imcb_error(ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "", + err->text ? err->text : ""); } - else - { - imcb_error( ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "", - err->text ? err->text : "" ); - } - - jabber_error_free( err ); - imc_logout( ic, allow_reconnect ); - + + jabber_error_free(err); + imc_logout(ic, allow_reconnect); + return XT_ABORT; } -static xt_status jabber_xmlconsole( struct xt_node *node, gpointer data ) +static xt_status jabber_xmlconsole(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; - - if( jd->flags & JFLAG_XMLCONSOLE ) - { + + if (jd->flags & JFLAG_XMLCONSOLE) { char *msg, *pkt; - - pkt = xt_to_string( node ); - msg = g_strdup_printf( "RX: %s", pkt ); - imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 ); - g_free( msg ); - g_free( pkt ); + + pkt = xt_to_string(node); + msg = g_strdup_printf("RX: %s", pkt); + imcb_buddy_msg(ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0); + g_free(msg); + g_free(pkt); } - + return XT_NEXT; } @@ -556,52 +524,52 @@ static const struct xt_handler_entry jabber_handlers[] = { { NULL, NULL, NULL } }; -gboolean jabber_start_stream( struct im_connection *ic ) +gboolean jabber_start_stream(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; int st; char *greet; - + /* We'll start our stream now, so prepare everything to receive one from the server too. */ - xt_free( jd->xt ); /* In case we're RE-starting. */ - jd->xt = xt_new( jabber_handlers, ic ); - - if( jd->r_inpa <= 0 ) - jd->r_inpa = b_input_add( jd->fd, B_EV_IO_READ, jabber_read_callback, ic ); - - greet = g_strdup_printf( "%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " - "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", - ( jd->flags & JFLAG_STARTTLS_DONE ) ? "" : "<?xml version='1.0' ?>", - jd->server ); - - st = jabber_write( ic, greet, strlen( greet ) ); - - g_free( greet ); - + xt_free(jd->xt); /* In case we're RE-starting. */ + jd->xt = xt_new(jabber_handlers, ic); + + if (jd->r_inpa <= 0) { + jd->r_inpa = b_input_add(jd->fd, B_EV_IO_READ, jabber_read_callback, ic); + } + + greet = g_strdup_printf("%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " + "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", + (jd->flags & JFLAG_STARTTLS_DONE) ? "" : "<?xml version='1.0' ?>", + jd->server); + + st = jabber_write(ic, greet, strlen(greet)); + + g_free(greet); + return st; } -void jabber_end_stream( struct im_connection *ic ) +void jabber_end_stream(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; - + /* Let's only do this if the queue is currently empty, otherwise it'd take too long anyway. */ - if( jd->tx_len == 0 ) - { + if (jd->tx_len == 0) { char eos[] = "</stream:stream>"; struct xt_node *node; int st = 1; - - if( ic->flags & OPT_LOGGED_IN ) - { - node = jabber_make_packet( "presence", "unavailable", NULL, NULL ); - st = jabber_write_packet( ic, node ); - xt_free_node( node ); + + if (ic->flags & OPT_LOGGED_IN) { + node = jabber_make_packet("presence", "unavailable", NULL, NULL); + st = jabber_write_packet(ic, node); + xt_free_node(node); + } + + if (st) { + jabber_write(ic, eos, strlen(eos)); } - - if( st ) - jabber_write( ic, eos, strlen( eos ) ); } } diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index cf1ff298..d7ba6f55 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -24,840 +24,801 @@ #include "jabber.h" #include "sha1.h" -static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -static int jabber_iq_disco_server( struct im_connection *ic ); +static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +static int jabber_iq_disco_server(struct im_connection *ic); -xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) +xt_status jabber_pkt_iq(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *type, *s; int st, pack = 1; - - type = xt_find_attr( node, "type" ); - - if( !type ) - { - imcb_error( ic, "Received IQ packet without type." ); - imc_logout( ic, TRUE ); + + type = xt_find_attr(node, "type"); + + if (!type) { + imcb_error(ic, "Received IQ packet without type."); + imc_logout(ic, TRUE); return XT_ABORT; } - - if( strcmp( type, "result" ) == 0 || strcmp( type, "error" ) == 0 ) - { - return jabber_cache_handle_packet( ic, node ); - } - else if( strcmp( type, "get" ) == 0 ) - { - if( !( ( c = xt_find_node( node->children, "query" ) ) || - ( c = xt_find_node( node->children, "ping" ) ) || - ( c = xt_find_node( node->children, "time" ) ) ) || - !( s = xt_find_attr( c, "xmlns" ) ) ) - { + + if (strcmp(type, "result") == 0 || strcmp(type, "error") == 0) { + return jabber_cache_handle_packet(ic, node); + } else if (strcmp(type, "get") == 0) { + if (!((c = xt_find_node(node->children, "query")) || + (c = xt_find_node(node->children, "ping")) || + (c = xt_find_node(node->children, "time"))) || + !(s = xt_find_attr(c, "xmlns"))) { /* Sigh. Who decided to suddenly invent new elements instead of just sticking with <query/>? */ return XT_HANDLED; } - - reply = xt_new_node( "query", NULL, NULL ); - xt_add_attr( reply, "xmlns", s ); - + + reply = xt_new_node("query", NULL, NULL); + xt_add_attr(reply, "xmlns", s); + /* Of course this is a very essential query to support. ;-) */ - if( strcmp( s, XMLNS_VERSION ) == 0 ) - { - xt_add_child( reply, xt_new_node( "name", set_getstr( &ic->acc->set, "user_agent" ), NULL ) ); - xt_add_child( reply, xt_new_node( "version", BITLBEE_VERSION, NULL ) ); - xt_add_child( reply, xt_new_node( "os", ARCH, NULL ) ); - } - else if( strcmp( s, XMLNS_TIME_OLD ) == 0 ) - { + if (strcmp(s, XMLNS_VERSION) == 0) { + xt_add_child(reply, xt_new_node("name", set_getstr(&ic->acc->set, "user_agent"), NULL)); + xt_add_child(reply, xt_new_node("version", BITLBEE_VERSION, NULL)); + xt_add_child(reply, xt_new_node("os", ARCH, NULL)); + } else if (strcmp(s, XMLNS_TIME_OLD) == 0) { time_t time_ep; char buf[1024]; - - buf[sizeof(buf)-1] = 0; - time_ep = time( NULL ); - - strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%S", gmtime( &time_ep ) ); - xt_add_child( reply, xt_new_node( "utc", buf, NULL ) ); - - strftime( buf, sizeof( buf ) - 1, "%Z", localtime( &time_ep ) ); - xt_add_child( reply, xt_new_node( "tz", buf, NULL ) ); - } - else if( strcmp( s, XMLNS_TIME ) == 0 ) - { + + buf[sizeof(buf) - 1] = 0; + time_ep = time(NULL); + + strftime(buf, sizeof(buf) - 1, "%Y%m%dT%H:%M:%S", gmtime(&time_ep)); + xt_add_child(reply, xt_new_node("utc", buf, NULL)); + + strftime(buf, sizeof(buf) - 1, "%Z", localtime(&time_ep)); + xt_add_child(reply, xt_new_node("tz", buf, NULL)); + } else if (strcmp(s, XMLNS_TIME) == 0) { time_t time_ep; char buf[1024]; - - buf[sizeof(buf)-1] = 0; - time_ep = time( NULL ); - - xt_free_node( reply ); - reply = xt_new_node( "time", NULL, NULL ); - xt_add_attr( reply, "xmlns", XMLNS_TIME ); - - strftime( buf, sizeof( buf ) - 1, "%Y%m%dT%H:%M:%SZ", gmtime( &time_ep ) ); - xt_add_child( reply, xt_new_node( "utc", buf, NULL ) ); - - strftime( buf, sizeof( buf ) - 1, "%z", localtime( &time_ep ) ); - if( strlen( buf ) >= 5 ) - { + + buf[sizeof(buf) - 1] = 0; + time_ep = time(NULL); + + xt_free_node(reply); + reply = xt_new_node("time", NULL, NULL); + xt_add_attr(reply, "xmlns", XMLNS_TIME); + + strftime(buf, sizeof(buf) - 1, "%Y%m%dT%H:%M:%SZ", gmtime(&time_ep)); + xt_add_child(reply, xt_new_node("utc", buf, NULL)); + + strftime(buf, sizeof(buf) - 1, "%z", localtime(&time_ep)); + if (strlen(buf) >= 5) { buf[6] = '\0'; buf[5] = buf[4]; buf[4] = buf[3]; buf[3] = ':'; } - xt_add_child( reply, xt_new_node( "tzo", buf, NULL ) ); - } - else if( strcmp( s, XMLNS_PING ) == 0 ) - { - xt_free_node( reply ); - reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), NULL ); - if( ( s = xt_find_attr( node, "id" ) ) ) - xt_add_attr( reply, "id", s ); + xt_add_child(reply, xt_new_node("tzo", buf, NULL)); + } else if (strcmp(s, XMLNS_PING) == 0) { + xt_free_node(reply); + reply = jabber_make_packet("iq", "result", xt_find_attr(node, "from"), NULL); + if ((s = xt_find_attr(node, "id"))) { + xt_add_attr(reply, "id", s); + } pack = 0; - } - else if( strcmp( s, XMLNS_DISCO_INFO ) == 0 ) - { + } else if (strcmp(s, XMLNS_DISCO_INFO) == 0) { const char *features[] = { XMLNS_DISCO_INFO, - XMLNS_VERSION, - XMLNS_TIME_OLD, - XMLNS_TIME, - XMLNS_CHATSTATES, - XMLNS_MUC, - XMLNS_PING, - XMLNS_RECEIPTS, - XMLNS_SI, - XMLNS_BYTESTREAMS, - XMLNS_FILETRANSFER, - NULL }; + XMLNS_VERSION, + XMLNS_TIME_OLD, + XMLNS_TIME, + XMLNS_CHATSTATES, + XMLNS_MUC, + XMLNS_PING, + XMLNS_RECEIPTS, + XMLNS_SI, + XMLNS_BYTESTREAMS, + XMLNS_FILETRANSFER, + NULL }; const char **f; - - c = xt_new_node( "identity", NULL, NULL ); - xt_add_attr( c, "category", "client" ); - xt_add_attr( c, "type", "pc" ); - xt_add_attr( c, "name", set_getstr( &ic->acc->set, "user_agent" ) ); - xt_add_child( reply, c ); - - for( f = features; *f; f ++ ) - { - c = xt_new_node( "feature", NULL, NULL ); - xt_add_attr( c, "var", *f ); - xt_add_child( reply, c ); + + c = xt_new_node("identity", NULL, NULL); + xt_add_attr(c, "category", "client"); + xt_add_attr(c, "type", "pc"); + xt_add_attr(c, "name", set_getstr(&ic->acc->set, "user_agent")); + xt_add_child(reply, c); + + for (f = features; *f; f++) { + c = xt_new_node("feature", NULL, NULL); + xt_add_attr(c, "var", *f); + xt_add_child(reply, c); } - } - else - { - xt_free_node( reply ); - reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); + } else { + xt_free_node(reply); + reply = jabber_make_error_packet(node, "feature-not-implemented", "cancel", NULL); pack = 0; } - } - else if( strcmp( type, "set" ) == 0 ) - { - if( ( c = xt_find_node( node->children, "si" ) ) && - ( s = xt_find_attr( c, "xmlns" ) ) && - ( strcmp( s, XMLNS_SI ) == 0 ) ) - { - return jabber_si_handle_request( ic, node, c ); - } - else if( !( c = xt_find_node( node->children, "query" ) ) || - !( s = xt_find_attr( c, "xmlns" ) ) ) - { + } else if (strcmp(type, "set") == 0) { + if ((c = xt_find_node(node->children, "si")) && + (s = xt_find_attr(c, "xmlns")) && + (strcmp(s, XMLNS_SI) == 0)) { + return jabber_si_handle_request(ic, node, c); + } else if (!(c = xt_find_node(node->children, "query")) || + !(s = xt_find_attr(c, "xmlns"))) { return XT_HANDLED; - } - else if( strcmp( s, XMLNS_ROSTER ) == 0 ) - { - /* This is a roster push. XMPP servers send this when someone - was added to (or removed from) the buddy list. AFAIK they're - sent even if we added this buddy in our own session. */ - int bare_len = strlen( jd->me ); - - if( ( s = xt_find_attr( node, "from" ) ) == NULL || - ( strncmp( s, jd->me, bare_len ) == 0 && - ( s[bare_len] == 0 || s[bare_len] == '/' ) ) ) - { - jabber_parse_roster( ic, node, NULL ); - + } else if (strcmp(s, XMLNS_ROSTER) == 0) { + /* This is a roster push. XMPP servers send this when someone + was added to (or removed from) the buddy list. AFAIK they're + sent even if we added this buddy in our own session. */ + int bare_len = strlen(jd->me); + + if ((s = xt_find_attr(node, "from")) == NULL || + (strncmp(s, jd->me, bare_len) == 0 && + (s[bare_len] == 0 || s[bare_len] == '/'))) { + jabber_parse_roster(ic, node, NULL); + /* Should we generate a reply here? Don't think it's very important... */ - } - else - { - imcb_log( ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)" ); - - xt_free_node( reply ); - reply = jabber_make_error_packet( node, "not-allowed", "cancel", NULL ); + } else { + imcb_log(ic, "Warning: %s tried to fake a roster push!", s ? s : "(unknown)"); + + xt_free_node(reply); + reply = jabber_make_error_packet(node, "not-allowed", "cancel", NULL); pack = 0; } - } - else if( strcmp( s, XMLNS_BYTESTREAMS ) == 0 ) - { + } else if (strcmp(s, XMLNS_BYTESTREAMS) == 0) { /* Bytestream Request (stage 2 of file transfer) */ - return jabber_bs_recv_request( ic, node, c ); - } - else - { - xt_free_node( reply ); - reply = jabber_make_error_packet( node, "feature-not-implemented", "cancel", NULL ); + return jabber_bs_recv_request(ic, node, c); + } else { + xt_free_node(reply); + reply = jabber_make_error_packet(node, "feature-not-implemented", "cancel", NULL); pack = 0; } } - + /* If we recognized the xmlns and managed to generate a reply, finish and send it. */ - if( reply ) - { + if (reply) { /* Normally we still have to pack it into an iq-result packet, but for errors, for example, we don't. */ - if( pack ) - { - reply = jabber_make_packet( "iq", "result", xt_find_attr( node, "from" ), reply ); - if( ( s = xt_find_attr( node, "id" ) ) ) - xt_add_attr( reply, "id", s ); - } - - st = jabber_write_packet( ic, reply ); - xt_free_node( reply ); - if( !st ) + if (pack) { + reply = jabber_make_packet("iq", "result", xt_find_attr(node, "from"), reply); + if ((s = xt_find_attr(node, "id"))) { + xt_add_attr(reply, "id", s); + } + } + + st = jabber_write_packet(ic, reply); + xt_free_node(reply); + if (!st) { return XT_ABORT; + } } - + return XT_HANDLED; } -static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_do_iq_auth(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +static xt_status jabber_finish_iq_auth(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -int jabber_init_iq_auth( struct im_connection *ic ) +int jabber_init_iq_auth(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; struct xt_node *node; int st; - - node = xt_new_node( "query", NULL, xt_new_node( "username", jd->username, NULL ) ); - xt_add_attr( node, "xmlns", XMLNS_AUTH ); - node = jabber_make_packet( "iq", "get", NULL, node ); - - jabber_cache_add( ic, node, jabber_do_iq_auth ); - st = jabber_write_packet( ic, node ); - + + node = xt_new_node("query", NULL, xt_new_node("username", jd->username, NULL)); + xt_add_attr(node, "xmlns", XMLNS_AUTH); + node = jabber_make_packet("iq", "get", NULL, node); + + jabber_cache_add(ic, node, jabber_do_iq_auth); + st = jabber_write_packet(ic, node); + return st; } -static xt_status jabber_do_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_do_iq_auth(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct jabber_data *jd = ic->proto_data; struct xt_node *reply, *query; xt_status st; char *s; - - if( !( query = xt_find_node( node->children, "query" ) ) ) - { - imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); - imc_logout( ic, FALSE ); + + if (!(query = xt_find_node(node->children, "query"))) { + imcb_log(ic, "Warning: Received incomplete IQ packet while authenticating"); + imc_logout(ic, FALSE); return XT_HANDLED; } - + /* Time to authenticate ourselves! */ - reply = xt_new_node( "query", NULL, NULL ); - xt_add_attr( reply, "xmlns", XMLNS_AUTH ); - xt_add_child( reply, xt_new_node( "username", jd->username, NULL ) ); - xt_add_child( reply, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); - - if( xt_find_node( query->children, "digest" ) && ( s = xt_find_attr( jd->xt->root, "id" ) ) ) - { + reply = xt_new_node("query", NULL, NULL); + xt_add_attr(reply, "xmlns", XMLNS_AUTH); + xt_add_child(reply, xt_new_node("username", jd->username, NULL)); + xt_add_child(reply, xt_new_node("resource", set_getstr(&ic->acc->set, "resource"), NULL)); + + if (xt_find_node(query->children, "digest") && (s = xt_find_attr(jd->xt->root, "id"))) { /* We can do digest authentication, it seems, and of course we prefer that. */ sha1_state_t sha; char hash_hex[41]; unsigned char hash[20]; int i; - - sha1_init( &sha ); - sha1_append( &sha, (unsigned char*) s, strlen( s ) ); - sha1_append( &sha, (unsigned char*) ic->acc->pass, strlen( ic->acc->pass ) ); - sha1_finish( &sha, hash ); - - for( i = 0; i < 20; i ++ ) - sprintf( hash_hex + i * 2, "%02x", hash[i] ); - - xt_add_child( reply, xt_new_node( "digest", hash_hex, NULL ) ); - } - else if( xt_find_node( query->children, "password" ) ) - { + + sha1_init(&sha); + sha1_append(&sha, (unsigned char *) s, strlen(s)); + sha1_append(&sha, (unsigned char *) ic->acc->pass, strlen(ic->acc->pass)); + sha1_finish(&sha, hash); + + for (i = 0; i < 20; i++) { + sprintf(hash_hex + i * 2, "%02x", hash[i]); + } + + xt_add_child(reply, xt_new_node("digest", hash_hex, NULL)); + } else if (xt_find_node(query->children, "password")) { /* We'll have to stick with plaintext. Let's hope we're using SSL/TLS... */ - xt_add_child( reply, xt_new_node( "password", ic->acc->pass, NULL ) ); - } - else - { - xt_free_node( reply ); - - imcb_error( ic, "Can't find suitable authentication method" ); - imc_logout( ic, FALSE ); + xt_add_child(reply, xt_new_node("password", ic->acc->pass, NULL)); + } else { + xt_free_node(reply); + + imcb_error(ic, "Can't find suitable authentication method"); + imc_logout(ic, FALSE); return XT_ABORT; } - - reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( ic, reply, jabber_finish_iq_auth ); - st = jabber_write_packet( ic, reply ); - + + reply = jabber_make_packet("iq", "set", NULL, reply); + jabber_cache_add(ic, reply, jabber_finish_iq_auth); + st = jabber_write_packet(ic, reply); + return st ? XT_HANDLED : XT_ABORT; } -static xt_status jabber_finish_iq_auth( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_finish_iq_auth(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct jabber_data *jd = ic->proto_data; char *type; - - if( !( type = xt_find_attr( node, "type" ) ) ) - { - imcb_log( ic, "Warning: Received incomplete IQ packet while authenticating" ); - imc_logout( ic, FALSE ); + + if (!(type = xt_find_attr(node, "type"))) { + imcb_log(ic, "Warning: Received incomplete IQ packet while authenticating"); + imc_logout(ic, FALSE); return XT_HANDLED; } - - if( strcmp( type, "error" ) == 0 ) - { - imcb_error( ic, "Authentication failure" ); - imc_logout( ic, FALSE ); + + if (strcmp(type, "error") == 0) { + imcb_error(ic, "Authentication failure"); + imc_logout(ic, FALSE); return XT_ABORT; - } - else if( strcmp( type, "result" ) == 0 ) - { + } else if (strcmp(type, "result") == 0) { /* This happens when we just successfully authenticated the old (non-SASL) way. */ jd->flags |= JFLAG_AUTHENTICATED; - if( !jabber_get_roster( ic ) ) + if (!jabber_get_roster(ic)) { return XT_ABORT; - if( !jabber_iq_disco_server( ic ) ) + } + if (!jabber_iq_disco_server(ic)) { return XT_ABORT; + } } - + return XT_HANDLED; } -xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +xt_status jabber_pkt_bind_sess(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply = NULL; char *s; - - if( node && ( c = xt_find_node( node->children, "bind" ) ) ) - { - c = xt_find_node( c->children, "jid" ); - if( !c || !c->text ) - { + + if (node && (c = xt_find_node(node->children, "bind"))) { + c = xt_find_node(c->children, "jid"); + if (!c || !c->text) { /* Server is crap, but this is no disaster. */ - } - else if( jabber_compare_jid( jd->me, c->text ) == 0 ) - { - s = strchr( c->text, '/' ); - if( s ) + } else if (jabber_compare_jid(jd->me, c->text) == 0) { + s = strchr(c->text, '/'); + if (s) { *s = '\0'; - jabber_set_me( ic, c->text ); - if( s ) + } + jabber_set_me(ic, c->text); + if (s) { *s = '/'; + } + } else if (c && c->text_len && (s = strchr(c->text, '/')) && + strcmp(s + 1, set_getstr(&ic->acc->set, "resource")) != 0) { + imcb_log(ic, "Server changed session resource string to `%s'", s + 1); } - else if( c && c->text_len && ( s = strchr( c->text, '/' ) ) && - strcmp( s + 1, set_getstr( &ic->acc->set, "resource" ) ) != 0 ) - imcb_log( ic, "Server changed session resource string to `%s'", s + 1 ); } - - if( jd->flags & JFLAG_WANT_BIND ) - { - reply = xt_new_node( "bind", NULL, xt_new_node( "resource", set_getstr( &ic->acc->set, "resource" ), NULL ) ); - xt_add_attr( reply, "xmlns", XMLNS_BIND ); + + if (jd->flags & JFLAG_WANT_BIND) { + reply = xt_new_node("bind", NULL, xt_new_node("resource", set_getstr(&ic->acc->set, "resource"), NULL)); + xt_add_attr(reply, "xmlns", XMLNS_BIND); jd->flags &= ~JFLAG_WANT_BIND; - } - else if( jd->flags & JFLAG_WANT_SESSION ) - { - reply = xt_new_node( "session", NULL, NULL ); - xt_add_attr( reply, "xmlns", XMLNS_SESSION ); + } else if (jd->flags & JFLAG_WANT_SESSION) { + reply = xt_new_node("session", NULL, NULL); + xt_add_attr(reply, "xmlns", XMLNS_SESSION); jd->flags &= ~JFLAG_WANT_SESSION; } - - if( reply != NULL ) - { - reply = jabber_make_packet( "iq", "set", NULL, reply ); - jabber_cache_add( ic, reply, jabber_pkt_bind_sess ); - - if( !jabber_write_packet( ic, reply ) ) + + if (reply != NULL) { + reply = jabber_make_packet("iq", "set", NULL, reply); + jabber_cache_add(ic, reply, jabber_pkt_bind_sess); + + if (!jabber_write_packet(ic, reply)) { return XT_ABORT; - } - else if( ( jd->flags & ( JFLAG_WANT_BIND | JFLAG_WANT_SESSION ) ) == 0 ) - { - if( !jabber_get_roster( ic ) ) + } + } else if ((jd->flags & (JFLAG_WANT_BIND | JFLAG_WANT_SESSION)) == 0) { + if (!jabber_get_roster(ic)) { return XT_ABORT; - if( !jabber_iq_disco_server( ic ) ) + } + if (!jabber_iq_disco_server(ic)) { return XT_ABORT; + } } - + return XT_HANDLED; } -int jabber_get_roster( struct im_connection *ic ) +int jabber_get_roster(struct im_connection *ic) { struct xt_node *node; int st; - - imcb_log( ic, "Authenticated, requesting buddy list" ); - - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_ROSTER ); - node = jabber_make_packet( "iq", "get", NULL, node ); - - jabber_cache_add( ic, node, jabber_parse_roster ); - st = jabber_write_packet( ic, node ); - + + imcb_log(ic, "Authenticated, requesting buddy list"); + + node = xt_new_node("query", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_ROSTER); + node = jabber_make_packet("iq", "get", NULL, node); + + jabber_cache_add(ic, node, jabber_parse_roster); + st = jabber_write_packet(ic, node); + return st; } -static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct xt_node *query, *c; - int initial = ( orig != NULL ); - - if( !( query = xt_find_node( node->children, "query" ) ) ) - { - imcb_log( ic, "Warning: Received NULL roster packet" ); + int initial = (orig != NULL); + + if (!(query = xt_find_node(node->children, "query"))) { + imcb_log(ic, "Warning: Received NULL roster packet"); return XT_HANDLED; } - + c = query->children; - while( ( c = xt_find_node( c, "item" ) ) ) - { - struct xt_node *group = xt_find_node( c->children, "group" ); - char *jid = xt_find_attr( c, "jid" ); - char *name = xt_find_attr( c, "name" ); - char *sub = xt_find_attr( c, "subscription" ); - - if( jid && sub ) - { - if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) ) - { - imcb_add_buddy( ic, jid, ( group && group->text_len ) ? - group->text : NULL ); - - if( name ) - imcb_rename_buddy( ic, jid, name ); - } - else if( strcmp( sub, "remove" ) == 0 ) - { - jabber_buddy_remove_bare( ic, jid ); - imcb_remove_buddy( ic, jid, NULL ); + while ((c = xt_find_node(c, "item"))) { + struct xt_node *group = xt_find_node(c->children, "group"); + char *jid = xt_find_attr(c, "jid"); + char *name = xt_find_attr(c, "name"); + char *sub = xt_find_attr(c, "subscription"); + + if (jid && sub) { + if ((strcmp(sub, "both") == 0 || strcmp(sub, "to") == 0)) { + imcb_add_buddy(ic, jid, (group && group->text_len) ? + group->text : NULL); + + if (name) { + imcb_rename_buddy(ic, jid, name); + } + } else if (strcmp(sub, "remove") == 0) { + jabber_buddy_remove_bare(ic, jid); + imcb_remove_buddy(ic, jid, NULL); } } - + c = c->next; } - - if( initial ) - imcb_connected( ic ); - + + if (initial) { + imcb_connected(ic); + } + return XT_HANDLED; } -int jabber_get_vcard( struct im_connection *ic, char *bare_jid ) +int jabber_get_vcard(struct im_connection *ic, char *bare_jid) { struct xt_node *node; - - if( strchr( bare_jid, '/' ) ) - return 1; /* This was an error, but return 0 should only be done if the connection died... */ - - node = xt_new_node( "vCard", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_VCARD ); - node = jabber_make_packet( "iq", "get", bare_jid, node ); - - jabber_cache_add( ic, node, jabber_iq_display_vcard ); - return jabber_write_packet( ic, node ); + + if (strchr(bare_jid, '/')) { + return 1; /* This was an error, but return 0 should only be done if the connection died... */ + + } + node = xt_new_node("vCard", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_VCARD); + node = jabber_make_packet("iq", "get", bare_jid, node); + + jabber_cache_add(ic, node, jabber_iq_display_vcard); + return jabber_write_packet(ic, node); } -static xt_status jabber_iq_display_vcard( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct xt_node *vc, *c, *sc; /* subchild, ic is already in use ;-) */ GString *reply; char *s; - - if( ( s = xt_find_attr( node, "type" ) ) == NULL || - strcmp( s, "result" ) != 0 || - ( vc = xt_find_node( node->children, "vCard" ) ) == NULL ) - { - s = xt_find_attr( orig, "to" ); /* If this returns NULL something's wrong.. */ - imcb_log( ic, "Could not retrieve vCard of %s", s ? s : "(NULL)" ); + + if ((s = xt_find_attr(node, "type")) == NULL || + strcmp(s, "result") != 0 || + (vc = xt_find_node(node->children, "vCard")) == NULL) { + s = xt_find_attr(orig, "to"); /* If this returns NULL something's wrong.. */ + imcb_log(ic, "Could not retrieve vCard of %s", s ? s : "(NULL)"); return XT_HANDLED; } - - s = xt_find_attr( orig, "to" ); - reply = g_string_new( "vCard information for " ); - reply = g_string_append( reply, s ? s : "(NULL)" ); - reply = g_string_append( reply, ":\n" ); - + + s = xt_find_attr(orig, "to"); + reply = g_string_new("vCard information for "); + reply = g_string_append(reply, s ? s : "(NULL)"); + reply = g_string_append(reply, ":\n"); + /* I hate this format, I really do... */ - - if( ( c = xt_find_node( vc->children, "FN" ) ) && c->text_len ) - g_string_append_printf( reply, "Name: %s\n", c->text ); - - if( ( c = xt_find_node( vc->children, "N" ) ) && c->children ) - { - reply = g_string_append( reply, "Full name:" ); - - if( ( sc = xt_find_node( c->children, "PREFIX" ) ) && sc->text_len ) - g_string_append_printf( reply, " %s", sc->text ); - if( ( sc = xt_find_node( c->children, "GIVEN" ) ) && sc->text_len ) - g_string_append_printf( reply, " %s", sc->text ); - if( ( sc = xt_find_node( c->children, "MIDDLE" ) ) && sc->text_len ) - g_string_append_printf( reply, " %s", sc->text ); - if( ( sc = xt_find_node( c->children, "FAMILY" ) ) && sc->text_len ) - g_string_append_printf( reply, " %s", sc->text ); - if( ( sc = xt_find_node( c->children, "SUFFIX" ) ) && sc->text_len ) - g_string_append_printf( reply, " %s", sc->text ); - - reply = g_string_append_c( reply, '\n' ); - } - - if( ( c = xt_find_node( vc->children, "NICKNAME" ) ) && c->text_len ) - g_string_append_printf( reply, "Nickname: %s\n", c->text ); - - if( ( c = xt_find_node( vc->children, "BDAY" ) ) && c->text_len ) - g_string_append_printf( reply, "Date of birth: %s\n", c->text ); - + + if ((c = xt_find_node(vc->children, "FN")) && c->text_len) { + g_string_append_printf(reply, "Name: %s\n", c->text); + } + + if ((c = xt_find_node(vc->children, "N")) && c->children) { + reply = g_string_append(reply, "Full name:"); + + if ((sc = xt_find_node(c->children, "PREFIX")) && sc->text_len) { + g_string_append_printf(reply, " %s", sc->text); + } + if ((sc = xt_find_node(c->children, "GIVEN")) && sc->text_len) { + g_string_append_printf(reply, " %s", sc->text); + } + if ((sc = xt_find_node(c->children, "MIDDLE")) && sc->text_len) { + g_string_append_printf(reply, " %s", sc->text); + } + if ((sc = xt_find_node(c->children, "FAMILY")) && sc->text_len) { + g_string_append_printf(reply, " %s", sc->text); + } + if ((sc = xt_find_node(c->children, "SUFFIX")) && sc->text_len) { + g_string_append_printf(reply, " %s", sc->text); + } + + reply = g_string_append_c(reply, '\n'); + } + + if ((c = xt_find_node(vc->children, "NICKNAME")) && c->text_len) { + g_string_append_printf(reply, "Nickname: %s\n", c->text); + } + + if ((c = xt_find_node(vc->children, "BDAY")) && c->text_len) { + g_string_append_printf(reply, "Date of birth: %s\n", c->text); + } + /* Slightly alternative use of for... ;-) */ - for( c = vc->children; ( c = xt_find_node( c, "EMAIL" ) ); c = c->next ) - { - if( ( sc = xt_find_node( c->children, "USERID" ) ) == NULL || sc->text_len == 0 ) + for (c = vc->children; (c = xt_find_node(c, "EMAIL")); c = c->next) { + if ((sc = xt_find_node(c->children, "USERID")) == NULL || sc->text_len == 0) { continue; - - if( xt_find_node( c->children, "HOME" ) ) + } + + if (xt_find_node(c->children, "HOME")) { s = "Home"; - else if( xt_find_node( c->children, "WORK" ) ) + } else if (xt_find_node(c->children, "WORK")) { s = "Work"; - else + } else { s = "Misc."; - - g_string_append_printf( reply, "%s e-mail address: %s\n", s, sc->text ); + } + + g_string_append_printf(reply, "%s e-mail address: %s\n", s, sc->text); } - - if( ( c = xt_find_node( vc->children, "URL" ) ) && c->text_len ) - g_string_append_printf( reply, "Homepage: %s\n", c->text ); - + + if ((c = xt_find_node(vc->children, "URL")) && c->text_len) { + g_string_append_printf(reply, "Homepage: %s\n", c->text); + } + /* Slightly alternative use of for... ;-) */ - for( c = vc->children; ( c = xt_find_node( c, "ADR" ) ); c = c->next ) - { - if( xt_find_node( c->children, "HOME" ) ) + for (c = vc->children; (c = xt_find_node(c, "ADR")); c = c->next) { + if (xt_find_node(c->children, "HOME")) { s = "Home"; - else if( xt_find_node( c->children, "WORK" ) ) + } else if (xt_find_node(c->children, "WORK")) { s = "Work"; - else + } else { s = "Misc."; - - g_string_append_printf( reply, "%s address: ", s ); - - if( ( sc = xt_find_node( c->children, "STREET" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s ", sc->text ); - if( ( sc = xt_find_node( c->children, "EXTADR" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s, ", sc->text ); - if( ( sc = xt_find_node( c->children, "PCODE" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s, ", sc->text ); - if( ( sc = xt_find_node( c->children, "LOCALITY" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s, ", sc->text ); - if( ( sc = xt_find_node( c->children, "REGION" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s, ", sc->text ); - if( ( sc = xt_find_node( c->children, "CTRY" ) ) && sc->text_len ) - g_string_append_printf( reply, "%s", sc->text ); - - if( reply->str[reply->len-2] == ',' ) - reply = g_string_truncate( reply, reply->len-2 ); - - reply = g_string_append_c( reply, '\n' ); - } - - for( c = vc->children; ( c = xt_find_node( c, "TEL" ) ); c = c->next ) - { - if( ( sc = xt_find_node( c->children, "NUMBER" ) ) == NULL || sc->text_len == 0 ) + } + + g_string_append_printf(reply, "%s address: ", s); + + if ((sc = xt_find_node(c->children, "STREET")) && sc->text_len) { + g_string_append_printf(reply, "%s ", sc->text); + } + if ((sc = xt_find_node(c->children, "EXTADR")) && sc->text_len) { + g_string_append_printf(reply, "%s, ", sc->text); + } + if ((sc = xt_find_node(c->children, "PCODE")) && sc->text_len) { + g_string_append_printf(reply, "%s, ", sc->text); + } + if ((sc = xt_find_node(c->children, "LOCALITY")) && sc->text_len) { + g_string_append_printf(reply, "%s, ", sc->text); + } + if ((sc = xt_find_node(c->children, "REGION")) && sc->text_len) { + g_string_append_printf(reply, "%s, ", sc->text); + } + if ((sc = xt_find_node(c->children, "CTRY")) && sc->text_len) { + g_string_append_printf(reply, "%s", sc->text); + } + + if (reply->str[reply->len - 2] == ',') { + reply = g_string_truncate(reply, reply->len - 2); + } + + reply = g_string_append_c(reply, '\n'); + } + + for (c = vc->children; (c = xt_find_node(c, "TEL")); c = c->next) { + if ((sc = xt_find_node(c->children, "NUMBER")) == NULL || sc->text_len == 0) { continue; - - if( xt_find_node( c->children, "HOME" ) ) + } + + if (xt_find_node(c->children, "HOME")) { s = "Home"; - else if( xt_find_node( c->children, "WORK" ) ) + } else if (xt_find_node(c->children, "WORK")) { s = "Work"; - else + } else { s = "Misc."; - - g_string_append_printf( reply, "%s phone number: %s\n", s, sc->text ); + } + + g_string_append_printf(reply, "%s phone number: %s\n", s, sc->text); + } + + if ((c = xt_find_node(vc->children, "DESC")) && c->text_len) { + g_string_append_printf(reply, "Other information:\n%s", c->text); } - - if( ( c = xt_find_node( vc->children, "DESC" ) ) && c->text_len ) - g_string_append_printf( reply, "Other information:\n%s", c->text ); - + /* *sigh* */ - - imcb_log( ic, "%s", reply->str ); - g_string_free( reply, TRUE ); - + + imcb_log(ic, "%s", reply->str); + g_string_free(reply, TRUE); + return XT_HANDLED; } -static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_add_to_roster_callback(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group ) +int jabber_add_to_roster(struct im_connection *ic, const char *handle, const char *name, const char *group) { struct xt_node *node; int st; - + /* Build the item entry */ - node = xt_new_node( "item", NULL, NULL ); - xt_add_attr( node, "jid", handle ); - if( name ) - xt_add_attr( node, "name", name ); - if( group ) - xt_add_child( node, xt_new_node( "group", group, NULL ) ); - + node = xt_new_node("item", NULL, NULL); + xt_add_attr(node, "jid", handle); + if (name) { + xt_add_attr(node, "name", name); + } + if (group) { + xt_add_child(node, xt_new_node("group", group, NULL)); + } + /* And pack it into a roster-add packet */ - node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_ROSTER ); - node = jabber_make_packet( "iq", "set", NULL, node ); - jabber_cache_add( ic, node, jabber_add_to_roster_callback ); - - st = jabber_write_packet( ic, node ); - + node = xt_new_node("query", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_ROSTER); + node = jabber_make_packet("iq", "set", NULL, node); + jabber_cache_add(ic, node, jabber_add_to_roster_callback); + + st = jabber_write_packet(ic, node); + return st; } -static xt_status jabber_add_to_roster_callback( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_add_to_roster_callback(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { char *s, *jid = NULL; struct xt_node *c; - - if( ( c = xt_find_node( orig->children, "query" ) ) && - ( c = xt_find_node( c->children, "item" ) ) && - ( jid = xt_find_attr( c, "jid" ) ) && - ( s = xt_find_attr( node, "type" ) ) && - strcmp( s, "result" ) == 0 ) - { - if( bee_user_by_handle( ic->bee, ic, jid ) == NULL ) - imcb_add_buddy( ic, jid, NULL ); - } - else - { - imcb_log( ic, "Error while adding `%s' to your contact list.", - jid ? jid : "(unknown handle)" ); - } - + + if ((c = xt_find_node(orig->children, "query")) && + (c = xt_find_node(c->children, "item")) && + (jid = xt_find_attr(c, "jid")) && + (s = xt_find_attr(node, "type")) && + strcmp(s, "result") == 0) { + if (bee_user_by_handle(ic->bee, ic, jid) == NULL) { + imcb_add_buddy(ic, jid, NULL); + } + } else { + imcb_log(ic, "Error while adding `%s' to your contact list.", + jid ? jid : "(unknown handle)"); + } + return XT_HANDLED; } -int jabber_remove_from_roster( struct im_connection *ic, char *handle ) +int jabber_remove_from_roster(struct im_connection *ic, char *handle) { struct xt_node *node; int st; - + /* Build the item entry */ - node = xt_new_node( "item", NULL, NULL ); - xt_add_attr( node, "jid", handle ); - xt_add_attr( node, "subscription", "remove" ); - + node = xt_new_node("item", NULL, NULL); + xt_add_attr(node, "jid", handle); + xt_add_attr(node, "subscription", "remove"); + /* And pack it into a roster-add packet */ - node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_ROSTER ); - node = jabber_make_packet( "iq", "set", NULL, node ); - - st = jabber_write_packet( ic, node ); - - xt_free_node( node ); + node = xt_new_node("query", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_ROSTER); + node = jabber_make_packet("iq", "set", NULL, node); + + st = jabber_write_packet(ic, node); + + xt_free_node(node); return st; } -xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +xt_status jabber_iq_parse_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ) +xt_status jabber_iq_query_features(struct im_connection *ic, char *bare_jid) { struct xt_node *node, *query; struct jabber_buddy *bud; - - if( ( bud = jabber_buddy_by_jid( ic, bare_jid , 0 ) ) == NULL ) - { + + if ((bud = jabber_buddy_by_jid(ic, bare_jid, 0)) == NULL) { /* Who cares about the unknown... */ - imcb_log( ic, "Couldn't find buddy: %s", bare_jid); + imcb_log(ic, "Couldn't find buddy: %s", bare_jid); return XT_HANDLED; } - - if( bud->features ) /* been here already */ + + if (bud->features) { /* been here already */ return XT_HANDLED; - - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO ); - - if( !( query = jabber_make_packet( "iq", "get", bare_jid, node ) ) ) - { - imcb_log( ic, "WARNING: Couldn't generate feature query" ); - xt_free_node( node ); + } + + node = xt_new_node("query", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_DISCO_INFO); + + if (!(query = jabber_make_packet("iq", "get", bare_jid, node))) { + imcb_log(ic, "WARNING: Couldn't generate feature query"); + xt_free_node(node); return XT_HANDLED; } - jabber_cache_add( ic, query, jabber_iq_parse_features ); + jabber_cache_add(ic, query, jabber_iq_parse_features); - return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; + return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT; } -xt_status jabber_iq_parse_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +xt_status jabber_iq_parse_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct xt_node *c; struct jabber_buddy *bud; char *feature, *xmlns, *from; - if( !( from = xt_find_attr( node, "from" ) ) || - !( c = xt_find_node( node->children, "query" ) ) || - !( xmlns = xt_find_attr( c, "xmlns" ) ) || - !( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) ) - { - imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); + if (!(from = xt_find_attr(node, "from")) || + !(c = xt_find_node(node->children, "query")) || + !(xmlns = xt_find_attr(c, "xmlns")) || + !(strcmp(xmlns, XMLNS_DISCO_INFO) == 0)) { + imcb_log(ic, "WARNING: Received incomplete IQ-result packet for discover"); return XT_HANDLED; } - if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) - { + if ((bud = jabber_buddy_by_jid(ic, from, 0)) == NULL) { /* Who cares about the unknown... */ - imcb_log( ic, "Couldn't find buddy: %s", from ); + imcb_log(ic, "Couldn't find buddy: %s", from); return XT_HANDLED; } - + c = c->children; - while( ( c = xt_find_node( c, "feature" ) ) ) - { - feature = xt_find_attr( c, "var" ); - if( feature ) - bud->features = g_slist_append( bud->features, g_strdup( feature ) ); + while ((c = xt_find_node(c, "feature"))) { + feature = xt_find_attr(c, "var"); + if (feature) { + bud->features = g_slist_append(bud->features, g_strdup(feature)); + } c = c->next; } return XT_HANDLED; } -xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ) +xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns) { struct xt_node *node, *query; struct jabber_data *jd = ic->proto_data; - - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", xmlns ); - - if( !( query = jabber_make_packet( "iq", "get", jid, node ) ) ) - { - imcb_log( ic, "WARNING: Couldn't generate server query" ); - xt_free_node( node ); + + node = xt_new_node("query", NULL, NULL); + xt_add_attr(node, "xmlns", xmlns); + + if (!(query = jabber_make_packet("iq", "get", jid, node))) { + imcb_log(ic, "WARNING: Couldn't generate server query"); + xt_free_node(node); } jd->have_streamhosts--; - jabber_cache_add( ic, query, jabber_iq_parse_server_features ); + jabber_cache_add(ic, query, jabber_iq_parse_server_features); - return jabber_write_packet( ic, query ) ? XT_HANDLED : XT_ABORT; + return jabber_write_packet(ic, query) ? XT_HANDLED : XT_ABORT; } /* * Query the server for "items", query each "item" for identities, query each "item" that's a proxy for it's bytestream info */ -xt_status jabber_iq_parse_server_features( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +xt_status jabber_iq_parse_server_features(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct xt_node *c; struct jabber_data *jd = ic->proto_data; char *xmlns, *from; - if( !( c = xt_find_node( node->children, "query" ) ) || - !( from = xt_find_attr( node, "from" ) ) || - !( xmlns = xt_find_attr( c, "xmlns" ) ) ) - { - imcb_log( ic, "WARNING: Received incomplete IQ-result packet for discover" ); + if (!(c = xt_find_node(node->children, "query")) || + !(from = xt_find_attr(node, "from")) || + !(xmlns = xt_find_attr(c, "xmlns"))) { + imcb_log(ic, "WARNING: Received incomplete IQ-result packet for discover"); return XT_HANDLED; } jd->have_streamhosts++; - if( strcmp( xmlns, XMLNS_DISCO_ITEMS ) == 0 ) - { + if (strcmp(xmlns, XMLNS_DISCO_ITEMS) == 0) { char *itemjid; /* answer from server */ - + c = c->children; - while( ( c = xt_find_node( c, "item" ) ) ) - { - itemjid = xt_find_attr( c, "jid" ); - - if( itemjid ) - jabber_iq_query_server( ic, itemjid, XMLNS_DISCO_INFO ); + while ((c = xt_find_node(c, "item"))) { + itemjid = xt_find_attr(c, "jid"); + + if (itemjid) { + jabber_iq_query_server(ic, itemjid, XMLNS_DISCO_INFO); + } c = c->next; } - } - else if( strcmp( xmlns, XMLNS_DISCO_INFO ) == 0 ) - { + } else if (strcmp(xmlns, XMLNS_DISCO_INFO) == 0) { char *category, *type; /* answer from potential proxy */ c = c->children; - while( ( c = xt_find_node( c, "identity" ) ) ) - { - category = xt_find_attr( c, "category" ); - type = xt_find_attr( c, "type" ); + while ((c = xt_find_node(c, "identity"))) { + category = xt_find_attr(c, "category"); + type = xt_find_attr(c, "type"); - if( type && ( strcmp( type, "bytestreams" ) == 0 ) && - category && ( strcmp( category, "proxy" ) == 0 ) ) - jabber_iq_query_server( ic, from, XMLNS_BYTESTREAMS ); + if (type && (strcmp(type, "bytestreams") == 0) && + category && (strcmp(category, "proxy") == 0)) { + jabber_iq_query_server(ic, from, XMLNS_BYTESTREAMS); + } c = c->next; } - } - else if( strcmp( xmlns, XMLNS_BYTESTREAMS ) == 0 ) - { + } else if (strcmp(xmlns, XMLNS_BYTESTREAMS) == 0) { char *host, *jid, *port_s; int port; /* answer from proxy */ - if( ( c = xt_find_node( c->children, "streamhost" ) ) && - ( host = xt_find_attr( c, "host" ) ) && - ( port_s = xt_find_attr( c, "port" ) ) && - ( sscanf( port_s, "%d", &port ) == 1 ) && - ( jid = xt_find_attr( c, "jid" ) ) ) - { - jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 ); - - sh->jid = g_strdup( jid ); - sh->host = g_strdup( host ); - g_snprintf( sh->port, sizeof( sh->port ), "%u", port ); + if ((c = xt_find_node(c->children, "streamhost")) && + (host = xt_find_attr(c, "host")) && + (port_s = xt_find_attr(c, "port")) && + (sscanf(port_s, "%d", &port) == 1) && + (jid = xt_find_attr(c, "jid"))) { + jabber_streamhost_t *sh = g_new0(jabber_streamhost_t, 1); - imcb_log( ic, "Proxy found: jid %s host %s port %u", jid, host, port ); - jd->streamhosts = g_slist_append( jd->streamhosts, sh ); + sh->jid = g_strdup(jid); + sh->host = g_strdup(host); + g_snprintf(sh->port, sizeof(sh->port), "%u", port); + + imcb_log(ic, "Proxy found: jid %s host %s port %u", jid, host, port); + jd->streamhosts = g_slist_append(jd->streamhosts, sh); } } - if( jd->have_streamhosts == 0 ) + if (jd->have_streamhosts == 0) { jd->have_streamhosts++; + } return XT_HANDLED; } -static xt_status jabber_iq_version_response( struct im_connection *ic, - struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_iq_version_response(struct im_connection *ic, + struct xt_node *node, struct xt_node *orig); -void jabber_iq_version_send( struct im_connection *ic, struct jabber_buddy *bud, void *data ) +void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data) { struct xt_node *node, *query; - - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_VERSION ); - query = jabber_make_packet( "iq", "get", bud->full_jid, node ); - jabber_cache_add( ic, query, jabber_iq_version_response ); - jabber_write_packet( ic, query ); + node = xt_new_node("query", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_VERSION); + query = jabber_make_packet("iq", "get", bud->full_jid, node); + jabber_cache_add(ic, query, jabber_iq_version_response); + + jabber_write_packet(ic, query); } -static xt_status jabber_iq_version_response( struct im_connection *ic, - struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_iq_version_response(struct im_connection *ic, + struct xt_node *node, struct xt_node *orig) { struct xt_node *query; GString *rets; @@ -865,65 +826,67 @@ static xt_status jabber_iq_version_response( struct im_connection *ic, char *ret[2] = {}; bee_user_t *bu; struct jabber_buddy *bud = NULL; - - if( ( s = xt_find_attr( node, "from" ) ) && - ( bud = jabber_buddy_by_jid( ic, s, 0 ) ) && - ( query = xt_find_node( node->children, "query" ) ) && - ( bu = bee_user_by_handle( ic->bee, ic, bud->bare_jid ) ) ) - { - rets = g_string_new( "Resource " ); - g_string_append( rets, bud->resource ); - } - else + + if ((s = xt_find_attr(node, "from")) && + (bud = jabber_buddy_by_jid(ic, s, 0)) && + (query = xt_find_node(node->children, "query")) && + (bu = bee_user_by_handle(ic->bee, ic, bud->bare_jid))) { + rets = g_string_new("Resource "); + g_string_append(rets, bud->resource); + } else { return XT_HANDLED; - - for( query = query->children; query; query = query->next ) - if( query->text_len > 0 ) - g_string_append_printf( rets, " %s: %s,", query->name, query->text ); - - g_string_truncate( rets, rets->len - 1 ); + } + + for (query = query->children; query; query = query->next) { + if (query->text_len > 0) { + g_string_append_printf(rets, " %s: %s,", query->name, query->text); + } + } + + g_string_truncate(rets, rets->len - 1); ret[0] = rets->str; - imcb_buddy_action_response( bu, "VERSION", ret, NULL ); - g_string_free( rets, TRUE ); - + imcb_buddy_action_response(bu, "VERSION", ret, NULL); + g_string_free(rets, TRUE); + return XT_HANDLED; } -static xt_status jabber_iq_disco_server_response( struct im_connection *ic, - struct xt_node *node, struct xt_node *orig ); +static xt_status jabber_iq_disco_server_response(struct im_connection *ic, + struct xt_node *node, struct xt_node *orig); -static int jabber_iq_disco_server( struct im_connection *ic ) +static int jabber_iq_disco_server(struct im_connection *ic) { struct xt_node *node, *iq; struct jabber_data *jd = ic->proto_data; - - node = xt_new_node( "query", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_DISCO_INFO ); - iq = jabber_make_packet( "iq", "get", jd->server, node ); - - jabber_cache_add( ic, iq, jabber_iq_disco_server_response ); - return jabber_write_packet( ic, iq ); + + node = xt_new_node("query", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_DISCO_INFO); + iq = jabber_make_packet("iq", "get", jd->server, node); + + jabber_cache_add(ic, iq, jabber_iq_disco_server_response); + return jabber_write_packet(ic, iq); } -static xt_status jabber_iq_disco_server_response( struct im_connection *ic, - struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_iq_disco_server_response(struct im_connection *ic, + struct xt_node *node, struct xt_node *orig) { struct jabber_data *jd = ic->proto_data; struct xt_node *id; - - if( ( id = xt_find_path( node, "query/identity" ) ) ) - { + + if ((id = xt_find_path(node, "query/identity"))) { char *cat, *type, *name; - - if( !( cat = xt_find_attr( id, "category" ) ) || - !( type = xt_find_attr( id, "type" ) ) || - !( name = xt_find_attr( id, "name" ) ) ) + + if (!(cat = xt_find_attr(id, "category")) || + !(type = xt_find_attr(id, "type")) || + !(name = xt_find_attr(id, "name"))) { return XT_HANDLED; - - if( strcmp( cat, "server" ) == 0 && strcmp( type, "im" ) == 0 && - strstr( name, "Google" ) != NULL ) + } + + if (strcmp(cat, "server") == 0 && strcmp(type, "im") == 0 && + strstr(name, "Google") != NULL) { jd->flags |= JFLAG_GTALK; + } } - + return XT_HANDLED; } diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c index b6fbb6b9..1ad5ecb6 100644 --- a/protocols/jabber/jabber.c +++ b/protocols/jabber/jabber.c @@ -53,411 +53,413 @@ static const int jabber_port_list[] = { 0 }; -static void jabber_init( account_t *acc ) +static void jabber_init(account_t *acc) { set_t *s; char str[16]; - - s = set_add( &acc->set, "activity_timeout", "600", set_eval_int, acc ); - - s = set_add( &acc->set, "oauth", "false", set_eval_oauth, acc ); - - s = set_add( &acc->set, "display_name", NULL, NULL, acc ); - - g_snprintf( str, sizeof( str ), "%d", jabber_port_list[0] ); - s = set_add( &acc->set, "port", str, set_eval_int, acc ); + + s = set_add(&acc->set, "activity_timeout", "600", set_eval_int, acc); + + s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc); + + s = set_add(&acc->set, "display_name", NULL, NULL, acc); + + g_snprintf(str, sizeof(str), "%d", jabber_port_list[0]); + s = set_add(&acc->set, "port", str, set_eval_int, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "priority", "0", set_eval_priority, acc ); - s = set_add( &acc->set, "proxy", "<local>;<auto>", NULL, acc ); - - s = set_add( &acc->set, "resource", "BitlBee", NULL, acc ); + s = set_add(&acc->set, "priority", "0", set_eval_priority, acc); + + s = set_add(&acc->set, "proxy", "<local>;<auto>", NULL, acc); + + s = set_add(&acc->set, "resource", "BitlBee", NULL, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "resource_select", "activity", NULL, acc ); - - s = set_add( &acc->set, "sasl", "true", set_eval_bool, acc ); + + s = set_add(&acc->set, "resource_select", "activity", NULL, acc); + + s = set_add(&acc->set, "sasl", "true", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY | SET_HIDDEN_DEFAULT; - - s = set_add( &acc->set, "server", NULL, set_eval_account, acc ); + + s = set_add(&acc->set, "server", NULL, set_eval_account, acc); s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK; - - s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc ); + + s = set_add(&acc->set, "ssl", "false", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "tls", "true", set_eval_tls, acc ); + + s = set_add(&acc->set, "tls", "true", set_eval_tls, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - - s = set_add( &acc->set, "tls_verify", "true", set_eval_bool, acc ); + + s = set_add(&acc->set, "tls_verify", "true", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - s = set_add( &acc->set, "user_agent", "BitlBee", NULL, acc ); - - s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc ); + s = set_add(&acc->set, "user_agent", "BitlBee", NULL, acc); + + s = set_add(&acc->set, "xmlconsole", "false", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | ACC_FLAG_HANDLE_DOMAINS; } -static void jabber_generate_id_hash( struct jabber_data *jd ); +static void jabber_generate_id_hash(struct jabber_data *jd); -static void jabber_login( account_t *acc ) +static void jabber_login(account_t *acc) { - struct im_connection *ic = imcb_new( acc ); - struct jabber_data *jd = g_new0( struct jabber_data, 1 ); + struct im_connection *ic = imcb_new(acc); + struct jabber_data *jd = g_new0(struct jabber_data, 1); char *s; - + /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events on dead connections. */ - jabber_connections = g_slist_prepend( jabber_connections, ic ); - + jabber_connections = g_slist_prepend(jabber_connections, ic); + jd->ic = ic; ic->proto_data = jd; - - jabber_set_me( ic, acc->user ); - + + jabber_set_me(ic, acc->user); + jd->fd = jd->r_inpa = jd->w_inpa = -1; - - if( jd->server == NULL ) - { - imcb_error( ic, "Incomplete account name (format it like <username@jabberserver.name>)" ); - imc_logout( ic, FALSE ); + + if (jd->server == NULL) { + imcb_error(ic, "Incomplete account name (format it like <username@jabberserver.name>)"); + imc_logout(ic, FALSE); return; } - - if( ( s = strchr( jd->server, '/' ) ) ) - { + + if ((s = strchr(jd->server, '/'))) { *s = 0; - set_setstr( &acc->set, "resource", s + 1 ); - + set_setstr(&acc->set, "resource", s + 1); + /* Also remove the /resource from the original variable so we won't have to do this again every time. */ - s = strchr( acc->user, '/' ); + s = strchr(acc->user, '/'); *s = 0; } - - jd->node_cache = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, jabber_cache_entry_free ); - jd->buddies = g_hash_table_new( g_str_hash, g_str_equal ); - - if( set_getbool( &acc->set, "oauth" ) ) - { + + jd->node_cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, jabber_cache_entry_free); + jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); + + if (set_getbool(&acc->set, "oauth")) { GSList *p_in = NULL; const char *tok; - + jd->fd = jd->r_inpa = jd->w_inpa = -1; - - if( strstr( jd->server, ".facebook.com" ) ) + + if (strstr(jd->server, ".facebook.com")) { jd->oauth2_service = &oauth2_service_facebook; - else + } else { jd->oauth2_service = &oauth2_service_google; - - oauth_params_parse( &p_in, ic->acc->pass ); - + } + + oauth_params_parse(&p_in, ic->acc->pass); + /* First see if we have a refresh token, in which case any access token we *might* have has probably expired already anyway. */ - if( ( tok = oauth_params_get( &p_in, "refresh_token" ) ) ) - { - sasl_oauth2_refresh( ic, tok ); + if ((tok = oauth_params_get(&p_in, "refresh_token"))) { + sasl_oauth2_refresh(ic, tok); } /* If we don't have a refresh token, let's hope the access token is still usable. */ - else if( ( tok = oauth_params_get( &p_in, "access_token" ) ) ) - { - jd->oauth2_access_token = g_strdup( tok ); - jabber_connect( ic ); + else if ((tok = oauth_params_get(&p_in, "access_token"))) { + jd->oauth2_access_token = g_strdup(tok); + jabber_connect(ic); } /* If we don't have any, start the OAuth process now. Don't even open an XMPP connection yet. */ - else - { - sasl_oauth2_init( ic ); + else { + sasl_oauth2_init(ic); ic->flags |= OPT_SLOW_LOGIN; } - - oauth_params_free( &p_in ); + + oauth_params_free(&p_in); + } else { + jabber_connect(ic); } - else - jabber_connect( ic ); } /* Separate this from jabber_login() so we can do OAuth first if necessary. Putting this in io.c would probably be more correct. */ -void jabber_connect( struct im_connection *ic ) +void jabber_connect(struct im_connection *ic) { account_t *acc = ic->acc; struct jabber_data *jd = ic->proto_data; int i; char *connect_to; struct ns_srv_reply **srvl = NULL, *srv = NULL; - + /* Figure out the hostname to connect to. */ - if( acc->server && *acc->server ) + if (acc->server && *acc->server) { connect_to = acc->server; - else if( ( srvl = srv_lookup( "xmpp-client", "tcp", jd->server ) ) || - ( srvl = srv_lookup( "jabber-client", "tcp", jd->server ) ) ) - { + } else if ((srvl = srv_lookup("xmpp-client", "tcp", jd->server)) || + (srvl = srv_lookup("jabber-client", "tcp", jd->server))) { /* Find the lowest-priority one. These usually come back in random/shuffled order. Not looking at weights etc for now. */ srv = *srvl; - for( i = 1; srvl[i]; i ++ ) - if( srvl[i]->prio < srv->prio ) + for (i = 1; srvl[i]; i++) { + if (srvl[i]->prio < srv->prio) { srv = srvl[i]; - + } + } + connect_to = srv->name; - } - else + } else { connect_to = jd->server; - - imcb_log( ic, "Connecting" ); - - for( i = 0; jabber_port_list[i] > 0; i ++ ) - if( set_getint( &acc->set, "port" ) == jabber_port_list[i] ) + } + + imcb_log(ic, "Connecting"); + + for (i = 0; jabber_port_list[i] > 0; i++) { + if (set_getint(&acc->set, "port") == jabber_port_list[i]) { break; + } + } - if( jabber_port_list[i] == 0 ) - { - imcb_log( ic, "Illegal port number" ); - imc_logout( ic, FALSE ); + if (jabber_port_list[i] == 0) { + imcb_log(ic, "Illegal port number"); + imc_logout(ic, FALSE); return; } - + /* For non-SSL connections we can try to use the port # from the SRV reply, but let's not do that when using SSL, SSL usually runs on non-standard ports... */ - if( set_getbool( &acc->set, "ssl" ) ) - { - jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), set_getbool( &acc->set, "tls_verify" ), jabber_connected_ssl, ic ); - jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1; - } - else - { - jd->fd = proxy_connect( connect_to, srv ? srv->port : set_getint( &acc->set, "port" ), jabber_connected_plain, ic ); - } - srv_free( srvl ); - - if( jd->fd == -1 ) - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); - + if (set_getbool(&acc->set, "ssl")) { + jd->ssl = ssl_connect(connect_to, set_getint(&acc->set, "port"), set_getbool(&acc->set, + "tls_verify"), jabber_connected_ssl, + ic); + jd->fd = jd->ssl ? ssl_getfd(jd->ssl) : -1; + } else { + jd->fd = proxy_connect(connect_to, srv ? srv->port : set_getint(&acc->set, + "port"), jabber_connected_plain, ic); + } + srv_free(srvl); + + if (jd->fd == -1) { + imcb_error(ic, "Could not connect to server"); + imc_logout(ic, TRUE); + return; } - - if( set_getbool( &acc->set, "xmlconsole" ) ) - { + + if (set_getbool(&acc->set, "xmlconsole")) { jd->flags |= JFLAG_XMLCONSOLE; /* Shouldn't really do this at this stage already, maybe. But I think this shouldn't break anything. */ - imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); + imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL); } - - jabber_generate_id_hash( jd ); + + jabber_generate_id_hash(jd); } /* This generates an unfinished md5_state_t variable. Every time we generate an ID, we finish the state by adding a sequence number and take the hash. */ -static void jabber_generate_id_hash( struct jabber_data *jd ) +static void jabber_generate_id_hash(struct jabber_data *jd) { md5_byte_t binbuf[4]; char *s; - - md5_init( &jd->cached_id_prefix ); - md5_append( &jd->cached_id_prefix, (unsigned char *) jd->username, strlen( jd->username ) ); - md5_append( &jd->cached_id_prefix, (unsigned char *) jd->server, strlen( jd->server ) ); - s = set_getstr( &jd->ic->acc->set, "resource" ); - md5_append( &jd->cached_id_prefix, (unsigned char *) s, strlen( s ) ); - random_bytes( binbuf, 4 ); - md5_append( &jd->cached_id_prefix, binbuf, 4 ); + + md5_init(&jd->cached_id_prefix); + md5_append(&jd->cached_id_prefix, (unsigned char *) jd->username, strlen(jd->username)); + md5_append(&jd->cached_id_prefix, (unsigned char *) jd->server, strlen(jd->server)); + s = set_getstr(&jd->ic->acc->set, "resource"); + md5_append(&jd->cached_id_prefix, (unsigned char *) s, strlen(s)); + random_bytes(binbuf, 4); + md5_append(&jd->cached_id_prefix, binbuf, 4); } -static void jabber_logout( struct im_connection *ic ) +static void jabber_logout(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; - - while( jd->filetransfers ) - imcb_file_canceled( ic, ( ( struct jabber_transfer *) jd->filetransfers->data )->ft, "Logging out" ); - while( jd->streamhosts ) - { + while (jd->filetransfers) { + imcb_file_canceled(ic, (( struct jabber_transfer *) jd->filetransfers->data)->ft, "Logging out"); + } + + while (jd->streamhosts) { jabber_streamhost_t *sh = jd->streamhosts->data; - jd->streamhosts = g_slist_remove( jd->streamhosts, sh ); - g_free( sh->jid ); - g_free( sh->host ); - g_free( sh ); - } - - if( jd->fd >= 0 ) - jabber_end_stream( ic ); - - while( ic->groupchats ) - jabber_chat_free( ic->groupchats->data ); - - if( jd->r_inpa >= 0 ) - b_event_remove( jd->r_inpa ); - if( jd->w_inpa >= 0 ) - b_event_remove( jd->w_inpa ); - - if( jd->ssl ) - ssl_disconnect( jd->ssl ); - if( jd->fd >= 0 ) - closesocket( jd->fd ); - - if( jd->tx_len ) - g_free( jd->txq ); - - if( jd->node_cache ) - g_hash_table_destroy( jd->node_cache ); - - jabber_buddy_remove_all( ic ); - - xt_free( jd->xt ); - - md5_free( &jd->cached_id_prefix ); - - g_free( jd->oauth2_access_token ); - g_free( jd->away_message ); - g_free( jd->internal_jid ); - g_free( jd->username ); - g_free( jd->me ); - g_free( jd ); - - jabber_connections = g_slist_remove( jabber_connections, ic ); + jd->streamhosts = g_slist_remove(jd->streamhosts, sh); + g_free(sh->jid); + g_free(sh->host); + g_free(sh); + } + + if (jd->fd >= 0) { + jabber_end_stream(ic); + } + + while (ic->groupchats) { + jabber_chat_free(ic->groupchats->data); + } + + if (jd->r_inpa >= 0) { + b_event_remove(jd->r_inpa); + } + if (jd->w_inpa >= 0) { + b_event_remove(jd->w_inpa); + } + + if (jd->ssl) { + ssl_disconnect(jd->ssl); + } + if (jd->fd >= 0) { + closesocket(jd->fd); + } + + if (jd->tx_len) { + g_free(jd->txq); + } + + if (jd->node_cache) { + g_hash_table_destroy(jd->node_cache); + } + + jabber_buddy_remove_all(ic); + + xt_free(jd->xt); + + md5_free(&jd->cached_id_prefix); + + g_free(jd->oauth2_access_token); + g_free(jd->away_message); + g_free(jd->internal_jid); + g_free(jd->username); + g_free(jd->me); + g_free(jd); + + jabber_connections = g_slist_remove(jabber_connections, ic); } -static int jabber_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) +static int jabber_buddy_msg(struct im_connection *ic, char *who, char *message, int flags) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; struct xt_node *node; char *s; int st; - - if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) - return jabber_write( ic, message, strlen( message ) ); - - if( g_strcasecmp( who, JABBER_OAUTH_HANDLE ) == 0 && - !( jd->flags & OPT_LOGGED_IN ) && jd->fd == -1 ) - { - if( sasl_oauth2_get_refresh_token( ic, message ) ) - { + + if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) { + return jabber_write(ic, message, strlen(message)); + } + + if (g_strcasecmp(who, JABBER_OAUTH_HANDLE) == 0 && + !(jd->flags & OPT_LOGGED_IN) && jd->fd == -1) { + if (sasl_oauth2_get_refresh_token(ic, message)) { return 1; - } - else - { - imcb_error( ic, "OAuth failure" ); - imc_logout( ic, TRUE ); + } else { + imcb_error(ic, "OAuth failure"); + imc_logout(ic, TRUE); return 0; } } - - if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) ) - bud = jabber_buddy_by_ext_jid( ic, who, 0 ); - else - bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_BARE_OK ); - - node = xt_new_node( "body", message, NULL ); - node = jabber_make_packet( "message", "chat", bud ? bud->full_jid : who, node ); - - if( bud && ( jd->flags & JFLAG_WANT_TYPING ) && - ( ( bud->flags & JBFLAG_DOES_XEP85 ) || - !( bud->flags & JBFLAG_PROBED_XEP85 ) ) ) - { + + if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { + bud = jabber_buddy_by_ext_jid(ic, who, 0); + } else { + bud = jabber_buddy_by_jid(ic, who, GET_BUDDY_BARE_OK); + } + + node = xt_new_node("body", message, NULL); + node = jabber_make_packet("message", "chat", bud ? bud->full_jid : who, node); + + if (bud && (jd->flags & JFLAG_WANT_TYPING) && + ((bud->flags & JBFLAG_DOES_XEP85) || + !(bud->flags & JBFLAG_PROBED_XEP85))) { struct xt_node *act; - + /* If the user likes typing notification and if we don't know (and didn't probe before) if this resource supports XEP85, include a probe in this packet now. Also, if we know this buddy does support XEP85, we have to send this <active/> tag to tell that the user stopped typing (well, that's what we guess when s/he pressed Enter...). */ - act = xt_new_node( "active", NULL, NULL ); - xt_add_attr( act, "xmlns", XMLNS_CHATSTATES ); - xt_add_child( node, act ); - + act = xt_new_node("active", NULL, NULL); + xt_add_attr(act, "xmlns", XMLNS_CHATSTATES); + xt_add_child(node, act); + /* Just make sure we do this only once. */ bud->flags |= JBFLAG_PROBED_XEP85; } - - st = jabber_write_packet( ic, node ); - xt_free_node( node ); - + + st = jabber_write_packet(ic, node); + xt_free_node(node); + return st; } -static GList *jabber_away_states( struct im_connection *ic ) +static GList *jabber_away_states(struct im_connection *ic) { static GList *l = NULL; int i; - - if( l == NULL ) - for( i = 0; jabber_away_state_list[i].full_name; i ++ ) - l = g_list_append( l, (void*) jabber_away_state_list[i].full_name ); - + + if (l == NULL) { + for (i = 0; jabber_away_state_list[i].full_name; i++) { + l = g_list_append(l, (void *) jabber_away_state_list[i].full_name); + } + } + return l; } -static void jabber_get_info( struct im_connection *ic, char *who ) +static void jabber_get_info(struct im_connection *ic, char *who) { struct jabber_buddy *bud; - - bud = jabber_buddy_by_jid( ic, who, GET_BUDDY_FIRST ); - - while( bud ) - { - imcb_log( ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority ); - if( bud->away_state ) - imcb_log( ic, "Away state: %s", bud->away_state->full_name ); - imcb_log( ic, "Status message: %s", bud->away_message ? bud->away_message : "(none)" ); - + + bud = jabber_buddy_by_jid(ic, who, GET_BUDDY_FIRST); + + while (bud) { + imcb_log(ic, "Buddy %s (%d) information:", bud->full_jid, bud->priority); + if (bud->away_state) { + imcb_log(ic, "Away state: %s", bud->away_state->full_name); + } + imcb_log(ic, "Status message: %s", bud->away_message ? bud->away_message : "(none)"); + bud = bud->next; } - - jabber_get_vcard( ic, bud ? bud->full_jid : who ); + + jabber_get_vcard(ic, bud ? bud->full_jid : who); } -static void jabber_set_away( struct im_connection *ic, char *state_txt, char *message ) +static void jabber_set_away(struct im_connection *ic, char *state_txt, char *message) { struct jabber_data *jd = ic->proto_data; - + /* state_txt == NULL -> Not away. Unknown state -> fall back to the first defined away state. */ - if( state_txt == NULL ) + if (state_txt == NULL) { jd->away_state = NULL; - else if( ( jd->away_state = jabber_away_state_by_name( state_txt ) ) == NULL ) + } else if ((jd->away_state = jabber_away_state_by_name(state_txt)) == NULL) { jd->away_state = jabber_away_state_list; - - g_free( jd->away_message ); - jd->away_message = ( message && *message ) ? g_strdup( message ) : NULL; - - presence_send_update( ic ); + } + + g_free(jd->away_message); + jd->away_message = (message && *message) ? g_strdup(message) : NULL; + + presence_send_update(ic); } -static void jabber_add_buddy( struct im_connection *ic, char *who, char *group ) +static void jabber_add_buddy(struct im_connection *ic, char *who, char *group) { struct jabber_data *jd = ic->proto_data; - - if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) - { + + if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) { jd->flags |= JFLAG_XMLCONSOLE; - imcb_add_buddy( ic, JABBER_XMLCONSOLE_HANDLE, NULL ); + imcb_add_buddy(ic, JABBER_XMLCONSOLE_HANDLE, NULL); return; } - - if( jabber_add_to_roster( ic, who, NULL, group ) ) - presence_send_request( ic, who, "subscribe" ); + + if (jabber_add_to_roster(ic, who, NULL, group)) { + presence_send_request(ic, who, "subscribe"); + } } -static void jabber_remove_buddy( struct im_connection *ic, char *who, char *group ) +static void jabber_remove_buddy(struct im_connection *ic, char *who, char *group) { struct jabber_data *jd = ic->proto_data; - - if( g_strcasecmp( who, JABBER_XMLCONSOLE_HANDLE ) == 0 ) - { + + if (g_strcasecmp(who, JABBER_XMLCONSOLE_HANDLE) == 0) { jd->flags &= ~JFLAG_XMLCONSOLE; /* Not necessary for now. And for now the code isn't too happy if the buddy is completely gone right after calling @@ -466,184 +468,194 @@ static void jabber_remove_buddy( struct im_connection *ic, char *who, char *grou */ return; } - + /* We should always do this part. Clean up our administration a little bit. */ - jabber_buddy_remove_bare( ic, who ); - - if( jabber_remove_from_roster( ic, who ) ) - presence_send_request( ic, who, "unsubscribe" ); + jabber_buddy_remove_bare(ic, who); + + if (jabber_remove_from_roster(ic, who)) { + presence_send_request(ic, who, "unsubscribe"); + } } -static struct groupchat *jabber_chat_join_( struct im_connection *ic, const char *room, const char *nick, const char *password, set_t **sets ) +static struct groupchat *jabber_chat_join_(struct im_connection *ic, const char *room, const char *nick, + const char *password, set_t **sets) { struct jabber_data *jd = ic->proto_data; char *final_nick; - + /* Ignore the passed nick parameter if we have our own default */ - if ( !( final_nick = set_getstr( sets, "nick" ) ) && - !( final_nick = set_getstr( &ic->acc->set, "display_name" ) ) ) { + if (!(final_nick = set_getstr(sets, "nick")) && + !(final_nick = set_getstr(&ic->acc->set, "display_name"))) { /* Well, whatever, actually use the provided default, then */ final_nick = (char *) nick; } - if( strchr( room, '@' ) == NULL ) - imcb_error( ic, "%s is not a valid Jabber room name. Maybe you mean %s@conference.%s?", - room, room, jd->server ); - else if( jabber_chat_by_jid( ic, room ) ) - imcb_error( ic, "Already present in chat `%s'", room ); - else - return jabber_chat_join( ic, room, final_nick, set_getstr( sets, "password" ) ); - + if (strchr(room, '@') == NULL) { + imcb_error(ic, "%s is not a valid Jabber room name. Maybe you mean %s@conference.%s?", + room, room, jd->server); + } else if (jabber_chat_by_jid(ic, room)) { + imcb_error(ic, "Already present in chat `%s'", room); + } else { + return jabber_chat_join(ic, room, final_nick, set_getstr(sets, "password")); + } + return NULL; } -static struct groupchat *jabber_chat_with_( struct im_connection *ic, char *who ) +static struct groupchat *jabber_chat_with_(struct im_connection *ic, char *who) { - return jabber_chat_with( ic, who ); + return jabber_chat_with(ic, who); } -static void jabber_chat_msg_( struct groupchat *c, char *message, int flags ) +static void jabber_chat_msg_(struct groupchat *c, char *message, int flags) { - if( c && message ) - jabber_chat_msg( c, message, flags ); + if (c && message) { + jabber_chat_msg(c, message, flags); + } } -static void jabber_chat_topic_( struct groupchat *c, char *topic ) +static void jabber_chat_topic_(struct groupchat *c, char *topic) { - if( c && topic ) - jabber_chat_topic( c, topic ); + if (c && topic) { + jabber_chat_topic(c, topic); + } } -static void jabber_chat_leave_( struct groupchat *c ) +static void jabber_chat_leave_(struct groupchat *c) { - if( c ) - jabber_chat_leave( c, NULL ); + if (c) { + jabber_chat_leave(c, NULL); + } } -static void jabber_chat_invite_( struct groupchat *c, char *who, char *msg ) +static void jabber_chat_invite_(struct groupchat *c, char *who, char *msg) { struct jabber_data *jd = c->ic->proto_data; struct jabber_chat *jc = c->data; gchar *msg_alt = NULL; - if( msg == NULL ) - msg_alt = g_strdup_printf( "%s invited you to %s", jd->me, jc->name ); - - if( c && who ) - jabber_chat_invite( c, who, msg ? msg : msg_alt ); - - g_free( msg_alt ); + if (msg == NULL) { + msg_alt = g_strdup_printf("%s invited you to %s", jd->me, jc->name); + } + + if (c && who) { + jabber_chat_invite(c, who, msg ? msg : msg_alt); + } + + g_free(msg_alt); } -static void jabber_keepalive( struct im_connection *ic ) +static void jabber_keepalive(struct im_connection *ic) { /* Just any whitespace character is enough as a keepalive for XMPP sessions. */ - if( !jabber_write( ic, "\n", 1 ) ) + if (!jabber_write(ic, "\n", 1)) { return; - + } + /* This runs the garbage collection every minute, which means every packet is in the cache for about a minute (which should be enough AFAIK). */ - jabber_cache_clean( ic ); + jabber_cache_clean(ic); } -static int jabber_send_typing( struct im_connection *ic, char *who, int typing ) +static int jabber_send_typing(struct im_connection *ic, char *who, int typing) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; - + /* Enable typing notification related code from now. */ jd->flags |= JFLAG_WANT_TYPING; - - if( ( bud = jabber_buddy_by_jid( ic, who, 0 ) ) == NULL ) - { + + if ((bud = jabber_buddy_by_jid(ic, who, 0)) == NULL) { /* Sending typing notifications to unknown buddies is unsupported for now. Shouldn't be a problem, I think. */ return 0; } - - if( bud->flags & JBFLAG_DOES_XEP85 ) - { + + if (bud->flags & JBFLAG_DOES_XEP85) { /* We're only allowed to send this stuff if we know the other side supports it. */ - + struct xt_node *node; char *type; int st; - - if( typing & OPT_TYPING ) + + if (typing & OPT_TYPING) { type = "composing"; - else if( typing & OPT_THINKING ) + } else if (typing & OPT_THINKING) { type = "paused"; - else + } else { type = "active"; - - node = xt_new_node( type, NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_CHATSTATES ); - node = jabber_make_packet( "message", "chat", bud->full_jid, node ); - - st = jabber_write_packet( ic, node ); - xt_free_node( node ); - + } + + node = xt_new_node(type, NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_CHATSTATES); + node = jabber_make_packet("message", "chat", bud->full_jid, node); + + st = jabber_write_packet(ic, node); + xt_free_node(node); + return st; } - + return 1; } -void jabber_chat_add_settings( account_t *acc, set_t **head ) +void jabber_chat_add_settings(account_t *acc, set_t **head) { /* Meh. Stupid room passwords. Not trying to obfuscate/hide them from the user for now. */ - set_add( head, "password", NULL, NULL, NULL ); + set_add(head, "password", NULL, NULL, NULL); } -void jabber_chat_free_settings( account_t *acc, set_t **head ) +void jabber_chat_free_settings(account_t *acc, set_t **head) { - set_del( head, "password" ); + set_del(head, "password"); } -GList *jabber_buddy_action_list( bee_user_t *bu ) +GList *jabber_buddy_action_list(bee_user_t *bu) { static GList *ret = NULL; - - if( ret == NULL ) - { + + if (ret == NULL) { static const struct buddy_action ba[2] = { { "VERSION", "Get client (version) information" }, }; - - ret = g_list_prepend( ret, (void*) ba + 0 ); + + ret = g_list_prepend(ret, (void *) ba + 0); } - + return ret; } -void *jabber_buddy_action( struct bee_user *bu, const char *action, char * const args[], void *data ) +void *jabber_buddy_action(struct bee_user *bu, const char *action, char * const args[], void *data) { - if( g_strcasecmp( action, "VERSION" ) == 0 ) - { + if (g_strcasecmp(action, "VERSION") == 0) { struct jabber_buddy *bud; - - if( ( bud = jabber_buddy_by_ext_jid( bu->ic, bu->handle, 0 ) ) == NULL ) - bud = jabber_buddy_by_jid( bu->ic, bu->handle, GET_BUDDY_FIRST ); - for( ; bud; bud = bud->next ) - jabber_iq_version_send( bu->ic, bud, data ); + + if ((bud = jabber_buddy_by_ext_jid(bu->ic, bu->handle, 0)) == NULL) { + bud = jabber_buddy_by_jid(bu->ic, bu->handle, GET_BUDDY_FIRST); + } + for (; bud; bud = bud->next) { + jabber_iq_version_send(bu->ic, bud, data); + } } - + return NULL; } -gboolean jabber_handle_is_self( struct im_connection *ic, const char *who ) { +gboolean jabber_handle_is_self(struct im_connection *ic, const char *who) +{ struct jabber_data *jd = ic->proto_data; - return ( ( g_strcasecmp( who, ic->acc->user ) == 0 ) || - ( jd->internal_jid && - g_strcasecmp( who, jd->internal_jid ) == 0 ) ); + + return ((g_strcasecmp(who, ic->acc->user) == 0) || + (jd->internal_jid && + g_strcasecmp(who, jd->internal_jid) == 0)); } void jabber_initmodule() { - struct prpl *ret = g_new0( struct prpl, 1 ); - + struct prpl *ret = g_new0(struct prpl, 1); + ret->name = "jabber"; ret->mms = 0; /* no limit */ ret->login = jabber_login; @@ -672,5 +684,5 @@ void jabber_initmodule() ret->buddy_action_list = jabber_buddy_action_list; ret->buddy_action = jabber_buddy_action; - register_protocol( ret ); + register_protocol(ret); } diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h index a5882767..f991465e 100644 --- a/protocols/jabber/jabber.h +++ b/protocols/jabber/jabber.h @@ -32,14 +32,13 @@ extern GSList *jabber_connections; -typedef enum -{ +typedef enum { JFLAG_STREAM_STARTED = 1, /* Set when we detected the beginning of the stream and want to do auth. */ JFLAG_AUTHENTICATED = 2, /* Set when we're successfully authenticatd. */ JFLAG_STREAM_RESTART = 4, /* Set when we want to restart the stream (after SASL or TLS). */ - JFLAG_WANT_SESSION = 8, /* Set if the server wants a <session/> tag + JFLAG_WANT_SESSION = 8, /* Set if the server wants a <session/> tag before we continue. */ JFLAG_WANT_BIND = 16, /* ... for <bind> tag. */ JFLAG_WANT_TYPING = 32, /* Set if we ever sent a typing notification, this @@ -52,8 +51,7 @@ typedef enum JFLAG_SASL_FB = 0x10000, /* Trying Facebook authentication. */ } jabber_flags_t; -typedef enum -{ +typedef enum { JBFLAG_PROBED_XEP85 = 1, /* Set this when we sent our probe packet to make sure it gets sent only once. */ JBFLAG_DOES_XEP85 = 2, /* Set this when the resource seems to support @@ -67,45 +65,42 @@ typedef enum } jabber_buddy_flags_t; /* Stores a streamhost's (a.k.a. proxy) data */ -typedef struct -{ +typedef struct { char *jid; char *host; char port[6]; } jabber_streamhost_t; -typedef enum -{ +typedef enum { JCFLAG_MESSAGE_SENT = 1, /* Set this after sending the first message, so we can detect echoes/backlogs. */ } jabber_chat_flags_t; -struct jabber_data -{ +struct jabber_data { struct im_connection *ic; - + int fd; void *ssl; char *txq; int tx_len; int r_inpa, w_inpa; - + struct xt_parser *xt; jabber_flags_t flags; - - char *username; /* USERNAME@server */ - char *server; /* username@SERVER -=> server/domain, not hostname */ - char *me; /* bare jid */ + + char *username; /* USERNAME@server */ + char *server; /* username@SERVER -=> server/domain, not hostname */ + char *me; /* bare jid */ char *internal_jid; - + const struct oauth2_service *oauth2_service; char *oauth2_access_token; - + /* After changing one of these two (or the priority setting), call presence_send_update() to inform the server about the changes. */ const struct jabber_away_state *away_state; char *away_message; - + md5_state_t cached_id_prefix; GHashTable *node_cache; GHashTable *buddies; @@ -115,16 +110,14 @@ struct jabber_data int have_streamhosts; }; -struct jabber_away_state -{ +struct jabber_away_state { char code[5]; char *full_name; }; -typedef xt_status (*jabber_cache_event) ( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); +typedef xt_status (*jabber_cache_event) (struct im_connection *ic, struct xt_node *node, struct xt_node *orig); -struct jabber_cache_entry -{ +struct jabber_cache_entry { time_t saved_at; struct xt_node *node; jabber_cache_event func; @@ -137,28 +130,26 @@ struct jabber_cache_entry follow. In that case, the bare JID at the beginning doesn't actually refer to a real session and should only be used for operations that support incomplete JIDs. */ -struct jabber_buddy -{ +struct jabber_buddy { char *bare_jid; char *full_jid; char *resource; - + char *ext_jid; /* The JID to use in BitlBee. The real JID if possible, */ /* otherwise something similar to the conference JID. */ - + int priority; struct jabber_away_state *away_state; char *away_message; GSList *features; - + time_t last_msg; jabber_buddy_flags_t flags; - + struct jabber_buddy *next; }; -struct jabber_chat -{ +struct jabber_chat { int flags; char *name; char *my_full_jid; /* Separate copy because of case sensitivity. */ @@ -166,8 +157,7 @@ struct jabber_chat char *invite; }; -struct jabber_transfer -{ +struct jabber_transfer { /* bitlbee's handle for this transfer */ file_transfer_t *ft; @@ -245,111 +235,109 @@ struct jabber_transfer #define XMLNS_IBB "http://jabber.org/protocol/ibb" /* XEP-0047 */ /* jabber.c */ -void jabber_connect( struct im_connection *ic ); +void jabber_connect(struct im_connection *ic); /* iq.c */ -xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ); -int jabber_init_iq_auth( struct im_connection *ic ); -xt_status jabber_pkt_bind_sess( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -int jabber_get_roster( struct im_connection *ic ); -int jabber_get_vcard( struct im_connection *ic, char *bare_jid ); -int jabber_add_to_roster( struct im_connection *ic, const char *handle, const char *name, const char *group ); -int jabber_remove_from_roster( struct im_connection *ic, char *handle ); -xt_status jabber_iq_query_features( struct im_connection *ic, char *bare_jid ); -xt_status jabber_iq_query_server( struct im_connection *ic, char *jid, char *xmlns ); -void jabber_iq_version_send( struct im_connection *ic, struct jabber_buddy *bud, void *data ); +xt_status jabber_pkt_iq(struct xt_node *node, gpointer data); +int jabber_init_iq_auth(struct im_connection *ic); +xt_status jabber_pkt_bind_sess(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +int jabber_get_roster(struct im_connection *ic); +int jabber_get_vcard(struct im_connection *ic, char *bare_jid); +int jabber_add_to_roster(struct im_connection *ic, const char *handle, const char *name, const char *group); +int jabber_remove_from_roster(struct im_connection *ic, char *handle); +xt_status jabber_iq_query_features(struct im_connection *ic, char *bare_jid); +xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns); +void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data); /* si.c */ -int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode ); -void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); -void jabber_si_free_transfer( file_transfer_t *ft); +int jabber_si_handle_request(struct im_connection *ic, struct xt_node *node, struct xt_node *sinode); +void jabber_si_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *who); +void jabber_si_free_transfer(file_transfer_t *ft); /* s5bytestream.c */ -int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode); -gboolean jabber_bs_send_start( struct jabber_transfer *tf ); -gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len ); +int jabber_bs_recv_request(struct im_connection *ic, struct xt_node *node, struct xt_node *qnode); +gboolean jabber_bs_send_start(struct jabber_transfer *tf); +gboolean jabber_bs_send_write(file_transfer_t *ft, char *buffer, unsigned int len); /* message.c */ -xt_status jabber_pkt_message( struct xt_node *node, gpointer data ); +xt_status jabber_pkt_message(struct xt_node *node, gpointer data); /* presence.c */ -xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ); -int presence_send_update( struct im_connection *ic ); -int presence_send_request( struct im_connection *ic, char *handle, char *request ); +xt_status jabber_pkt_presence(struct xt_node *node, gpointer data); +int presence_send_update(struct im_connection *ic); +int presence_send_request(struct im_connection *ic, char *handle, char *request); /* jabber_util.c */ -char *set_eval_priority( set_t *set, char *value ); -char *set_eval_tls( set_t *set, char *value ); -struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ); -struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ); -void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ); -struct xt_node *jabber_cache_get( struct im_connection *ic, char *id ); -void jabber_cache_entry_free( gpointer entry ); -void jabber_cache_clean( struct im_connection *ic ); -xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ); -const struct jabber_away_state *jabber_away_state_by_code( char *code ); -const struct jabber_away_state *jabber_away_state_by_name( char *name ); -void jabber_buddy_ask( struct im_connection *ic, char *handle ); -int jabber_compare_jid( const char *jid1, const char *jid2 ); -char *jabber_normalize( const char *orig ); - -typedef enum -{ - GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */ - GET_BUDDY_EXACT = 2, /* Get an exact match (only makes sense with bare JIDs). */ - GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */ - GET_BUDDY_BARE = 8, /* Get the bare version of the JID (possibly inexistent). */ - GET_BUDDY_BARE_OK = 16, /* Allow returning a bare JID if that seems better. */ +char *set_eval_priority(set_t *set, char *value); +char *set_eval_tls(set_t *set, char *value); +struct xt_node *jabber_make_packet(char *name, char *type, char *to, struct xt_node *children); +struct xt_node *jabber_make_error_packet(struct xt_node *orig, char *err_cond, char *err_type, char *err_code); +void jabber_cache_add(struct im_connection *ic, struct xt_node *node, jabber_cache_event func); +struct xt_node *jabber_cache_get(struct im_connection *ic, char *id); +void jabber_cache_entry_free(gpointer entry); +void jabber_cache_clean(struct im_connection *ic); +xt_status jabber_cache_handle_packet(struct im_connection *ic, struct xt_node *node); +const struct jabber_away_state *jabber_away_state_by_code(char *code); +const struct jabber_away_state *jabber_away_state_by_name(char *name); +void jabber_buddy_ask(struct im_connection *ic, char *handle); +int jabber_compare_jid(const char *jid1, const char *jid2); +char *jabber_normalize(const char *orig); + +typedef enum { + GET_BUDDY_CREAT = 1, /* Try to create it, if necessary. */ + GET_BUDDY_EXACT = 2, /* Get an exact match (only makes sense with bare JIDs). */ + GET_BUDDY_FIRST = 4, /* No selection, simply get the first resource for this JID. */ + GET_BUDDY_BARE = 8, /* Get the bare version of the JID (possibly inexistent). */ + GET_BUDDY_BARE_OK = 16, /* Allow returning a bare JID if that seems better. */ } get_buddy_flags_t; -struct jabber_error -{ +struct jabber_error { char *code, *text, *type; }; -struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid ); -struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); -struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid, get_buddy_flags_t flags ); -int jabber_buddy_remove( struct im_connection *ic, char *full_jid ); -int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ); -void jabber_buddy_remove_all( struct im_connection *ic ); -time_t jabber_get_timestamp( struct xt_node *xt ); -struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ); -void jabber_error_free( struct jabber_error *err ); -gboolean jabber_set_me( struct im_connection *ic, const char *me ); +struct jabber_buddy *jabber_buddy_add(struct im_connection *ic, char *full_jid); +struct jabber_buddy *jabber_buddy_by_jid(struct im_connection *ic, char *jid, get_buddy_flags_t flags); +struct jabber_buddy *jabber_buddy_by_ext_jid(struct im_connection *ic, char *jid, get_buddy_flags_t flags); +int jabber_buddy_remove(struct im_connection *ic, char *full_jid); +int jabber_buddy_remove_bare(struct im_connection *ic, char *bare_jid); +void jabber_buddy_remove_all(struct im_connection *ic); +time_t jabber_get_timestamp(struct xt_node *xt); +struct jabber_error *jabber_error_parse(struct xt_node *node, char *xmlns); +void jabber_error_free(struct jabber_error *err); +gboolean jabber_set_me(struct im_connection *ic, const char *me); extern const struct jabber_away_state jabber_away_state_list[]; /* io.c */ -int jabber_write_packet( struct im_connection *ic, struct xt_node *node ); -int jabber_write( struct im_connection *ic, char *buf, int len ); -gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond ); -gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond ); -gboolean jabber_start_stream( struct im_connection *ic ); -void jabber_end_stream( struct im_connection *ic ); +int jabber_write_packet(struct im_connection *ic, struct xt_node *node); +int jabber_write(struct im_connection *ic, char *buf, int len); +gboolean jabber_connected_plain(gpointer data, gint source, b_input_condition cond); +gboolean jabber_connected_ssl(gpointer data, int returncode, void *source, b_input_condition cond); +gboolean jabber_start_stream(struct im_connection *ic); +void jabber_end_stream(struct im_connection *ic); /* sasl.c */ -xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ); -xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ); -xt_status sasl_pkt_result( struct xt_node *node, gpointer data ); -gboolean sasl_supported( struct im_connection *ic ); -void sasl_oauth2_init( struct im_connection *ic ); -int sasl_oauth2_get_refresh_token( struct im_connection *ic, const char *msg ); -int sasl_oauth2_refresh( struct im_connection *ic, const char *refresh_token ); +xt_status sasl_pkt_mechanisms(struct xt_node *node, gpointer data); +xt_status sasl_pkt_challenge(struct xt_node *node, gpointer data); +xt_status sasl_pkt_result(struct xt_node *node, gpointer data); +gboolean sasl_supported(struct im_connection *ic); +void sasl_oauth2_init(struct im_connection *ic); +int sasl_oauth2_get_refresh_token(struct im_connection *ic, const char *msg); +int sasl_oauth2_refresh(struct im_connection *ic, const char *refresh_token); extern const struct oauth2_service oauth2_service_google; extern const struct oauth2_service oauth2_service_facebook; /* conference.c */ -struct groupchat *jabber_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password ); -struct groupchat *jabber_chat_with( struct im_connection *ic, char *who ); -struct groupchat *jabber_chat_by_jid( struct im_connection *ic, const char *name ); -void jabber_chat_free( struct groupchat *c ); -int jabber_chat_msg( struct groupchat *ic, char *message, int flags ); -int jabber_chat_topic( struct groupchat *c, char *topic ); -int jabber_chat_leave( struct groupchat *c, const char *reason ); -void jabber_chat_pkt_presence( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); -void jabber_chat_pkt_message( struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node ); -void jabber_chat_invite( struct groupchat *c, char *who, char *message ); +struct groupchat *jabber_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password); +struct groupchat *jabber_chat_with(struct im_connection *ic, char *who); +struct groupchat *jabber_chat_by_jid(struct im_connection *ic, const char *name); +void jabber_chat_free(struct groupchat *c); +int jabber_chat_msg(struct groupchat *ic, char *message, int flags); +int jabber_chat_topic(struct groupchat *c, char *topic); +int jabber_chat_leave(struct groupchat *c, const char *reason); +void jabber_chat_pkt_presence(struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node); +void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, struct xt_node *node); +void jabber_chat_invite(struct groupchat *c, char *who, char *message); #endif diff --git a/protocols/jabber/jabber_util.c b/protocols/jabber/jabber_util.c index 0276db9f..b0bc033f 100644 --- a/protocols/jabber/jabber_util.c +++ b/protocols/jabber/jabber_util.c @@ -3,7 +3,7 @@ * BitlBee - An IRC to IM gateway * * Jabber module - Misc. stuff * * * -* Copyright 2006-2010 Wilmer van der Gaast <wilmer@gaast.net> +* Copyright 2006-2010 Wilmer van der Gaast <wilmer@gaast.net> * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -27,204 +27,201 @@ static unsigned int next_id = 1; -char *set_eval_priority( set_t *set, char *value ) +char *set_eval_priority(set_t *set, char *value) { account_t *acc = set->data; int i; - - if( sscanf( value, "%d", &i ) == 1 ) - { + + if (sscanf(value, "%d", &i) == 1) { /* Priority is a signed 8-bit integer, according to RFC 3921. */ - if( i < -128 || i > 127 ) + if (i < -128 || i > 127) { return SET_INVALID; - } - else + } + } else { return SET_INVALID; - + } + /* Only run this stuff if the account is online ATM, and if the setting seems to be acceptable. */ - if( acc->ic ) - { + if (acc->ic) { /* Although set_eval functions usually are very nice and convenient, they have one disadvantage: If I would just call p_s_u() now to send the new prio setting, it would send the old setting because the set->value gets changed after the (this) eval returns a non-NULL value. - + So now I can choose between implementing post-set functions next to evals, or just do this little hack: */ - - g_free( set->value ); - set->value = g_strdup( value ); - + + g_free(set->value); + set->value = g_strdup(value); + /* (Yes, sorry, I prefer the hack. :-P) */ - - presence_send_update( acc->ic ); + + presence_send_update(acc->ic); } - + return value; } -char *set_eval_tls( set_t *set, char *value ) +char *set_eval_tls(set_t *set, char *value) { - if( g_strcasecmp( value, "try" ) == 0 ) + if (g_strcasecmp(value, "try") == 0) { return value; - else - return set_eval_bool( set, value ); + } else { + return set_eval_bool(set, value); + } } -struct xt_node *jabber_make_packet( char *name, char *type, char *to, struct xt_node *children ) +struct xt_node *jabber_make_packet(char *name, char *type, char *to, struct xt_node *children) { struct xt_node *node; - - node = xt_new_node( name, NULL, children ); - - if( type ) - xt_add_attr( node, "type", type ); - if( to ) - xt_add_attr( node, "to", to ); - + + node = xt_new_node(name, NULL, children); + + if (type) { + xt_add_attr(node, "type", type); + } + if (to) { + xt_add_attr(node, "to", to); + } + /* IQ packets should always have an ID, so let's generate one. It might get overwritten by jabber_cache_add() if this packet has to be saved until we receive a response. Cached packets get slightly different IDs so we can recognize them. */ - if( strcmp( name, "iq" ) == 0 ) - { - char *id = g_strdup_printf( "%s%05x", JABBER_PACKET_ID, ( next_id++ ) & 0xfffff ); - xt_add_attr( node, "id", id ); - g_free( id ); + if (strcmp(name, "iq") == 0) { + char *id = g_strdup_printf("%s%05x", JABBER_PACKET_ID, (next_id++) & 0xfffff); + xt_add_attr(node, "id", id); + g_free(id); } - + return node; } -struct xt_node *jabber_make_error_packet( struct xt_node *orig, char *err_cond, char *err_type, char *err_code ) +struct xt_node *jabber_make_error_packet(struct xt_node *orig, char *err_cond, char *err_type, char *err_code) { struct xt_node *node, *c; char *to; - + /* Create the "defined-condition" tag. */ - c = xt_new_node( err_cond, NULL, NULL ); - xt_add_attr( c, "xmlns", XMLNS_STANZA_ERROR ); - + c = xt_new_node(err_cond, NULL, NULL); + xt_add_attr(c, "xmlns", XMLNS_STANZA_ERROR); + /* Put it in an <error> tag. */ - c = xt_new_node( "error", NULL, c ); - xt_add_attr( c, "type", err_type ); - + c = xt_new_node("error", NULL, c); + xt_add_attr(c, "type", err_type); + /* Add the error code, if present */ - if (err_code) - xt_add_attr( c, "code", err_code ); - + if (err_code) { + xt_add_attr(c, "code", err_code); + } + /* To make the actual error packet, we copy the original packet and add our <error>/type="error" tag. Including the original packet is recommended, so let's just do it. */ - node = xt_dup( orig ); - xt_add_child( node, c ); - xt_add_attr( node, "type", "error" ); - + node = xt_dup(orig); + xt_add_child(node, c); + xt_add_attr(node, "type", "error"); + /* Return to sender. */ - if( ( to = xt_find_attr( node, "from" ) ) ) - { - xt_add_attr( node, "to", to ); - xt_remove_attr( node, "from" ); + if ((to = xt_find_attr(node, "from"))) { + xt_add_attr(node, "to", to); + xt_remove_attr(node, "from"); } - + return node; } /* Cache a node/packet for later use. Mainly useful for IQ packets if you need them when you receive the response. Use this BEFORE sending the packet so it'll get a new id= tag, and do NOT free() the packet after sending it! */ -void jabber_cache_add( struct im_connection *ic, struct xt_node *node, jabber_cache_event func ) +void jabber_cache_add(struct im_connection *ic, struct xt_node *node, jabber_cache_event func) { struct jabber_data *jd = ic->proto_data; - struct jabber_cache_entry *entry = g_new0( struct jabber_cache_entry, 1 ); + struct jabber_cache_entry *entry = g_new0(struct jabber_cache_entry, 1); md5_state_t id_hash; md5_byte_t id_sum[16]; char *id, *asc_hash; - - next_id ++; - + + next_id++; + id_hash = jd->cached_id_prefix; - md5_append( &id_hash, (md5_byte_t*) &next_id, sizeof( next_id ) ); - md5_digest_keep( &id_hash, id_sum ); - asc_hash = base64_encode( id_sum, 12 ); - - id = g_strdup_printf( "%s%s", JABBER_CACHED_ID, asc_hash ); - xt_add_attr( node, "id", id ); - g_free( id ); - g_free( asc_hash ); - + md5_append(&id_hash, (md5_byte_t *) &next_id, sizeof(next_id)); + md5_digest_keep(&id_hash, id_sum); + asc_hash = base64_encode(id_sum, 12); + + id = g_strdup_printf("%s%s", JABBER_CACHED_ID, asc_hash); + xt_add_attr(node, "id", id); + g_free(id); + g_free(asc_hash); + entry->node = node; entry->func = func; - entry->saved_at = time( NULL ); - g_hash_table_insert( jd->node_cache, xt_find_attr( node, "id" ), entry ); + entry->saved_at = time(NULL); + g_hash_table_insert(jd->node_cache, xt_find_attr(node, "id"), entry); } -void jabber_cache_entry_free( gpointer data ) +void jabber_cache_entry_free(gpointer data) { struct jabber_cache_entry *entry = data; - - xt_free_node( entry->node ); - g_free( entry ); + + xt_free_node(entry->node); + g_free(entry); } -gboolean jabber_cache_clean_entry( gpointer key, gpointer entry, gpointer nullpointer ); +gboolean jabber_cache_clean_entry(gpointer key, gpointer entry, gpointer nullpointer); /* This one should be called from time to time (from keepalive, in this case) to make sure things don't stay in the node cache forever. By marking nodes during the first run and deleting marked nodes during a next run, every node should be available in the cache for at least a minute (assuming the function is indeed called every minute). */ -void jabber_cache_clean( struct im_connection *ic ) +void jabber_cache_clean(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; - time_t threshold = time( NULL ) - JABBER_CACHE_MAX_AGE; - - g_hash_table_foreach_remove( jd->node_cache, jabber_cache_clean_entry, &threshold ); + time_t threshold = time(NULL) - JABBER_CACHE_MAX_AGE; + + g_hash_table_foreach_remove(jd->node_cache, jabber_cache_clean_entry, &threshold); } -gboolean jabber_cache_clean_entry( gpointer key, gpointer entry_, gpointer threshold_ ) +gboolean jabber_cache_clean_entry(gpointer key, gpointer entry_, gpointer threshold_) { struct jabber_cache_entry *entry = entry_; time_t *threshold = threshold_; - + return entry->saved_at < *threshold; } -xt_status jabber_cache_handle_packet( struct im_connection *ic, struct xt_node *node ) +xt_status jabber_cache_handle_packet(struct im_connection *ic, struct xt_node *node) { struct jabber_data *jd = ic->proto_data; struct jabber_cache_entry *entry; char *s; - - if( ( s = xt_find_attr( node, "id" ) ) == NULL || - strncmp( s, JABBER_CACHED_ID, strlen( JABBER_CACHED_ID ) ) != 0 ) - { + + if ((s = xt_find_attr(node, "id")) == NULL || + strncmp(s, JABBER_CACHED_ID, strlen(JABBER_CACHED_ID)) != 0) { /* Silently ignore it, without an ID (or a non-cache ID) we don't know how to handle the packet and we probably don't have to. */ return XT_HANDLED; } - - entry = g_hash_table_lookup( jd->node_cache, s ); - - if( entry == NULL ) - { + + entry = g_hash_table_lookup(jd->node_cache, s); + + if (entry == NULL) { /* There's no longer an easy way to see if we generated this one or someone else, and there's a ten-minute timeout anyway, so meh. - + imcb_log( ic, "Warning: Received %s-%s packet with unknown/expired ID %s!", node->name, xt_find_attr( node, "type" ) ? : "(no type)", s ); */ + } else if (entry->func) { + return entry->func(ic, node, entry->node); } - else if( entry->func ) - { - return entry->func( ic, node, entry->node ); - } - + return XT_HANDLED; } @@ -237,129 +234,134 @@ const struct jabber_away_state jabber_away_state_list[] = { "", NULL } }; -const struct jabber_away_state *jabber_away_state_by_code( char *code ) +const struct jabber_away_state *jabber_away_state_by_code(char *code) { int i; - - if( code == NULL ) + + if (code == NULL) { return NULL; - - for( i = 0; jabber_away_state_list[i].full_name; i ++ ) - if( g_strcasecmp( jabber_away_state_list[i].code, code ) == 0 ) + } + + for (i = 0; jabber_away_state_list[i].full_name; i++) { + if (g_strcasecmp(jabber_away_state_list[i].code, code) == 0) { return jabber_away_state_list + i; - + } + } + return NULL; } -const struct jabber_away_state *jabber_away_state_by_name( char *name ) +const struct jabber_away_state *jabber_away_state_by_name(char *name) { int i; - - if( name == NULL ) + + if (name == NULL) { return NULL; - - for( i = 0; jabber_away_state_list[i].full_name; i ++ ) - if( g_strcasecmp( jabber_away_state_list[i].full_name, name ) == 0 ) + } + + for (i = 0; jabber_away_state_list[i].full_name; i++) { + if (g_strcasecmp(jabber_away_state_list[i].full_name, name) == 0) { return jabber_away_state_list + i; - + } + } + return NULL; } -struct jabber_buddy_ask_data -{ +struct jabber_buddy_ask_data { struct im_connection *ic; char *handle; char *realname; }; -static void jabber_buddy_ask_yes( void *data ) +static void jabber_buddy_ask_yes(void *data) { struct jabber_buddy_ask_data *bla = data; - - presence_send_request( bla->ic, bla->handle, "subscribed" ); - - imcb_ask_add( bla->ic, bla->handle, NULL ); - - g_free( bla->handle ); - g_free( bla ); + + presence_send_request(bla->ic, bla->handle, "subscribed"); + + imcb_ask_add(bla->ic, bla->handle, NULL); + + g_free(bla->handle); + g_free(bla); } -static void jabber_buddy_ask_no( void *data ) +static void jabber_buddy_ask_no(void *data) { struct jabber_buddy_ask_data *bla = data; - - presence_send_request( bla->ic, bla->handle, "unsubscribed" ); - - g_free( bla->handle ); - g_free( bla ); + + presence_send_request(bla->ic, bla->handle, "unsubscribed"); + + g_free(bla->handle); + g_free(bla); } -void jabber_buddy_ask( struct im_connection *ic, char *handle ) +void jabber_buddy_ask(struct im_connection *ic, char *handle) { - struct jabber_buddy_ask_data *bla = g_new0( struct jabber_buddy_ask_data, 1 ); + struct jabber_buddy_ask_data *bla = g_new0(struct jabber_buddy_ask_data, 1); char *buf; - + bla->ic = ic; - bla->handle = g_strdup( handle ); - - buf = g_strdup_printf( "The user %s wants to add you to his/her buddy list.", handle ); - imcb_ask( ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no ); - g_free( buf ); + bla->handle = g_strdup(handle); + + buf = g_strdup_printf("The user %s wants to add you to his/her buddy list.", handle); + imcb_ask(ic, buf, bla, jabber_buddy_ask_yes, jabber_buddy_ask_no); + g_free(buf); } /* Compares just the bare portions of two Jabber IDs. */ -int jabber_compare_jid( const char *jid1, const char *jid2 ) +int jabber_compare_jid(const char *jid1, const char *jid2) { int i; - - for( i = 0; ; i ++ ) - { - if( jid1[i] == '\0' || jid1[i] == '/' || jid2[i] == '\0' || jid2[i] == '/' ) - { - if( ( jid1[i] == '\0' || jid1[i] == '/' ) && ( jid2[i] == '\0' || jid2[i] == '/' ) ) + + for (i = 0;; i++) { + if (jid1[i] == '\0' || jid1[i] == '/' || jid2[i] == '\0' || jid2[i] == '/') { + if ((jid1[i] == '\0' || jid1[i] == '/') && (jid2[i] == '\0' || jid2[i] == '/')) { break; + } return FALSE; } - if( g_ascii_tolower( jid1[i] ) != g_ascii_tolower( jid2[i] ) ) - { + if (g_ascii_tolower(jid1[i]) != g_ascii_tolower(jid2[i])) { return FALSE; } } - + return TRUE; } /* The /resource part is case sensitive. This stops once we see a slash. Returns a new string. Don't leak it! */ -char *jabber_normalize( const char *orig ) +char *jabber_normalize(const char *orig) { char *lower, *new, *s; - if ( ! ( s = strchr( orig, '/' ) ) ) - return g_utf8_strdown( orig, -1 ); + if (!(s = strchr(orig, '/'))) { + return g_utf8_strdown(orig, -1); + } - lower = g_utf8_strdown( orig, (s - orig) ); /* stop in s */ - new = g_strconcat( lower, s, NULL ); - g_free( lower ); + lower = g_utf8_strdown(orig, (s - orig)); /* stop in s */ + new = g_strconcat(lower, s, NULL); + g_free(lower); return new; } /* Similar to jabber_normalize, but works with addresses in the form * resource=chatroom@example.com */ -char *jabber_normalize_ext( const char *orig ) +char *jabber_normalize_ext(const char *orig) { char *lower, *new, *s; - if ( ! ( s = strchr( orig, '=' ) ) ) - return g_utf8_strdown( orig, -1 ); + if (!(s = strchr(orig, '='))) { + return g_utf8_strdown(orig, -1); + } - lower = g_utf8_strdown( s, -1 ); /* start in s */ + lower = g_utf8_strdown(s, -1); /* start in s */ *s = 0; - new = g_strconcat( orig, lower, NULL ); + new = g_strconcat(orig, lower, NULL); *s = '='; - g_free( lower ); + g_free(lower); return new; } @@ -368,192 +370,183 @@ char *jabber_normalize_ext( const char *orig ) buddies from transports don't (usually) have resources. So we'll really have to deal with that properly. Set their ->resource property to NULL. Do *NOT* allow to mix this stuff, though... */ -struct jabber_buddy *jabber_buddy_add( struct im_connection *ic, char *full_jid_ ) +struct jabber_buddy *jabber_buddy_add(struct im_connection *ic, char *full_jid_) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *new, *bi; char *s, *full_jid; - - full_jid = jabber_normalize( full_jid_ ); - - if( ( s = strchr( full_jid, '/' ) ) ) + + full_jid = jabber_normalize(full_jid_); + + if ((s = strchr(full_jid, '/'))) { *s = 0; - - new = g_new0( struct jabber_buddy, 1 ); - - if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) - { + } + + new = g_new0(struct jabber_buddy, 1); + + if ((bud = g_hash_table_lookup(jd->buddies, full_jid))) { /* The first entry is always a bare JID. If there are more, we should ignore the first one here. */ - if( bud->next ) + if (bud->next) { bud = bud->next; - + } + /* If this is a transport buddy or whatever, it can't have more than one instance, so this is always wrong: */ - if( s == NULL || bud->resource == NULL ) - { - if( s ) *s = '/'; - g_free( new ); - g_free( full_jid ); + if (s == NULL || bud->resource == NULL) { + if (s) { + *s = '/'; + } + g_free(new); + g_free(full_jid); return NULL; } - + new->bare_jid = bud->bare_jid; - + /* We already have another resource for this buddy, add the new one to the list. */ - for( bi = bud; bi; bi = bi->next ) - { + for (bi = bud; bi; bi = bi->next) { /* Check for dupes. */ - if( strcmp( bi->resource, s + 1 ) == 0 ) - { + if (strcmp(bi->resource, s + 1) == 0) { *s = '/'; - g_free( new ); - g_free( full_jid ); + g_free(new); + g_free(full_jid); return NULL; } /* Append the new item to the list. */ - else if( bi->next == NULL ) - { + else if (bi->next == NULL) { bi->next = new; break; } } - } - else - { - new->full_jid = new->bare_jid = g_strdup( full_jid ); - g_hash_table_insert( jd->buddies, new->bare_jid, new ); - - if( s ) - { - new->next = g_new0( struct jabber_buddy, 1 ); + } else { + new->full_jid = new->bare_jid = g_strdup(full_jid); + g_hash_table_insert(jd->buddies, new->bare_jid, new); + + if (s) { + new->next = g_new0(struct jabber_buddy, 1); new->next->bare_jid = new->bare_jid; new = new->next; } } - - if( s ) - { + + if (s) { *s = '/'; new->full_jid = full_jid; - new->resource = strchr( new->full_jid, '/' ) + 1; - } - else - { + new->resource = strchr(new->full_jid, '/') + 1; + } else { /* Let's waste some more bytes of RAM instead of to make memory management a total disaster here. And it saves me one g_free() call in this function. :-P */ new->full_jid = full_jid; } - + return new; } /* Finds a buddy from our structures. Can find both full- and bare JIDs. When asked for a bare JID, it uses the "resource_select" setting to see which resource to pick. */ -struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) +struct jabber_buddy *jabber_buddy_by_jid(struct im_connection *ic, char *jid_, get_buddy_flags_t flags) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *head; char *s, *jid; - - jid = jabber_normalize( jid_ ); - - if( ( s = strchr( jid, '/' ) ) ) - { + + jid = jabber_normalize(jid_); + + if ((s = strchr(jid, '/'))) { int bare_exists = 0; - + *s = 0; - if( ( bud = g_hash_table_lookup( jd->buddies, jid ) ) ) - { + if ((bud = g_hash_table_lookup(jd->buddies, jid))) { bare_exists = 1; - - if( bud->next ) + + if (bud->next) { bud = bud->next; - + } + /* Just return the first one for this bare JID. */ - if( flags & GET_BUDDY_FIRST ) - { + if (flags & GET_BUDDY_FIRST) { *s = '/'; - g_free( jid ); + g_free(jid); return bud; } - + /* Is this one of those no-resource buddies? */ - if( bud->resource == NULL ) - { + if (bud->resource == NULL) { *s = '/'; - g_free( jid ); + g_free(jid); return NULL; } - + /* See if there's an exact match. */ - for( ; bud; bud = bud->next ) - if( strcmp( bud->resource, s + 1 ) == 0 ) + for (; bud; bud = bud->next) { + if (strcmp(bud->resource, s + 1) == 0) { break; + } + } } - - if( bud == NULL && ( flags & GET_BUDDY_CREAT ) && - ( bare_exists || bee_user_by_handle( ic->bee, ic, jid ) ) ) - { + + if (bud == NULL && (flags & GET_BUDDY_CREAT) && + (bare_exists || bee_user_by_handle(ic->bee, ic, jid))) { *s = '/'; - bud = jabber_buddy_add( ic, jid ); + bud = jabber_buddy_add(ic, jid); } - - g_free( jid ); + + g_free(jid); return bud; - } - else - { + } else { struct jabber_buddy *best_prio, *best_time; char *set; - - head = g_hash_table_lookup( jd->buddies, jid ); - bud = ( head && head->next ) ? head->next : head; - - g_free( jid ); - - if( bud == NULL ) + + head = g_hash_table_lookup(jd->buddies, jid); + bud = (head && head->next) ? head->next : head; + + g_free(jid); + + if (bud == NULL) { /* No match. Create it now? */ - return ( ( flags & GET_BUDDY_CREAT ) && - bee_user_by_handle( ic->bee, ic, jid_ ) ) ? - jabber_buddy_add( ic, jid_ ) : NULL; - else if( bud->resource && ( flags & GET_BUDDY_EXACT ) ) + return ((flags & GET_BUDDY_CREAT) && + bee_user_by_handle(ic->bee, ic, jid_)) ? + jabber_buddy_add(ic, jid_) : NULL; + } else if (bud->resource && (flags & GET_BUDDY_EXACT)) { /* We want an exact match, so in thise case there shouldn't be a /resource. */ return NULL; - else if( bud->resource == NULL || bud->next == NULL ) + } else if (bud->resource == NULL || bud->next == NULL) { /* No need for selection if there's only one option. */ return bud; - else if( flags & GET_BUDDY_FIRST ) + } else if (flags & GET_BUDDY_FIRST) { /* Looks like the caller doesn't care about details. */ return bud; - else if( flags & GET_BUDDY_BARE ) + } else if (flags & GET_BUDDY_BARE) { return head; - + } + best_prio = best_time = bud; - for( ; bud; bud = bud->next ) - { - if( bud->priority > best_prio->priority ) + for (; bud; bud = bud->next) { + if (bud->priority > best_prio->priority) { best_prio = bud; - if( bud->last_msg > best_time->last_msg ) + } + if (bud->last_msg > best_time->last_msg) { best_time = bud; + } } - - if( ( set = set_getstr( &ic->acc->set, "resource_select" ) ) == NULL ) + + if ((set = set_getstr(&ic->acc->set, "resource_select")) == NULL) { return NULL; - else if( strcmp( set, "priority" ) == 0 ) + } else if (strcmp(set, "priority") == 0) { return best_prio; - else if( flags & GET_BUDDY_BARE_OK ) /* && strcmp( set, "activity" ) == 0 */ - { - if( best_time->last_msg + set_getint( &ic->acc->set, "activity_timeout" ) >= time( NULL ) ) + } else if (flags & GET_BUDDY_BARE_OK) { /* && strcmp( set, "activity" ) == 0 */ + if (best_time->last_msg + set_getint(&ic->acc->set, "activity_timeout") >= time(NULL)) { return best_time; - else + } else { return head; - } - else + } + } else { return best_time; + } } } @@ -564,100 +557,96 @@ struct jabber_buddy *jabber_buddy_by_jid( struct im_connection *ic, char *jid_, a normal JID to ext_jid by swapping the part before and after the / and replacing the / with a =. But there should be some stripping (@s are allowed in Jabber nicks...). */ -struct jabber_buddy *jabber_buddy_by_ext_jid( struct im_connection *ic, char *jid_, get_buddy_flags_t flags ) +struct jabber_buddy *jabber_buddy_by_ext_jid(struct im_connection *ic, char *jid_, get_buddy_flags_t flags) { struct jabber_buddy *bud; char *s, *jid; - - jid = jabber_normalize_ext( jid_ ); - - if( ( s = strchr( jid, '=' ) ) == NULL ) + + jid = jabber_normalize_ext(jid_); + + if ((s = strchr(jid, '=')) == NULL) { return NULL; - - for( bud = jabber_buddy_by_jid( ic, s + 1, GET_BUDDY_FIRST ); bud; bud = bud->next ) - { + } + + for (bud = jabber_buddy_by_jid(ic, s + 1, GET_BUDDY_FIRST); bud; bud = bud->next) { /* Hmmm, could happen if not all people in the chat are anonymized? */ - if( bud->ext_jid == NULL ) + if (bud->ext_jid == NULL) { continue; - - if( strcmp( bud->ext_jid, jid ) == 0 ) + } + + if (strcmp(bud->ext_jid, jid) == 0) { break; + } } - - g_free( jid ); - + + g_free(jid); + return bud; } /* Remove one specific full JID from our list. Use this when a buddy goes off-line (because (s)he can still be online from a different location. XXX: See above, we should accept bare JIDs too... */ -int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) +int jabber_buddy_remove(struct im_connection *ic, char *full_jid_) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *prev = NULL, *bi; char *s, *full_jid; - - full_jid = jabber_normalize( full_jid_ ); - - if( ( s = strchr( full_jid, '/' ) ) ) + + full_jid = jabber_normalize(full_jid_); + + if ((s = strchr(full_jid, '/'))) { *s = 0; - - if( ( bud = g_hash_table_lookup( jd->buddies, full_jid ) ) ) - { - if( bud->next ) - bud = (prev=bud)->next; - + } + + if ((bud = g_hash_table_lookup(jd->buddies, full_jid))) { + if (bud->next) { + bud = (prev = bud)->next; + } + /* If there's only one item in the list (and if the resource matches), removing it is simple. (And the hash reference should be removed too!) */ - if( bud->next == NULL && - ( ( s == NULL && bud->resource == NULL ) || - ( bud->resource && s && strcmp( bud->resource, s + 1 ) == 0 ) ) ) - { - int st = jabber_buddy_remove_bare( ic, full_jid ); - g_free( full_jid ); + if (bud->next == NULL && + ((s == NULL && bud->resource == NULL) || + (bud->resource && s && strcmp(bud->resource, s + 1) == 0))) { + int st = jabber_buddy_remove_bare(ic, full_jid); + g_free(full_jid); return st; - } - else if( s == NULL || bud->resource == NULL ) - { + } else if (s == NULL || bud->resource == NULL) { /* Tried to remove a bare JID while this JID does seem to have resources... (Or the opposite.) *sigh* */ - g_free( full_jid ); + g_free(full_jid); return 0; - } - else - { - for( bi = bud; bi; bi = (prev=bi)->next ) - if( strcmp( bi->resource, s + 1 ) == 0 ) + } else { + for (bi = bud; bi; bi = (prev = bi)->next) { + if (strcmp(bi->resource, s + 1) == 0) { break; - - g_free( full_jid ); - - if( bi ) - { - if( prev ) + } + } + + g_free(full_jid); + + if (bi) { + if (prev) { prev->next = bi->next; - else + } else { /* Don't think this should ever happen anymore. */ - g_hash_table_replace( jd->buddies, bi->bare_jid, bi->next ); - - g_free( bi->ext_jid ); - g_free( bi->full_jid ); - g_free( bi->away_message ); - g_free( bi ); - + g_hash_table_replace(jd->buddies, bi->bare_jid, bi->next); + } + + g_free(bi->ext_jid); + g_free(bi->full_jid); + g_free(bi->away_message); + g_free(bi); + return 1; - } - else - { + } else { return 0; } } - } - else - { - g_free( full_jid ); + } else { + g_free(full_jid); return 0; } } @@ -665,76 +654,74 @@ int jabber_buddy_remove( struct im_connection *ic, char *full_jid_ ) /* Remove a buddy completely; removes all resources that belong to the specified bare JID. Use this when removing someone from the contact list, for example. */ -int jabber_buddy_remove_bare( struct im_connection *ic, char *bare_jid ) +int jabber_buddy_remove_bare(struct im_connection *ic, char *bare_jid) { struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud, *next; - - if( strchr( bare_jid, '/' ) ) + + if (strchr(bare_jid, '/')) { return 0; - - if( ( bud = jabber_buddy_by_jid( ic, bare_jid, GET_BUDDY_FIRST ) ) ) - { + } + + if ((bud = jabber_buddy_by_jid(ic, bare_jid, GET_BUDDY_FIRST))) { /* Most important: Remove the hash reference. We don't know this buddy anymore. */ - g_hash_table_remove( jd->buddies, bud->bare_jid ); - g_free( bud->bare_jid ); - + g_hash_table_remove(jd->buddies, bud->bare_jid); + g_free(bud->bare_jid); + /* Deallocate the linked list of resources. */ - while( bud ) - { + while (bud) { /* ext_jid && anonymous means that this buddy is specific to one groupchat (the one we're currently cleaning up) so it can be deleted completely. */ - if( bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS ) - imcb_remove_buddy( ic, bud->ext_jid, NULL ); - + if (bud->ext_jid && bud->flags & JBFLAG_IS_ANONYMOUS) { + imcb_remove_buddy(ic, bud->ext_jid, NULL); + } + next = bud->next; - g_free( bud->ext_jid ); - g_free( bud->full_jid ); - g_free( bud->away_message ); - g_free( bud ); + g_free(bud->ext_jid); + g_free(bud->full_jid); + g_free(bud->away_message); + g_free(bud); bud = next; } - + return 1; - } - else - { + } else { return 0; } } -static gboolean jabber_buddy_remove_all_cb( gpointer key, gpointer value, gpointer data ) +static gboolean jabber_buddy_remove_all_cb(gpointer key, gpointer value, gpointer data) { struct jabber_buddy *bud, *next; - + bud = value; - if( bud->bare_jid != bud->full_jid ) - g_free( bud->bare_jid ); - while( bud ) - { + if (bud->bare_jid != bud->full_jid) { + g_free(bud->bare_jid); + } + while (bud) { next = bud->next; - g_free( bud->ext_jid ); - g_free( bud->full_jid ); - g_free( bud->away_message ); - g_free( bud ); + g_free(bud->ext_jid); + g_free(bud->full_jid); + g_free(bud->away_message); + g_free(bud); bud = next; } - + return TRUE; } -void jabber_buddy_remove_all( struct im_connection *ic ) +void jabber_buddy_remove_all(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; - - g_hash_table_foreach_remove( jd->buddies, jabber_buddy_remove_all_cb, NULL ); - g_hash_table_destroy( jd->buddies ); + + g_hash_table_foreach_remove(jd->buddies, jabber_buddy_remove_all_cb, NULL); + g_hash_table_destroy(jd->buddies); } -time_t jabber_get_timestamp( struct xt_node *xt ) +time_t jabber_get_timestamp(struct xt_node *xt) { struct xt_node *c; char *s = NULL; @@ -743,90 +730,91 @@ time_t jabber_get_timestamp( struct xt_node *xt ) const char *format; /* XEP-0091 has <x> */ - c = xt_find_node_by_attr( xt->children, "x", "xmlns", XMLNS_DELAY_OLD ); + c = xt_find_node_by_attr(xt->children, "x", "xmlns", XMLNS_DELAY_OLD); - if( !c || !( s = xt_find_attr( c, "stamp" ) ) ) { + if (!c || !(s = xt_find_attr(c, "stamp"))) { is_old = FALSE; /* XEP-0203 has <delay> */ - c = xt_find_node_by_attr( xt->children, "delay", "xmlns", XMLNS_DELAY ); - if( !c || !( s = xt_find_attr( c, "stamp" ) ) ) { + c = xt_find_node_by_attr(xt->children, "delay", "xmlns", XMLNS_DELAY); + if (!c || !(s = xt_find_attr(c, "stamp"))) { return 0; } } - - memset( &tp, 0, sizeof( tp ) ); + + memset(&tp, 0, sizeof(tp)); /* The other main difference between XEPs is the timestamp format */ format = (is_old) ? "%4d%2d%2dT%2d:%2d:%2d" : "%4d-%2d-%2dT%2d:%2d:%2dZ"; - if( sscanf( s, format, &tp.tm_year, &tp.tm_mon, &tp.tm_mday, - &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) != 6 ) + if (sscanf(s, format, &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec) != 6) { return 0; - + } + tp.tm_year -= 1900; - tp.tm_mon --; - - return mktime_utc( &tp ); + tp.tm_mon--; + + return mktime_utc(&tp); } -struct jabber_error *jabber_error_parse( struct xt_node *node, char *xmlns ) +struct jabber_error *jabber_error_parse(struct xt_node *node, char *xmlns) { struct jabber_error *err; struct xt_node *c; char *s; - - if( node == NULL ) + + if (node == NULL) { return NULL; - - err = g_new0( struct jabber_error, 1 ); - err->type = xt_find_attr( node, "type" ); - - for( c = node->children; c; c = c->next ) - { - if( !( s = xt_find_attr( c, "xmlns" ) ) || - strcmp( s, xmlns ) != 0 ) + } + + err = g_new0(struct jabber_error, 1); + err->type = xt_find_attr(node, "type"); + + for (c = node->children; c; c = c->next) { + if (!(s = xt_find_attr(c, "xmlns")) || + strcmp(s, xmlns) != 0) { continue; - - if( strcmp( c->name, "text" ) != 0 ) - { + } + + if (strcmp(c->name, "text") != 0) { err->code = c->name; } /* Only use the text if it doesn't have an xml:lang attribute, if it's empty or if it's set to something English. */ - else if( !( s = xt_find_attr( c, "xml:lang" ) ) || - !*s || strncmp( s, "en", 2 ) == 0 ) - { + else if (!(s = xt_find_attr(c, "xml:lang")) || + !*s || strncmp(s, "en", 2) == 0) { err->text = c->text; } } - + return err; } -void jabber_error_free( struct jabber_error *err ) +void jabber_error_free(struct jabber_error *err) { - g_free( err ); + g_free(err); } -gboolean jabber_set_me( struct im_connection *ic, const char *me ) +gboolean jabber_set_me(struct im_connection *ic, const char *me) { struct jabber_data *jd = ic->proto_data; - - if( strchr( me, '@' ) == NULL ) + + if (strchr(me, '@') == NULL) { return FALSE; - - g_free( jd->username ); - g_free( jd->me ); - - jd->me = jabber_normalize( me ); - jd->server = strchr( jd->me, '@' ); - jd->username = g_strndup( jd->me, jd->server - jd->me ); - jd->server ++; + } + + g_free(jd->username); + g_free(jd->me); + + jd->me = jabber_normalize(me); + jd->server = strchr(jd->me, '@'); + jd->username = g_strndup(jd->me, jd->server - jd->me); + jd->server++; /* Set the "internal" account username, for groupchats */ - g_free( jd->internal_jid ); - jd->internal_jid = g_strdup( jd->me ); - + g_free(jd->internal_jid); + jd->internal_jid = g_strdup(jd->me); + return TRUE; } diff --git a/protocols/jabber/message.c b/protocols/jabber/message.c index 1c832bee..1b47693b 100644 --- a/protocols/jabber/message.c +++ b/protocols/jabber/message.c @@ -23,22 +23,22 @@ #include "jabber.h" -xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) +xt_status jabber_pkt_message(struct xt_node *node, gpointer data) { struct im_connection *ic = data; - char *from = xt_find_attr( node, "from" ); - char *type = xt_find_attr( node, "type" ); - char *id = xt_find_attr( node, "id" ); - struct xt_node *body = xt_find_node( node->children, "body" ), *c; - struct xt_node *request = xt_find_node( node->children, "request" ); + char *from = xt_find_attr(node, "from"); + char *type = xt_find_attr(node, "type"); + char *id = xt_find_attr(node, "id"); + struct xt_node *body = xt_find_node(node->children, "body"), *c; + struct xt_node *request = xt_find_node(node->children, "request"); struct jabber_buddy *bud = NULL; char *s, *room = NULL, *reason = NULL; - - if( !from ) + + if (!from) { return XT_HANDLED; /* Consider this packet corrupted. */ - if( request && id ) - { + } + if (request && id) { /* Send a message receipt (XEP-0184), looking like this: * <message * from='kingrichard@royalty.england.lit/throne' @@ -47,125 +47,113 @@ xt_status jabber_pkt_message( struct xt_node *node, gpointer data ) * <received xmlns='urn:xmpp:receipts' id='richard2-4.1.247'/> * </message> */ struct xt_node *received, *receipt; - - received = xt_new_node( "received", NULL, NULL ); - xt_add_attr( received, "xmlns", XMLNS_RECEIPTS ); - xt_add_attr( received, "id", id ); - receipt = jabber_make_packet( "message", NULL, from, received ); - - jabber_write_packet( ic, receipt ); - xt_free_node( receipt ); + + received = xt_new_node("received", NULL, NULL); + xt_add_attr(received, "xmlns", XMLNS_RECEIPTS); + xt_add_attr(received, "id", id); + receipt = jabber_make_packet("message", NULL, from, received); + + jabber_write_packet(ic, receipt); + xt_free_node(receipt); } - - bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT ); - - if( type && strcmp( type, "error" ) == 0 ) - { + + bud = jabber_buddy_by_jid(ic, from, GET_BUDDY_EXACT); + + if (type && strcmp(type, "error") == 0) { /* Handle type=error packet. */ - } - else if( type && from && strcmp( type, "groupchat" ) == 0 ) - { - jabber_chat_pkt_message( ic, bud, node ); - } - else /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */ - { - GString *fullmsg = g_string_new( "" ); + } else if (type && from && strcmp(type, "groupchat") == 0) { + jabber_chat_pkt_message(ic, bud, node); + } else { /* "chat", "normal", "headline", no-type or whatever. Should all be pretty similar. */ + GString *fullmsg = g_string_new(""); - for( c = node->children; ( c = xt_find_node( c, "x" ) ); c = c->next ) - { - char *ns = xt_find_attr( c, "xmlns" ); + for (c = node->children; (c = xt_find_node(c, "x")); c = c->next) { + char *ns = xt_find_attr(c, "xmlns"); struct xt_node *inv; - - if( ns && strcmp( ns, XMLNS_MUC_USER ) == 0 && - ( inv = xt_find_node( c->children, "invite" ) ) ) - { + + if (ns && strcmp(ns, XMLNS_MUC_USER) == 0 && + (inv = xt_find_node(c->children, "invite"))) { /* This is an invitation. Set some vars which will be passed to imcb_chat_invite() below. */ room = from; - if( ( from = xt_find_attr( inv, "from" ) ) == NULL ) + if ((from = xt_find_attr(inv, "from")) == NULL) { from = room; - if( ( inv = xt_find_node( inv->children, "reason" ) ) && inv->text_len > 0 ) + } + if ((inv = xt_find_node(inv->children, "reason")) && inv->text_len > 0) { reason = inv->text; + } } } - - if( ( s = strchr( from, '/' ) ) ) - { - if( bud ) - { - bud->last_msg = time( NULL ); + + if ((s = strchr(from, '/'))) { + if (bud) { + bud->last_msg = time(NULL); from = bud->ext_jid ? bud->ext_jid : bud->bare_jid; - } - else + } else { *s = 0; /* We need to generate a bare JID now. */ + } } - - if( type && strcmp( type, "headline" ) == 0 ) - { - if( ( c = xt_find_node( node->children, "subject" ) ) && c->text_len > 0 ) - g_string_append_printf( fullmsg, "Headline: %s\n", c->text ); - + + if (type && strcmp(type, "headline") == 0) { + if ((c = xt_find_node(node->children, "subject")) && c->text_len > 0) { + g_string_append_printf(fullmsg, "Headline: %s\n", c->text); + } + /* <x xmlns="jabber:x:oob"><url>http://....</url></x> can contain a URL, it seems. */ - for( c = node->children; c; c = c->next ) - { + for (c = node->children; c; c = c->next) { struct xt_node *url; - - if( ( url = xt_find_node( c->children, "url" ) ) && url->text_len > 0 ) - g_string_append_printf( fullmsg, "URL: %s\n", url->text ); + + if ((url = xt_find_node(c->children, "url")) && url->text_len > 0) { + g_string_append_printf(fullmsg, "URL: %s\n", url->text); + } } - } - else if( ( c = xt_find_node( node->children, "subject" ) ) && c->text_len > 0 && - ( !bud || !( bud->flags & JBFLAG_HIDE_SUBJECT ) ) ) - { - g_string_append_printf( fullmsg, "<< \002BitlBee\002 - Message with subject: %s >>\n", c->text ); - if( bud ) + } else if ((c = xt_find_node(node->children, "subject")) && c->text_len > 0 && + (!bud || !(bud->flags & JBFLAG_HIDE_SUBJECT))) { + g_string_append_printf(fullmsg, "<< \002BitlBee\002 - Message with subject: %s >>\n", c->text); + if (bud) { bud->flags |= JBFLAG_HIDE_SUBJECT; - } - else if( bud && !c ) - { + } + } else if (bud && !c) { /* Yeah, possibly we're hiding changes to this field now. But nobody uses this for anything useful anyway, except GMail when people reply to an e-mail via chat, repeating the same subject all the time. I don't want to have to remember full subject strings for everyone. */ bud->flags &= ~JBFLAG_HIDE_SUBJECT; } - - if( body && body->text_len > 0 ) /* Could be just a typing notification. */ - fullmsg = g_string_append( fullmsg, body->text ); - - if( fullmsg->len > 0 ) - imcb_buddy_msg( ic, from, fullmsg->str, - 0, jabber_get_timestamp( node ) ); - if( room ) - imcb_chat_invite( ic, room, from, reason ); - - g_string_free( fullmsg, TRUE ); - + + if (body && body->text_len > 0) { /* Could be just a typing notification. */ + fullmsg = g_string_append(fullmsg, body->text); + } + + if (fullmsg->len > 0) { + imcb_buddy_msg(ic, from, fullmsg->str, + 0, jabber_get_timestamp(node)); + } + if (room) { + imcb_chat_invite(ic, room, from, reason); + } + + g_string_free(fullmsg, TRUE); + /* Handling of incoming typing notifications. */ - if( bud == NULL ) - { + if (bud == NULL) { /* Can't handle these for unknown buddies. */ - } - else if( xt_find_node( node->children, "composing" ) ) - { + } else if (xt_find_node(node->children, "composing")) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, from, OPT_TYPING ); + imcb_buddy_typing(ic, from, OPT_TYPING); } /* No need to send a "stopped typing" signal when there's a message. */ - else if( xt_find_node( node->children, "active" ) && ( body == NULL ) ) - { + else if (xt_find_node(node->children, "active") && (body == NULL)) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, from, 0 ); - } - else if( xt_find_node( node->children, "paused" ) ) - { + imcb_buddy_typing(ic, from, 0); + } else if (xt_find_node(node->children, "paused")) { bud->flags |= JBFLAG_DOES_XEP85; - imcb_buddy_typing( ic, from, OPT_THINKING ); + imcb_buddy_typing(ic, from, OPT_THINKING); } - - if( s ) + + if (s) { *s = '/'; /* And convert it back to a full JID. */ + } } - + return XT_HANDLED; } diff --git a/protocols/jabber/presence.c b/protocols/jabber/presence.c index 2875d23e..82ea5f8f 100644 --- a/protocols/jabber/presence.c +++ b/protocols/jabber/presence.c @@ -23,236 +23,219 @@ #include "jabber.h" -xt_status jabber_pkt_presence( struct xt_node *node, gpointer data ) +xt_status jabber_pkt_presence(struct xt_node *node, gpointer data) { struct im_connection *ic = data; - char *from = xt_find_attr( node, "from" ); - char *type = xt_find_attr( node, "type" ); /* NULL should mean the person is online. */ + char *from = xt_find_attr(node, "from"); + char *type = xt_find_attr(node, "type"); /* NULL should mean the person is online. */ struct xt_node *c, *cap; struct jabber_buddy *bud, *send_presence = NULL; int is_chat = 0; char *s; - - if( !from ) + + if (!from) { return XT_HANDLED; - - if( ( s = strchr( from, '/' ) ) ) - { + } + + if ((s = strchr(from, '/'))) { *s = 0; - if( jabber_chat_by_jid( ic, from ) ) + if (jabber_chat_by_jid(ic, from)) { is_chat = 1; + } *s = '/'; } - - if( type == NULL ) - { - if( !( bud = jabber_buddy_by_jid( ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT ) ) ) - { + + if (type == NULL) { + if (!(bud = jabber_buddy_by_jid(ic, from, GET_BUDDY_EXACT | GET_BUDDY_CREAT))) { /* imcb_log( ic, "Warning: Could not handle presence information from JID: %s", from ); */ return XT_HANDLED; } - - g_free( bud->away_message ); - if( ( c = xt_find_node( node->children, "status" ) ) && c->text_len > 0 ) - bud->away_message = g_strdup( c->text ); - else + + g_free(bud->away_message); + if ((c = xt_find_node(node->children, "status")) && c->text_len > 0) { + bud->away_message = g_strdup(c->text); + } else { bud->away_message = NULL; - - if( ( c = xt_find_node( node->children, "show" ) ) && c->text_len > 0 ) - { - bud->away_state = (void*) jabber_away_state_by_code( c->text ); } - else - { + + if ((c = xt_find_node(node->children, "show")) && c->text_len > 0) { + bud->away_state = (void *) jabber_away_state_by_code(c->text); + } else { bud->away_state = NULL; } - - if( ( c = xt_find_node( node->children, "priority" ) ) && c->text_len > 0 ) - bud->priority = atoi( c->text ); - else + + if ((c = xt_find_node(node->children, "priority")) && c->text_len > 0) { + bud->priority = atoi(c->text); + } else { bud->priority = 0; - - if( bud && ( cap = xt_find_node( node->children, "c" ) ) && - ( s = xt_find_attr( cap, "xmlns" ) ) && strcmp( s, XMLNS_CAPS ) == 0 ) - { + } + + if (bud && (cap = xt_find_node(node->children, "c")) && + (s = xt_find_attr(cap, "xmlns")) && strcmp(s, XMLNS_CAPS) == 0) { /* This <presence> stanza includes an XEP-0115 capabilities part. Not too interesting, but we can see if it has an ext= attribute. */ - s = xt_find_attr( cap, "ext" ); - if( s && ( strstr( s, "cstates" ) || strstr( s, "chatstate" ) ) ) + s = xt_find_attr(cap, "ext"); + if (s && (strstr(s, "cstates") || strstr(s, "chatstate"))) { bud->flags |= JBFLAG_DOES_XEP85; - + } + /* This field can contain more information like xhtml support, but we don't support that ourselves. Officially the ext= tag was deprecated, but enough clients do send it. - + (I'm aware that this is not the right way to use this field.) See for an explanation of ext=: http://www.xmpp.org/extensions/attic/xep-0115-1.3.html*/ } - - if( is_chat ) - jabber_chat_pkt_presence( ic, bud, node ); - else - send_presence = jabber_buddy_by_jid( ic, bud->bare_jid, 0 ); - } - else if( strcmp( type, "unavailable" ) == 0 ) - { - if( ( bud = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) - { + + if (is_chat) { + jabber_chat_pkt_presence(ic, bud, node); + } else { + send_presence = jabber_buddy_by_jid(ic, bud->bare_jid, 0); + } + } else if (strcmp(type, "unavailable") == 0) { + if ((bud = jabber_buddy_by_jid(ic, from, 0)) == NULL) { /* imcb_log( ic, "Warning: Received presence information from unknown JID: %s", from ); */ return XT_HANDLED; } - + /* Handle this before we delete the JID. */ - if( is_chat ) - { - jabber_chat_pkt_presence( ic, bud, node ); + if (is_chat) { + jabber_chat_pkt_presence(ic, bud, node); } - - if( strchr( from, '/' ) == NULL ) + + if (strchr(from, '/') == NULL) { /* Sometimes servers send a type="unavailable" from a bare JID, which should mean that suddenly all resources for this JID disappeared. */ - jabber_buddy_remove_bare( ic, from ); - else - jabber_buddy_remove( ic, from ); - - if( is_chat ) - { - /* Nothing else to do for now? */ + jabber_buddy_remove_bare(ic, from); + } else { + jabber_buddy_remove(ic, from); } - else if( ( s = strchr( from, '/' ) ) ) - { + + if (is_chat) { + /* Nothing else to do for now? */ + } else if ((s = strchr(from, '/'))) { *s = 0; - + /* If another resource is still available, send its presence information. */ - if( ( send_presence = jabber_buddy_by_jid( ic, from, 0 ) ) == NULL ) - { + if ((send_presence = jabber_buddy_by_jid(ic, from, 0)) == NULL) { /* Otherwise, count him/her as offline now. */ - imcb_buddy_status( ic, from, 0, NULL, NULL ); + imcb_buddy_status(ic, from, 0, NULL, NULL); } - + *s = '/'; + } else { + imcb_buddy_status(ic, from, 0, NULL, NULL); } - else - { - imcb_buddy_status( ic, from, 0, NULL, NULL ); - } - } - else if( strcmp( type, "subscribe" ) == 0 ) - { - jabber_buddy_ask( ic, from ); - } - else if( strcmp( type, "subscribed" ) == 0 ) - { + } else if (strcmp(type, "subscribe") == 0) { + jabber_buddy_ask(ic, from); + } else if (strcmp(type, "subscribed") == 0) { /* Not sure about this one, actually... */ - imcb_log( ic, "%s just accepted your authorization request", from ); - } - else if( strcmp( type, "unsubscribe" ) == 0 || strcmp( type, "unsubscribed" ) == 0 ) - { + imcb_log(ic, "%s just accepted your authorization request", from); + } else if (strcmp(type, "unsubscribe") == 0 || strcmp(type, "unsubscribed") == 0) { /* Do nothing here. Plenty of control freaks or over-curious souls get excited when they can see who still has them in their buddy list and who finally removed them. Somehow I got the impression that those are the people who get removed from many buddy lists for "some" reason... - + If you're one of those people, this is your chance to write your first line of code in C... */ - } - else if( strcmp( type, "error" ) == 0 ) - { - return jabber_cache_handle_packet( ic, node ); - + } else if (strcmp(type, "error") == 0) { + return jabber_cache_handle_packet(ic, node); + /* struct jabber_error *err; if( ( c = xt_find_node( node->children, "error" ) ) ) { - err = jabber_error_parse( c, XMLNS_STANZA_ERROR ); - imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name, - err->code, err->text ? ": " : "", - err->text ? err->text : "" ); - jabber_error_free( err ); + err = jabber_error_parse( c, XMLNS_STANZA_ERROR ); + imcb_error( ic, "Stanza (%s) error: %s%s%s", node->name, + err->code, err->text ? ": " : "", + err->text ? err->text : "" ); + jabber_error_free( err ); } */ } - if( send_presence ) - { + if (send_presence) { int is_away = 0; - if( send_presence->away_state && - strcmp( send_presence->away_state->code, "chat" ) != 0 ) + if (send_presence->away_state && + strcmp(send_presence->away_state->code, "chat") != 0) { is_away = OPT_AWAY; + } - imcb_buddy_status( ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, - is_away ? send_presence->away_state->full_name : NULL, - send_presence->away_message ); + imcb_buddy_status(ic, send_presence->bare_jid, OPT_LOGGED_IN | is_away, + is_away ? send_presence->away_state->full_name : NULL, + send_presence->away_message); } - + return XT_HANDLED; } /* Whenever presence information is updated, call this function to inform the server. */ -int presence_send_update( struct im_connection *ic ) +int presence_send_update(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; struct xt_node *node, *cap; GSList *l; int st; - - node = jabber_make_packet( "presence", NULL, NULL, NULL ); - xt_add_child( node, xt_new_node( "priority", set_getstr( &ic->acc->set, "priority" ), NULL ) ); - if( jd->away_state ) - xt_add_child( node, xt_new_node( "show", jd->away_state->code, NULL ) ); - if( jd->away_message ) - xt_add_child( node, xt_new_node( "status", jd->away_message, NULL ) ); - + + node = jabber_make_packet("presence", NULL, NULL, NULL); + xt_add_child(node, xt_new_node("priority", set_getstr(&ic->acc->set, "priority"), NULL)); + if (jd->away_state) { + xt_add_child(node, xt_new_node("show", jd->away_state->code, NULL)); + } + if (jd->away_message) { + xt_add_child(node, xt_new_node("status", jd->away_message, NULL)); + } + /* This makes the packet slightly bigger, but clients interested in capabilities can now cache the discovery info. This reduces the usual post-login iq-flood. See XEP-0115. At least libpurple and Trillian seem to do this right. */ - cap = xt_new_node( "c", NULL, NULL ); - xt_add_attr( cap, "xmlns", XMLNS_CAPS ); - xt_add_attr( cap, "node", "http://bitlbee.org/xmpp/caps" ); - xt_add_attr( cap, "ver", BITLBEE_VERSION ); /* The XEP wants this hashed, but nobody's doing that. */ - xt_add_child( node, cap ); - - st = jabber_write_packet( ic, node ); - + cap = xt_new_node("c", NULL, NULL); + xt_add_attr(cap, "xmlns", XMLNS_CAPS); + xt_add_attr(cap, "node", "http://bitlbee.org/xmpp/caps"); + xt_add_attr(cap, "ver", BITLBEE_VERSION); /* The XEP wants this hashed, but nobody's doing that. */ + xt_add_child(node, cap); + + st = jabber_write_packet(ic, node); + /* Have to send this update to all groupchats too, the server won't do this automatically. */ - for( l = ic->groupchats; l && st; l = l->next ) - { + for (l = ic->groupchats; l && st; l = l->next) { struct groupchat *c = l->data; struct jabber_chat *jc = c->data; - - xt_add_attr( node, "to", jc->my_full_jid ); - st = jabber_write_packet( ic, node ); + + xt_add_attr(node, "to", jc->my_full_jid); + st = jabber_write_packet(ic, node); } - - xt_free_node( node ); + + xt_free_node(node); return st; } /* Send a subscribe/unsubscribe request to a buddy. */ -int presence_send_request( struct im_connection *ic, char *handle, char *request ) +int presence_send_request(struct im_connection *ic, char *handle, char *request) { struct xt_node *node; int st; - - node = jabber_make_packet( "presence", NULL, NULL, NULL ); - xt_add_attr( node, "to", handle ); - xt_add_attr( node, "type", request ); - - st = jabber_write_packet( ic, node ); - - xt_free_node( node ); + + node = jabber_make_packet("presence", NULL, NULL, NULL); + xt_add_attr(node, "to", handle); + xt_add_attr(node, "type", request); + + st = jabber_write_packet(ic, node); + + xt_free_node(node); return st; } diff --git a/protocols/jabber/s5bytestream.c b/protocols/jabber/s5bytestream.c index 6b22d95f..27fb018b 100644 --- a/protocols/jabber/s5bytestream.c +++ b/protocols/jabber/s5bytestream.c @@ -33,11 +33,10 @@ struct bs_transfer { jabber_streamhost_t *sh; GSList *streamhosts; - enum - { - BS_PHASE_CONNECT, - BS_PHASE_CONNECTED, - BS_PHASE_REQUEST, + enum { + BS_PHASE_CONNECT, + BS_PHASE_CONNECTED, + BS_PHASE_REQUEST, BS_PHASE_REPLY } phase; @@ -45,16 +44,14 @@ struct bs_transfer { char *pseudoadr; gint connect_timeout; - + char peek_buf[64]; int peek_buf_len; }; -struct socks5_message -{ +struct socks5_message { unsigned char ver; - union - { + union { unsigned char cmd; unsigned char rep; } cmdrep; @@ -63,7 +60,7 @@ struct socks5_message unsigned char addrlen; unsigned char address[40]; in_port_t port; -} __attribute__ ((packed)); +} __attribute__ ((packed)); char *socks5_reply_code[] = { "succeeded", @@ -75,7 +72,8 @@ char *socks5_reply_code[] = { "TTL expired", "Command not supported", "Address type not supported", - "unassigned"}; + "unassigned" +}; /* connect() timeout in seconds. */ #define JABBER_BS_CONTIMEOUT 15 @@ -84,286 +82,284 @@ char *socks5_reply_code[] = { /* very useful */ #define ASSERTSOCKOP(op, msg) \ - if( (op) == -1 ) \ - return jabber_bs_abort( bt , msg ": %s", strerror( errno ) ); - -gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... ); -void jabber_bs_canceled( file_transfer_t *ft , char *reason ); -void jabber_bs_free_transfer( file_transfer_t *ft ); -gboolean jabber_bs_connect_timeout( gpointer data, gint fd, b_input_condition cond ); -gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents ); -gboolean jabber_bs_peek( struct bs_transfer *bt, void *buffer, int buflen ); - -void jabber_bs_recv_answer_request( struct bs_transfer *bt ); -gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond ); -gboolean jabber_bs_recv_write_request( file_transfer_t *ft ); -gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition cond ); -gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error ); -int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode ); - -gboolean jabber_bs_send_handshake_abort( struct bs_transfer *bt, char *error ); -gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts ); -gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition cond ); -static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ); -void jabber_bs_send_activate( struct bs_transfer *bt ); + if ((op) == -1) { \ + return jabber_bs_abort(bt, msg ": %s", strerror(errno)); } + +gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...); +void jabber_bs_canceled(file_transfer_t *ft, char *reason); +void jabber_bs_free_transfer(file_transfer_t *ft); +gboolean jabber_bs_connect_timeout(gpointer data, gint fd, b_input_condition cond); +gboolean jabber_bs_poll(struct bs_transfer *bt, int fd, short *revents); +gboolean jabber_bs_peek(struct bs_transfer *bt, void *buffer, int buflen); + +void jabber_bs_recv_answer_request(struct bs_transfer *bt); +gboolean jabber_bs_recv_read(gpointer data, gint fd, b_input_condition cond); +gboolean jabber_bs_recv_write_request(file_transfer_t *ft); +gboolean jabber_bs_recv_handshake(gpointer data, gint fd, b_input_condition cond); +gboolean jabber_bs_recv_handshake_abort(struct bs_transfer *bt, char *error); +int jabber_bs_recv_request(struct im_connection *ic, struct xt_node *node, struct xt_node *qnode); + +gboolean jabber_bs_send_handshake_abort(struct bs_transfer *bt, char *error); +gboolean jabber_bs_send_request(struct jabber_transfer *tf, GSList *streamhosts); +gboolean jabber_bs_send_handshake(gpointer data, gint fd, b_input_condition cond); +static xt_status jabber_bs_send_handle_activate(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); +void jabber_bs_send_activate(struct bs_transfer *bt); /* * Frees a bs_transfer struct and calls the SI free function */ -void jabber_bs_free_transfer( file_transfer_t *ft) { +void jabber_bs_free_transfer(file_transfer_t *ft) +{ struct jabber_transfer *tf = ft->data; struct bs_transfer *bt = tf->streamhandle; jabber_streamhost_t *sh; - if ( bt->connect_timeout ) - { - b_event_remove( bt->connect_timeout ); + if (bt->connect_timeout) { + b_event_remove(bt->connect_timeout); bt->connect_timeout = 0; } - if ( tf->watch_in ) - { - b_event_remove( tf->watch_in ); + if (tf->watch_in) { + b_event_remove(tf->watch_in); tf->watch_in = 0; } - - if( tf->watch_out ) - { - b_event_remove( tf->watch_out ); + + if (tf->watch_out) { + b_event_remove(tf->watch_out); tf->watch_out = 0; } - - g_free( bt->pseudoadr ); - while( bt->streamhosts ) - { + g_free(bt->pseudoadr); + + while (bt->streamhosts) { sh = bt->streamhosts->data; - bt->streamhosts = g_slist_remove( bt->streamhosts, sh ); - g_free( sh->jid ); - g_free( sh->host ); - g_free( sh ); + bt->streamhosts = g_slist_remove(bt->streamhosts, sh); + g_free(sh->jid); + g_free(sh->host); + g_free(sh); } - - g_free( bt ); - jabber_si_free_transfer( ft ); + g_free(bt); + + jabber_si_free_transfer(ft); } /* * Checks if buflen data is available on the socket and * writes it to buffer if that's the case. */ -gboolean jabber_bs_peek( struct bs_transfer *bt, void *buffer, int buflen ) +gboolean jabber_bs_peek(struct bs_transfer *bt, void *buffer, int buflen) { int ret; int fd = bt->tf->fd; - if( buflen > sizeof( bt->peek_buf ) ) - return jabber_bs_abort( bt, "BUG: %d > sizeof(peek_buf)", buflen ); + if (buflen > sizeof(bt->peek_buf)) { + return jabber_bs_abort(bt, "BUG: %d > sizeof(peek_buf)", buflen); + } + + ASSERTSOCKOP(ret = recv(fd, bt->peek_buf + bt->peek_buf_len, + buflen - bt->peek_buf_len, 0), "recv() on SOCKS5 connection"); - ASSERTSOCKOP( ret = recv( fd, bt->peek_buf + bt->peek_buf_len, - buflen - bt->peek_buf_len, 0 ), "recv() on SOCKS5 connection" ); + if (ret == 0) { + return jabber_bs_abort(bt, "Remote end closed connection"); + } - if( ret == 0 ) - return jabber_bs_abort( bt, "Remote end closed connection" ); - bt->peek_buf_len += ret; - memcpy( buffer, bt->peek_buf, bt->peek_buf_len ); - - if( bt->peek_buf_len == buflen ) - { + memcpy(buffer, bt->peek_buf, bt->peek_buf_len); + + if (bt->peek_buf_len == buflen) { /* If we have everything the caller wanted, reset the peek buffer. */ bt->peek_buf_len = 0; return buflen; - } - else + } else { return bt->peek_buf_len; + } } -/* +/* * This function is scheduled in bs_handshake via b_timeout_add after a (non-blocking) connect(). */ -gboolean jabber_bs_connect_timeout( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_bs_connect_timeout(gpointer data, gint fd, b_input_condition cond) { struct bs_transfer *bt = data; bt->connect_timeout = 0; - jabber_bs_abort( bt, "no connection after %d seconds", bt->tf->ft->sending ? JABBER_BS_LISTEN_TIMEOUT : JABBER_BS_CONTIMEOUT ); + jabber_bs_abort(bt, "no connection after %d seconds", + bt->tf->ft->sending ? JABBER_BS_LISTEN_TIMEOUT : JABBER_BS_CONTIMEOUT); return FALSE; } -/* +/* * Polls the socket, checks for errors and removes a connect timer * if there is one. */ -gboolean jabber_bs_poll( struct bs_transfer *bt, int fd, short *revents ) +gboolean jabber_bs_poll(struct bs_transfer *bt, int fd, short *revents) { - struct pollfd pfd = { .fd = fd, .events = POLLHUP|POLLERR }; - - if ( bt->connect_timeout ) - { - b_event_remove( bt->connect_timeout ); + struct pollfd pfd = { .fd = fd, .events = POLLHUP | POLLERR }; + + if (bt->connect_timeout) { + b_event_remove(bt->connect_timeout); bt->connect_timeout = 0; } - ASSERTSOCKOP( poll( &pfd, 1, 0 ), "poll()" ) + ASSERTSOCKOP(poll(&pfd, 1, 0), "poll()") - if( pfd.revents & POLLERR ) - { + if (pfd.revents & POLLERR) { int sockerror; - socklen_t errlen = sizeof( sockerror ); + socklen_t errlen = sizeof(sockerror); + + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen)) { + return jabber_bs_abort(bt, + "getsockopt() failed, unknown socket error during SOCKS5 handshake (weird!)"); + } - if ( getsockopt( fd, SOL_SOCKET, SO_ERROR, &sockerror, &errlen ) ) - return jabber_bs_abort( bt, "getsockopt() failed, unknown socket error during SOCKS5 handshake (weird!)" ); + if (bt->phase == BS_PHASE_CONNECTED) { + return jabber_bs_abort(bt, "connect failed: %s", strerror(sockerror)); + } - if ( bt->phase == BS_PHASE_CONNECTED ) - return jabber_bs_abort( bt, "connect failed: %s", strerror( sockerror ) ); + return jabber_bs_abort(bt, "Socket error during SOCKS5 handshake(weird!): %s", strerror(sockerror)); + } - return jabber_bs_abort( bt, "Socket error during SOCKS5 handshake(weird!): %s", strerror( sockerror ) ); + if (pfd.revents & POLLHUP) { + return jabber_bs_abort(bt, "Remote end closed connection"); } - if( pfd.revents & POLLHUP ) - return jabber_bs_abort( bt, "Remote end closed connection" ); - *revents = pfd.revents; - + return TRUE; } /* * Used for receive and send path. */ -gboolean jabber_bs_abort( struct bs_transfer *bt, char *format, ... ) +gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...) { va_list params; - va_start( params, format ); + + va_start(params, format); char error[128]; - if( vsnprintf( error, 128, format, params ) < 0 ) - sprintf( error, "internal error parsing error string (BUG)" ); - va_end( params ); - if( bt->tf->ft->sending ) - return jabber_bs_send_handshake_abort( bt, error ); - else - return jabber_bs_recv_handshake_abort( bt, error ); + if (vsnprintf(error, 128, format, params) < 0) { + sprintf(error, "internal error parsing error string (BUG)"); + } + va_end(params); + if (bt->tf->ft->sending) { + return jabber_bs_send_handshake_abort(bt, error); + } else { + return jabber_bs_recv_handshake_abort(bt, error); + } } /* Bad luck */ -void jabber_bs_canceled( file_transfer_t *ft , char *reason ) +void jabber_bs_canceled(file_transfer_t *ft, char *reason) { struct jabber_transfer *tf = ft->data; - imcb_log( tf->ic, "File transfer aborted: %s", reason ); + imcb_log(tf->ic, "File transfer aborted: %s", reason); } /* * Parses an incoming bytestream request and calls jabber_bs_handshake on success. */ -int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, struct xt_node *qnode) +int jabber_bs_recv_request(struct im_connection *ic, struct xt_node *node, struct xt_node *qnode) { char *sid, *ini_jid, *tgt_jid, *mode, *iq_id; struct jabber_data *jd = ic->proto_data; struct jabber_transfer *tf = NULL; GSList *tflist; struct bs_transfer *bt; - GSList *shlist=NULL; + GSList *shlist = NULL; struct xt_node *shnode; sha1_state_t sha; char hash_hex[41]; unsigned char hash[20]; int i; - - if( !(iq_id = xt_find_attr( node, "id" ) ) || - !(ini_jid = xt_find_attr( node, "from" ) ) || - !(tgt_jid = xt_find_attr( node, "to" ) ) || - !(sid = xt_find_attr( qnode, "sid" ) ) ) - { - imcb_log( ic, "WARNING: Received incomplete SI bytestream request"); + + if (!(iq_id = xt_find_attr(node, "id")) || + !(ini_jid = xt_find_attr(node, "from")) || + !(tgt_jid = xt_find_attr(node, "to")) || + !(sid = xt_find_attr(qnode, "sid"))) { + imcb_log(ic, "WARNING: Received incomplete SI bytestream request"); return XT_HANDLED; } - if( ( mode = xt_find_attr( qnode, "mode" ) ) && - ( strcmp( mode, "tcp" ) != 0 ) ) - { - imcb_log( ic, "WARNING: Received SI Request for unsupported bytestream mode %s", xt_find_attr( qnode, "mode" ) ); + if ((mode = xt_find_attr(qnode, "mode")) && + (strcmp(mode, "tcp") != 0)) { + imcb_log(ic, "WARNING: Received SI Request for unsupported bytestream mode %s", + xt_find_attr(qnode, "mode")); return XT_HANDLED; } shnode = qnode->children; - while( ( shnode = xt_find_node( shnode, "streamhost" ) ) ) - { + while ((shnode = xt_find_node(shnode, "streamhost"))) { char *jid, *host, *port_s; int port; - if( ( jid = xt_find_attr( shnode, "jid" ) ) && - ( host = xt_find_attr( shnode, "host" ) ) && - ( port_s = xt_find_attr( shnode, "port" ) ) && - ( sscanf( port_s, "%d", &port ) == 1 ) ) - { - jabber_streamhost_t *sh = g_new0( jabber_streamhost_t, 1 ); + if ((jid = xt_find_attr(shnode, "jid")) && + (host = xt_find_attr(shnode, "host")) && + (port_s = xt_find_attr(shnode, "port")) && + (sscanf(port_s, "%d", &port) == 1)) { + jabber_streamhost_t *sh = g_new0(jabber_streamhost_t, 1); sh->jid = g_strdup(jid); sh->host = g_strdup(host); - sprintf( sh->port, "%u", port ); - shlist = g_slist_append( shlist, sh ); + sprintf(sh->port, "%u", port); + shlist = g_slist_append(shlist, sh); } shnode = shnode->next; } - - if( !shlist ) - { - imcb_log( ic, "WARNING: Received incomplete SI bytestream request, no parseable streamhost entries"); + + if (!shlist) { + imcb_log(ic, "WARNING: Received incomplete SI bytestream request, no parseable streamhost entries"); return XT_HANDLED; } /* Let's see if we can find out what this bytestream should be for... */ - for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) ) - { + for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) { struct jabber_transfer *tft = tflist->data; - if( ( strcmp( tft->sid, sid ) == 0 ) && - ( strcmp( tft->ini_jid, ini_jid ) == 0 ) && - ( strcmp( tft->tgt_jid, tgt_jid ) == 0 ) ) - { - tf = tft; + if ((strcmp(tft->sid, sid) == 0) && + (strcmp(tft->ini_jid, ini_jid) == 0) && + (strcmp(tft->tgt_jid, tgt_jid) == 0)) { + tf = tft; break; } } - if (!tf) - { - imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid ); + if (!tf) { + imcb_log(ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid); return XT_HANDLED; } /* iq_id and canceled can be reused since SI is done */ - g_free( tf->iq_id ); - tf->iq_id = g_strdup( iq_id ); + g_free(tf->iq_id); + tf->iq_id = g_strdup(iq_id); tf->ft->canceled = jabber_bs_canceled; /* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */ - sha1_init( &sha ); - sha1_append( &sha, (unsigned char*) sid, strlen( sid ) ); - sha1_append( &sha, (unsigned char*) ini_jid, strlen( ini_jid ) ); - sha1_append( &sha, (unsigned char*) tgt_jid, strlen( tgt_jid ) ); - sha1_finish( &sha, hash ); - - for( i = 0; i < 20; i ++ ) - sprintf( hash_hex + i * 2, "%02x", hash[i] ); - - bt = g_new0( struct bs_transfer, 1 ); + sha1_init(&sha); + sha1_append(&sha, (unsigned char *) sid, strlen(sid)); + sha1_append(&sha, (unsigned char *) ini_jid, strlen(ini_jid)); + sha1_append(&sha, (unsigned char *) tgt_jid, strlen(tgt_jid)); + sha1_finish(&sha, hash); + + for (i = 0; i < 20; i++) { + sprintf(hash_hex + i * 2, "%02x", hash[i]); + } + + bt = g_new0(struct bs_transfer, 1); bt->tf = tf; bt->streamhosts = shlist; bt->sh = shlist->data; bt->phase = BS_PHASE_CONNECT; - bt->pseudoadr = g_strdup( hash_hex ); + bt->pseudoadr = g_strdup(hash_hex); tf->streamhandle = bt; tf->ft->free = jabber_bs_free_transfer; - jabber_bs_recv_handshake( bt, -1, 0 ); + jabber_bs_recv_handshake(bt, -1, 0); return XT_HANDLED; } @@ -375,155 +371,161 @@ int jabber_bs_recv_request( struct im_connection *ic, struct xt_node *node, stru * * All in all, it turned out quite nice :) */ -gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_bs_recv_handshake(gpointer data, gint fd, b_input_condition cond) { struct bs_transfer *bt = data; short revents; int gret; - if ( ( fd != -1 ) && !jabber_bs_poll( bt, fd, &revents ) ) + if ((fd != -1) && !jabber_bs_poll(bt, fd, &revents)) { return FALSE; - - switch( bt->phase ) - { + } + + switch (bt->phase) { case BS_PHASE_CONNECT: - { - struct addrinfo hints, *rp; + { + struct addrinfo hints, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_socktype = SOCK_STREAM; - memset( &hints, 0, sizeof( struct addrinfo ) ); - hints.ai_socktype = SOCK_STREAM; + if ((gret = getaddrinfo(bt->sh->host, bt->sh->port, &hints, &rp)) != 0) { + return jabber_bs_abort(bt, "getaddrinfo() failed: %s", gai_strerror(gret)); + } - if ( ( gret = getaddrinfo( bt->sh->host, bt->sh->port, &hints, &rp ) ) != 0 ) - return jabber_bs_abort( bt, "getaddrinfo() failed: %s", gai_strerror( gret ) ); + ASSERTSOCKOP(bt->tf->fd = fd = socket(rp->ai_family, rp->ai_socktype, 0), "Opening socket"); - ASSERTSOCKOP( bt->tf->fd = fd = socket( rp->ai_family, rp->ai_socktype, 0 ), "Opening socket" ); + sock_make_nonblocking(fd); - sock_make_nonblocking( fd ); + imcb_log(bt->tf->ic, "File %s: Connecting to streamhost %s:%s", bt->tf->ft->file_name, bt->sh->host, + bt->sh->port); - imcb_log( bt->tf->ic, "File %s: Connecting to streamhost %s:%s", bt->tf->ft->file_name, bt->sh->host, bt->sh->port ); + if ((connect(fd, rp->ai_addr, rp->ai_addrlen) == -1) && + (errno != EINPROGRESS)) { + return jabber_bs_abort(bt, "connect() failed: %s", strerror(errno)); + } - if( ( connect( fd, rp->ai_addr, rp->ai_addrlen ) == -1 ) && - ( errno != EINPROGRESS ) ) - return jabber_bs_abort( bt , "connect() failed: %s", strerror( errno ) ); + freeaddrinfo(rp); - freeaddrinfo( rp ); + bt->phase = BS_PHASE_CONNECTED; - bt->phase = BS_PHASE_CONNECTED; - - bt->tf->watch_out = b_input_add( fd, B_EV_IO_WRITE, jabber_bs_recv_handshake, bt ); + bt->tf->watch_out = b_input_add(fd, B_EV_IO_WRITE, jabber_bs_recv_handshake, bt); - /* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */ - bt->connect_timeout = b_timeout_add( JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt ); + /* since it takes forever(3mins?) till connect() fails on itself we schedule a timeout */ + bt->connect_timeout = b_timeout_add(JABBER_BS_CONTIMEOUT * 1000, jabber_bs_connect_timeout, bt); - bt->tf->watch_in = 0; - return FALSE; - } + bt->tf->watch_in = 0; + return FALSE; + } case BS_PHASE_CONNECTED: + { + struct { + unsigned char ver; + unsigned char nmethods; + unsigned char method; + } socks5_hello = { + .ver = 5, + .nmethods = 1, + .method = 0x00 /* no auth */ + /* one could also implement username/password. If you know + * a jabber client or proxy that actually does it, tell me. + */ + }; + + ASSERTSOCKOP(send(fd, &socks5_hello, sizeof(socks5_hello), 0), "Sending auth request"); + + bt->phase = BS_PHASE_REQUEST; + + bt->tf->watch_in = b_input_add(fd, B_EV_IO_READ, jabber_bs_recv_handshake, bt); + + bt->tf->watch_out = 0; + return FALSE; + } + case BS_PHASE_REQUEST: + { + struct socks5_message socks5_connect = { - struct { - unsigned char ver; - unsigned char nmethods; - unsigned char method; - } socks5_hello = { - .ver = 5, - .nmethods = 1, - .method = 0x00 /* no auth */ - /* one could also implement username/password. If you know - * a jabber client or proxy that actually does it, tell me. - */ - }; - - ASSERTSOCKOP( send( fd, &socks5_hello, sizeof( socks5_hello ) , 0 ), "Sending auth request" ); - - bt->phase = BS_PHASE_REQUEST; - - bt->tf->watch_in = b_input_add( fd, B_EV_IO_READ, jabber_bs_recv_handshake, bt ); - - bt->tf->watch_out = 0; + .ver = 5, + .cmdrep.cmd = 0x01, + .rsv = 0, + .atyp = 0x03, + .addrlen = strlen(bt->pseudoadr), + .port = 0 + }; + int ret; + char buf[2]; + + /* If someone's trying to be funny and sends only one byte at a time we'll fail :) */ + ASSERTSOCKOP(ret = recv(fd, buf, 2, 0), "Receiving auth reply"); + + if (!(ret == 2) || + !(buf[0] == 5) || + !(buf[1] == 0)) { + return jabber_bs_abort(bt, "Auth not accepted by streamhost (reply: len=%d, ver=%d, status=%d)", + ret, buf[0], buf[1]); + } + + /* copy hash into connect message */ + memcpy(socks5_connect.address, bt->pseudoadr, socks5_connect.addrlen); + + ASSERTSOCKOP(send(fd, &socks5_connect, sizeof(struct socks5_message), 0), "Sending SOCKS5 Connect"); + + bt->phase = BS_PHASE_REPLY; + + return TRUE; + } + case BS_PHASE_REPLY: + { + struct socks5_message socks5_reply; + int ret; + + if (!(ret = jabber_bs_peek(bt, &socks5_reply, sizeof(struct socks5_message)))) { return FALSE; } - case BS_PHASE_REQUEST: - { - struct socks5_message socks5_connect = - { - .ver = 5, - .cmdrep.cmd = 0x01, - .rsv = 0, - .atyp = 0x03, - .addrlen = strlen( bt->pseudoadr ), - .port = 0 - }; - int ret; - char buf[2]; - - /* If someone's trying to be funny and sends only one byte at a time we'll fail :) */ - ASSERTSOCKOP( ret = recv( fd, buf, 2, 0 ) , "Receiving auth reply" ); - - if( !( ret == 2 ) || - !( buf[0] == 5 ) || - !( buf[1] == 0 ) ) - return jabber_bs_abort( bt, "Auth not accepted by streamhost (reply: len=%d, ver=%d, status=%d)", - ret, buf[0], buf[1] ); - - /* copy hash into connect message */ - memcpy( socks5_connect.address, bt->pseudoadr, socks5_connect.addrlen ); - - ASSERTSOCKOP( send( fd, &socks5_connect, sizeof( struct socks5_message ), 0 ) , "Sending SOCKS5 Connect" ); - - bt->phase = BS_PHASE_REPLY; + if (ret < 5) { /* header up to address length */ return TRUE; + } else if (ret < sizeof(struct socks5_message)) { + /* Either a buggy proxy or just one that doesnt regard + * the SHOULD in XEP-0065 saying the reply SHOULD + * contain the address. We'll take it, so make sure the + * next jabber_bs_peek starts with an empty buffer. */ + bt->peek_buf_len = 0; } - case BS_PHASE_REPLY: - { - struct socks5_message socks5_reply; - int ret; - - if ( !( ret = jabber_bs_peek( bt, &socks5_reply, sizeof( struct socks5_message ) ) ) ) - return FALSE; - - if ( ret < 5 ) /* header up to address length */ - return TRUE; - else if( ret < sizeof( struct socks5_message ) ) - { - /* Either a buggy proxy or just one that doesnt regard - * the SHOULD in XEP-0065 saying the reply SHOULD - * contain the address. We'll take it, so make sure the - * next jabber_bs_peek starts with an empty buffer. */ - bt->peek_buf_len = 0; - } - if( !( socks5_reply.ver == 5 ) || - !( socks5_reply.cmdrep.rep == 0 ) ) { - char errstr[128] = ""; - if( ( socks5_reply.ver == 5 ) && ( socks5_reply.cmdrep.rep < - ( sizeof( socks5_reply_code ) / sizeof( socks5_reply_code[0] ) ) ) ) { - sprintf( errstr, "with \"%s\" ", socks5_reply_code[ socks5_reply.cmdrep.rep ] ); - } - return jabber_bs_abort( bt, "SOCKS5 CONNECT failed %s(reply: ver=%d, rep=%d, atyp=%d, addrlen=%d)", - errstr, - socks5_reply.ver, - socks5_reply.cmdrep.rep, - socks5_reply.atyp, - socks5_reply.addrlen); + if (!(socks5_reply.ver == 5) || + !(socks5_reply.cmdrep.rep == 0)) { + char errstr[128] = ""; + if ((socks5_reply.ver == 5) && (socks5_reply.cmdrep.rep < + (sizeof(socks5_reply_code) / sizeof(socks5_reply_code[0])))) { + sprintf(errstr, "with \"%s\" ", socks5_reply_code[ socks5_reply.cmdrep.rep ]); } - - /* usually a proxy sends back the 40 bytes address but I encountered at least one (of jabber.cz) - * that sends atyp=0 addrlen=0 and only 6 bytes (one less than one would expect). - * Therefore I removed the wait for more bytes. Since we don't care about what else the proxy - * is sending, it shouldnt matter */ + return jabber_bs_abort(bt, + "SOCKS5 CONNECT failed %s(reply: ver=%d, rep=%d, atyp=%d, addrlen=%d)", + errstr, + socks5_reply.ver, + socks5_reply.cmdrep.rep, + socks5_reply.atyp, + socks5_reply.addrlen); + } - if( bt->tf->ft->sending ) - jabber_bs_send_activate( bt ); - else - jabber_bs_recv_answer_request( bt ); + /* usually a proxy sends back the 40 bytes address but I encountered at least one (of jabber.cz) + * that sends atyp=0 addrlen=0 and only 6 bytes (one less than one would expect). + * Therefore I removed the wait for more bytes. Since we don't care about what else the proxy + * is sending, it shouldnt matter */ - return FALSE; + if (bt->tf->ft->sending) { + jabber_bs_send_activate(bt); + } else { + jabber_bs_recv_answer_request(bt); } + + return FALSE; + } default: /* BUG */ - imcb_log( bt->tf->ic, "BUG in file transfer code: undefined handshake phase" ); + imcb_log(bt->tf->ic, "BUG in file transfer code: undefined handshake phase"); bt->tf->watch_in = 0; return FALSE; @@ -533,156 +535,156 @@ gboolean jabber_bs_recv_handshake( gpointer data, gint fd, b_input_condition con /* * If the handshake failed we can try the next streamhost, if there is one. * An intelligent sender would probably specify himself as the first streamhost and - * a proxy as the second (Kopete and PSI are examples here). That way, a (potentially) + * a proxy as the second (Kopete and PSI are examples here). That way, a (potentially) * slow proxy is only used if neccessary. This of course also means, that the timeout * per streamhost should be kept short. If one or two firewalled adresses are specified, * they have to timeout first before a proxy is tried. */ -gboolean jabber_bs_recv_handshake_abort( struct bs_transfer *bt, char *error ) +gboolean jabber_bs_recv_handshake_abort(struct bs_transfer *bt, char *error) { struct jabber_transfer *tf = bt->tf; struct xt_node *reply, *iqnode; GSList *shlist; - imcb_log( tf->ic, "Transferring file %s: connection to streamhost %s:%s failed (%s)", - tf->ft->file_name, - bt->sh->host, - bt->sh->port, - error ); + imcb_log(tf->ic, "Transferring file %s: connection to streamhost %s:%s failed (%s)", + tf->ft->file_name, + bt->sh->host, + bt->sh->port, + error); /* Alright, this streamhost failed, let's try the next... */ bt->phase = BS_PHASE_CONNECT; - shlist = g_slist_find( bt->streamhosts, bt->sh ); - if( shlist && shlist->next ) - { + shlist = g_slist_find(bt->streamhosts, bt->sh); + if (shlist && shlist->next) { bt->sh = shlist->next->data; - return jabber_bs_recv_handshake( bt, -1, 0 ); + return jabber_bs_recv_handshake(bt, -1, 0); } /* out of stream hosts */ - iqnode = jabber_make_packet( "iq", "result", tf->ini_jid, NULL ); - reply = jabber_make_error_packet( iqnode, "item-not-found", "cancel" , "404" ); - xt_free_node( iqnode ); + iqnode = jabber_make_packet("iq", "result", tf->ini_jid, NULL); + reply = jabber_make_error_packet(iqnode, "item-not-found", "cancel", "404"); + xt_free_node(iqnode); + + xt_add_attr(reply, "id", tf->iq_id); - xt_add_attr( reply, "id", tf->iq_id ); - - if( !jabber_write_packet( tf->ic, reply ) ) - imcb_log( tf->ic, "WARNING: Error transmitting bytestream response" ); - xt_free_node( reply ); + if (!jabber_write_packet(tf->ic, reply)) { + imcb_log(tf->ic, "WARNING: Error transmitting bytestream response"); + } + xt_free_node(reply); - imcb_file_canceled( tf->ic, tf->ft, "couldn't connect to any streamhosts" ); + imcb_file_canceled(tf->ic, tf->ft, "couldn't connect to any streamhosts"); /* MUST always return FALSE! */ return FALSE; } -/* +/* * After the SOCKS5 handshake succeeds we need to inform the initiator which streamhost we chose. * If he is the streamhost himself, he might already know that. However, if it's a proxy, * the initiator will have to make a connection himself. */ -void jabber_bs_recv_answer_request( struct bs_transfer *bt ) +void jabber_bs_recv_answer_request(struct bs_transfer *bt) { struct jabber_transfer *tf = bt->tf; struct xt_node *reply; - imcb_log( tf->ic, "File %s: established SOCKS5 connection to %s:%s", - tf->ft->file_name, - bt->sh->host, - bt->sh->port ); + imcb_log(tf->ic, "File %s: established SOCKS5 connection to %s:%s", + tf->ft->file_name, + bt->sh->host, + bt->sh->port); tf->ft->data = tf; - tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt ); + tf->watch_in = b_input_add(tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt); tf->ft->write_request = jabber_bs_recv_write_request; - reply = xt_new_node( "streamhost-used", NULL, NULL ); - xt_add_attr( reply, "jid", bt->sh->jid ); + reply = xt_new_node("streamhost-used", NULL, NULL); + xt_add_attr(reply, "jid", bt->sh->jid); + + reply = xt_new_node("query", NULL, reply); + xt_add_attr(reply, "xmlns", XMLNS_BYTESTREAMS); - reply = xt_new_node( "query", NULL, reply ); - xt_add_attr( reply, "xmlns", XMLNS_BYTESTREAMS ); + reply = jabber_make_packet("iq", "result", tf->ini_jid, reply); - reply = jabber_make_packet( "iq", "result", tf->ini_jid, reply ); + xt_add_attr(reply, "id", tf->iq_id); - xt_add_attr( reply, "id", tf->iq_id ); - - if( !jabber_write_packet( tf->ic, reply ) ) - imcb_file_canceled( tf->ic, tf->ft, "Error transmitting bytestream response" ); - xt_free_node( reply ); + if (!jabber_write_packet(tf->ic, reply)) { + imcb_file_canceled(tf->ic, tf->ft, "Error transmitting bytestream response"); + } + xt_free_node(reply); } -/* +/* * This function is called from write_request directly. If no data is available, it will install itself * as a watcher for input on fd and once that happens, deliver the data and unschedule itself again. */ -gboolean jabber_bs_recv_read( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_bs_recv_read(gpointer data, gint fd, b_input_condition cond) { int ret; struct bs_transfer *bt = data; struct jabber_transfer *tf = bt->tf; - if( fd != -1 ) /* called via event thread */ - { + if (fd != -1) { /* called via event thread */ tf->watch_in = 0; - ASSERTSOCKOP( ret = recv( fd, tf->ft->buffer, sizeof( tf->ft->buffer ), 0 ) , "Receiving" ); - } - else - { + ASSERTSOCKOP(ret = recv(fd, tf->ft->buffer, sizeof(tf->ft->buffer), 0), "Receiving"); + } else { /* called directly. There might not be any data available. */ - if( ( ( ret = recv( tf->fd, tf->ft->buffer, sizeof( tf->ft->buffer ), 0 ) ) == -1 ) && - ( errno != EAGAIN ) ) - return jabber_bs_abort( bt, "Receiving: %s", strerror( errno ) ); + if (((ret = recv(tf->fd, tf->ft->buffer, sizeof(tf->ft->buffer), 0)) == -1) && + (errno != EAGAIN)) { + return jabber_bs_abort(bt, "Receiving: %s", strerror(errno)); + } - if( ( ret == -1 ) && ( errno == EAGAIN ) ) - { - tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt ); + if ((ret == -1) && (errno == EAGAIN)) { + tf->watch_in = b_input_add(tf->fd, B_EV_IO_READ, jabber_bs_recv_read, bt); return FALSE; } } /* shouldn't happen since we know the file size */ - if( ret == 0 ) - return jabber_bs_abort( bt, "Remote end closed connection" ); - + if (ret == 0) { + return jabber_bs_abort(bt, "Remote end closed connection"); + } + tf->bytesread += ret; - if( tf->bytesread >= tf->ft->file_size ) - imcb_file_finished( tf->ic, tf->ft ); + if (tf->bytesread >= tf->ft->file_size) { + imcb_file_finished(tf->ic, tf->ft); + } - tf->ft->write( tf->ft, tf->ft->buffer, ret ); + tf->ft->write(tf->ft, tf->ft->buffer, ret); return FALSE; } -/* +/* * imc callback that is invoked when it is ready to receive some data. */ -gboolean jabber_bs_recv_write_request( file_transfer_t *ft ) +gboolean jabber_bs_recv_write_request(file_transfer_t *ft) { struct jabber_transfer *tf = ft->data; - if( tf->watch_in ) - { - imcb_file_canceled( tf->ic, ft, "BUG in jabber file transfer: write_request called when already watching for input" ); + if (tf->watch_in) { + imcb_file_canceled(tf->ic, ft, + "BUG in jabber file transfer: write_request called when already watching for input"); return FALSE; } - - jabber_bs_recv_read( tf->streamhandle, -1 , 0 ); + + jabber_bs_recv_read(tf->streamhandle, -1, 0); return TRUE; } -/* +/* * Issues a write_request to imc. * */ -gboolean jabber_bs_send_can_write( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_bs_send_can_write(gpointer data, gint fd, b_input_condition cond) { struct bs_transfer *bt = data; bt->tf->watch_out = 0; - bt->tf->ft->write_request( bt->tf->ft ); + bt->tf->ft->write_request(bt->tf->ft); return FALSE; } @@ -691,36 +693,40 @@ gboolean jabber_bs_send_can_write( gpointer data, gint fd, b_input_condition con * This should only be called if we can write, so just do it. * Add a write watch so we can write more during the next cycle (if possible). */ -gboolean jabber_bs_send_write( file_transfer_t *ft, char *buffer, unsigned int len ) +gboolean jabber_bs_send_write(file_transfer_t *ft, char *buffer, unsigned int len) { struct jabber_transfer *tf = ft->data; struct bs_transfer *bt = tf->streamhandle; int ret; - if( tf->watch_out ) - return jabber_bs_abort( bt, "BUG: write() called while watching " ); - + if (tf->watch_out) { + return jabber_bs_abort(bt, "BUG: write() called while watching "); + } + /* TODO: catch broken pipe */ - ASSERTSOCKOP( ret = send( tf->fd, buffer, len, 0 ), "Sending" ); + ASSERTSOCKOP(ret = send(tf->fd, buffer, len, 0), "Sending"); tf->byteswritten += ret; - + /* TODO: this should really not be fatal */ - if( ret < len ) - return jabber_bs_abort( bt, "send() sent %d instead of %d (send buffer too big!)", ret, len ); - - if( tf->byteswritten >= ft->file_size ) - imcb_file_finished( tf->ic, ft ); - else - bt->tf->watch_out = b_input_add( tf->fd, B_EV_IO_WRITE, jabber_bs_send_can_write, bt ); - + if (ret < len) { + return jabber_bs_abort(bt, "send() sent %d instead of %d (send buffer too big!)", ret, len); + } + + if (tf->byteswritten >= ft->file_size) { + imcb_file_finished(tf->ic, ft); + } else { + bt->tf->watch_out = b_input_add(tf->fd, B_EV_IO_WRITE, jabber_bs_send_can_write, bt); + } + return TRUE; } /* * Handles the reply by the receiver containing the used streamhost. */ -static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) { +static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) +{ struct jabber_transfer *tf = NULL; struct jabber_data *jd = ic->proto_data; struct bs_transfer *bt; @@ -728,37 +734,31 @@ static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt struct xt_node *c; char *sid, *jid; - if( !( c = xt_find_node( node->children, "query" ) ) || - !( c = xt_find_node( c->children, "streamhost-used" ) ) || - !( jid = xt_find_attr( c, "jid" ) ) ) - - { - imcb_log( ic, "WARNING: Received incomplete bytestream reply" ); + if (!(c = xt_find_node(node->children, "query")) || + !(c = xt_find_node(c->children, "streamhost-used")) || + !(jid = xt_find_attr(c, "jid"))) { + imcb_log(ic, "WARNING: Received incomplete bytestream reply"); return XT_HANDLED; } - - if( !( c = xt_find_node( orig->children, "query" ) ) || - !( sid = xt_find_attr( c, "sid" ) ) ) - { - imcb_log( ic, "WARNING: Error parsing request corresponding to the incoming bytestream reply" ); + + if (!(c = xt_find_node(orig->children, "query")) || + !(sid = xt_find_attr(c, "sid"))) { + imcb_log(ic, "WARNING: Error parsing request corresponding to the incoming bytestream reply"); return XT_HANDLED; } /* Let's see if we can find out what this bytestream should be for... */ - for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) ) - { + for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) { struct jabber_transfer *tft = tflist->data; - if( ( strcmp( tft->sid, sid ) == 0 ) ) - { - tf = tft; + if ((strcmp(tft->sid, sid) == 0)) { + tf = tft; break; } } - if( !tf ) - { - imcb_log( ic, "WARNING: Received SOCKS5 bytestream reply to unknown request" ); + if (!tf) { + imcb_log(ic, "WARNING: Received SOCKS5 bytestream reply to unknown request"); return XT_HANDLED; } @@ -766,82 +766,75 @@ static xt_status jabber_bs_send_handle_reply(struct im_connection *ic, struct xt tf->accepted = TRUE; - if( strcmp( jid, tf->ini_jid ) == 0 ) - { + if (strcmp(jid, tf->ini_jid) == 0) { /* we're streamhost and target */ - if( bt->phase == BS_PHASE_REPLY ) - { + if (bt->phase == BS_PHASE_REPLY) { /* handshake went through, let's start transferring */ - tf->ft->write_request( tf->ft ); + tf->ft->write_request(tf->ft); } - } else - { + } else { /* using a proxy, abort listen */ - if( tf->watch_in ) - { - b_event_remove( tf->watch_in ); + if (tf->watch_in) { + b_event_remove(tf->watch_in); tf->watch_in = 0; } - - if( tf->fd != -1 ) { - closesocket( tf->fd ); + + if (tf->fd != -1) { + closesocket(tf->fd); tf->fd = -1; } - if ( bt->connect_timeout ) - { - b_event_remove( bt->connect_timeout ); + if (bt->connect_timeout) { + b_event_remove(bt->connect_timeout); bt->connect_timeout = 0; } GSList *shlist; - for( shlist = jd->streamhosts ; shlist ; shlist = g_slist_next( shlist ) ) - { + for (shlist = jd->streamhosts; shlist; shlist = g_slist_next(shlist)) { jabber_streamhost_t *sh = shlist->data; - if( strcmp( sh->jid, jid ) == 0 ) - { + if (strcmp(sh->jid, jid) == 0) { bt->sh = sh; - jabber_bs_recv_handshake( bt, -1, 0 ); + jabber_bs_recv_handshake(bt, -1, 0); return XT_HANDLED; } } - imcb_log( ic, "WARNING: Received SOCKS5 bytestream reply with unknown streamhost %s", jid ); + imcb_log(ic, "WARNING: Received SOCKS5 bytestream reply with unknown streamhost %s", jid); } return XT_HANDLED; } -/* +/* * Tell the proxy to activate the stream. Looks like this: * * <iq type=set> - * <query xmlns=bs sid=sid> - * <activate>tgt_jid</activate> - * </query> + * <query xmlns=bs sid=sid> + * <activate>tgt_jid</activate> + * </query> * </iq> */ -void jabber_bs_send_activate( struct bs_transfer *bt ) +void jabber_bs_send_activate(struct bs_transfer *bt) { struct xt_node *node; - node = xt_new_node( "activate", bt->tf->tgt_jid, NULL ); - node = xt_new_node( "query", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_BYTESTREAMS ); - xt_add_attr( node, "sid", bt->tf->sid ); - node = jabber_make_packet( "iq", "set", bt->sh->jid, node ); + node = xt_new_node("activate", bt->tf->tgt_jid, NULL); + node = xt_new_node("query", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_BYTESTREAMS); + xt_add_attr(node, "sid", bt->tf->sid); + node = jabber_make_packet("iq", "set", bt->sh->jid, node); - jabber_cache_add( bt->tf->ic, node, jabber_bs_send_handle_activate ); + jabber_cache_add(bt->tf->ic, node, jabber_bs_send_handle_activate); - jabber_write_packet( bt->tf->ic, node ); + jabber_write_packet(bt->tf->ic, node); } /* * The proxy has activated the bytestream. * We can finally start pushing some data out. */ -static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_bs_send_handle_activate(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { char *sid; GSList *tflist; @@ -849,100 +842,101 @@ static xt_status jabber_bs_send_handle_activate( struct im_connection *ic, struc struct xt_node *query; struct jabber_data *jd = ic->proto_data; - query = xt_find_node( orig->children, "query" ); - sid = xt_find_attr( query, "sid" ); + query = xt_find_node(orig->children, "query"); + sid = xt_find_attr(query, "sid"); - for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) ) - { + for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) { struct jabber_transfer *tft = tflist->data; - if( ( strcmp( tft->sid, sid ) == 0 ) ) - { - tf = tft; + if ((strcmp(tft->sid, sid) == 0)) { + tf = tft; break; } } - if( !tf ) - { - imcb_log( ic, "WARNING: Received SOCKS5 bytestream activation for unknown stream" ); + if (!tf) { + imcb_log(ic, "WARNING: Received SOCKS5 bytestream activation for unknown stream"); return XT_HANDLED; } - imcb_log( tf->ic, "File %s: SOCKS5 handshake and activation successful! Transfer about to start...", tf->ft->file_name ); + imcb_log(tf->ic, "File %s: SOCKS5 handshake and activation successful! Transfer about to start...", + tf->ft->file_name); /* handshake went through, let's start transferring */ - tf->ft->write_request( tf->ft ); + tf->ft->write_request(tf->ft); return XT_HANDLED; } -jabber_streamhost_t *jabber_si_parse_proxy( struct im_connection *ic, char *proxy ) +jabber_streamhost_t *jabber_si_parse_proxy(struct im_connection *ic, char *proxy) { char *host, *port, *jid; jabber_streamhost_t *sh; - if( ( ( host = strchr( proxy, ',' ) ) == 0 ) || - ( ( port = strchr( host+1, ',' ) ) == 0 ) ) - { - imcb_log( ic, "Error parsing proxy setting: \"%s\" (ignored)", proxy ); + if (((host = strchr(proxy, ',')) == 0) || + ((port = strchr(host + 1, ',')) == 0)) { + imcb_log(ic, "Error parsing proxy setting: \"%s\" (ignored)", proxy); return NULL; } - + jid = proxy; *host++ = '\0'; *port++ = '\0'; - sh = g_new0( jabber_streamhost_t, 1 ); - sh->jid = g_strdup( jid ); - sh->host = g_strdup( host ); - g_snprintf( sh->port, sizeof( sh->port ), "%s", port ); + sh = g_new0(jabber_streamhost_t, 1); + sh->jid = g_strdup(jid); + sh->host = g_strdup(host); + g_snprintf(sh->port, sizeof(sh->port), "%s", port); return sh; } -void jabber_si_set_proxies( struct bs_transfer *bt ) +void jabber_si_set_proxies(struct bs_transfer *bt) { struct jabber_transfer *tf = bt->tf; struct jabber_data *jd = tf->ic->proto_data; - char *proxysetting = g_strdup ( set_getstr( &tf->ic->acc->set, "proxy" ) ); + char *proxysetting = g_strdup(set_getstr(&tf->ic->acc->set, "proxy")); char *proxy, *next, *errmsg = NULL; char port[6]; - char host[HOST_NAME_MAX+1]; + char host[HOST_NAME_MAX + 1]; jabber_streamhost_t *sh, *sh2; GSList *streamhosts = jd->streamhosts; proxy = proxysetting; - while ( proxy && ( *proxy!='\0' ) ) { - if( ( next = strchr( proxy, ';' ) ) ) - *next++ = '\0'; - - if( strcmp( proxy, "<local>" ) == 0 ) { - if( ( tf->fd = ft_listen( &tf->saddr, host, port, jd->fd, FALSE, &errmsg ) ) != -1 ) { - sh = g_new0( jabber_streamhost_t, 1 ); - sh->jid = g_strdup( tf->ini_jid ); - sh->host = g_strdup( host ); - g_snprintf( sh->port, sizeof( sh->port ), "%s", port ); - bt->streamhosts = g_slist_append( bt->streamhosts, sh ); - - bt->tf->watch_in = b_input_add( tf->fd, B_EV_IO_READ, jabber_bs_send_handshake, bt ); - bt->connect_timeout = b_timeout_add( JABBER_BS_LISTEN_TIMEOUT * 1000, jabber_bs_connect_timeout, bt ); + while (proxy && (*proxy != '\0')) { + if ((next = strchr(proxy, ';'))) { + *next++ = '\0'; + } + + if (strcmp(proxy, "<local>") == 0) { + if ((tf->fd = ft_listen(&tf->saddr, host, port, jd->fd, FALSE, &errmsg)) != -1) { + sh = g_new0(jabber_streamhost_t, 1); + sh->jid = g_strdup(tf->ini_jid); + sh->host = g_strdup(host); + g_snprintf(sh->port, sizeof(sh->port), "%s", port); + bt->streamhosts = g_slist_append(bt->streamhosts, sh); + + bt->tf->watch_in = b_input_add(tf->fd, B_EV_IO_READ, jabber_bs_send_handshake, bt); + bt->connect_timeout = b_timeout_add(JABBER_BS_LISTEN_TIMEOUT * 1000, + jabber_bs_connect_timeout, bt); } else { - imcb_log( tf->ic, "Transferring file %s: couldn't listen locally(non fatal, check your ft_listen setting in bitlbee.conf): %s", - tf->ft->file_name, - errmsg ); + imcb_log(tf->ic, + "Transferring file %s: couldn't listen locally(non fatal, check your ft_listen setting in bitlbee.conf): %s", + tf->ft->file_name, + errmsg); } - } else if( strcmp( proxy, "<auto>" ) == 0 ) { - while ( streamhosts ) { - sh = g_new0( jabber_streamhost_t, 1 ); + } else if (strcmp(proxy, "<auto>") == 0) { + while (streamhosts) { + sh = g_new0(jabber_streamhost_t, 1); sh2 = streamhosts->data; - sh->jid = g_strdup( sh2->jid ); - sh->host = g_strdup( sh2->host ); - strcpy( sh->port, sh2->port ); - bt->streamhosts = g_slist_append( bt->streamhosts, sh ); - streamhosts = g_slist_next( streamhosts ); + sh->jid = g_strdup(sh2->jid); + sh->host = g_strdup(sh2->host); + strcpy(sh->port, sh2->port); + bt->streamhosts = g_slist_append(bt->streamhosts, sh); + streamhosts = g_slist_next(streamhosts); } - } else if( ( sh = jabber_si_parse_proxy( tf->ic, proxy ) ) ) - bt->streamhosts = g_slist_append( bt->streamhosts, sh ); + } else if ((sh = jabber_si_parse_proxy(tf->ic, proxy))) { + bt->streamhosts = g_slist_append(bt->streamhosts, sh); + } proxy = next; } } @@ -950,83 +944,86 @@ void jabber_si_set_proxies( struct bs_transfer *bt ) /* * Starts a bytestream. */ -gboolean jabber_bs_send_start( struct jabber_transfer *tf ) +gboolean jabber_bs_send_start(struct jabber_transfer *tf) { struct bs_transfer *bt; sha1_state_t sha; char hash_hex[41]; unsigned char hash[20]; - int i,ret; + int i, ret; /* SHA1( SID + Initiator JID + Target JID ) is given to the streamhost which it will match against the initiator's value */ - sha1_init( &sha ); - sha1_append( &sha, (unsigned char*) tf->sid, strlen( tf->sid ) ); - sha1_append( &sha, (unsigned char*) tf->ini_jid, strlen( tf->ini_jid ) ); - sha1_append( &sha, (unsigned char*) tf->tgt_jid, strlen( tf->tgt_jid ) ); - sha1_finish( &sha, hash ); - - for( i = 0; i < 20; i ++ ) - sprintf( hash_hex + i * 2, "%02x", hash[i] ); - - bt = g_new0( struct bs_transfer, 1 ); + sha1_init(&sha); + sha1_append(&sha, (unsigned char *) tf->sid, strlen(tf->sid)); + sha1_append(&sha, (unsigned char *) tf->ini_jid, strlen(tf->ini_jid)); + sha1_append(&sha, (unsigned char *) tf->tgt_jid, strlen(tf->tgt_jid)); + sha1_finish(&sha, hash); + + for (i = 0; i < 20; i++) { + sprintf(hash_hex + i * 2, "%02x", hash[i]); + } + + bt = g_new0(struct bs_transfer, 1); bt->tf = tf; bt->phase = BS_PHASE_CONNECT; - bt->pseudoadr = g_strdup( hash_hex ); + bt->pseudoadr = g_strdup(hash_hex); tf->streamhandle = bt; tf->ft->free = jabber_bs_free_transfer; tf->ft->canceled = jabber_bs_canceled; - jabber_si_set_proxies( bt ); + jabber_si_set_proxies(bt); - ret = jabber_bs_send_request( tf, bt->streamhosts); + ret = jabber_bs_send_request(tf, bt->streamhosts); return ret; } -gboolean jabber_bs_send_request( struct jabber_transfer *tf, GSList *streamhosts ) +gboolean jabber_bs_send_request(struct jabber_transfer *tf, GSList *streamhosts) { struct xt_node *shnode, *query, *iq; - query = xt_new_node( "query", NULL, NULL ); - xt_add_attr( query, "xmlns", XMLNS_BYTESTREAMS ); - xt_add_attr( query, "sid", tf->sid ); - xt_add_attr( query, "mode", "tcp" ); + query = xt_new_node("query", NULL, NULL); + xt_add_attr(query, "xmlns", XMLNS_BYTESTREAMS); + xt_add_attr(query, "sid", tf->sid); + xt_add_attr(query, "mode", "tcp"); - while( streamhosts ) { + while (streamhosts) { jabber_streamhost_t *sh = streamhosts->data; - shnode = xt_new_node( "streamhost", NULL, NULL ); - xt_add_attr( shnode, "jid", sh->jid ); - xt_add_attr( shnode, "host", sh->host ); - xt_add_attr( shnode, "port", sh->port ); + shnode = xt_new_node("streamhost", NULL, NULL); + xt_add_attr(shnode, "jid", sh->jid); + xt_add_attr(shnode, "host", sh->host); + xt_add_attr(shnode, "port", sh->port); - xt_add_child( query, shnode ); + xt_add_child(query, shnode); - streamhosts = g_slist_next( streamhosts ); + streamhosts = g_slist_next(streamhosts); } - iq = jabber_make_packet( "iq", "set", tf->tgt_jid, query ); - xt_add_attr( iq, "from", tf->ini_jid ); + iq = jabber_make_packet("iq", "set", tf->tgt_jid, query); + xt_add_attr(iq, "from", tf->ini_jid); - jabber_cache_add( tf->ic, iq, jabber_bs_send_handle_reply ); + jabber_cache_add(tf->ic, iq, jabber_bs_send_handle_reply); - if( !jabber_write_packet( tf->ic, iq ) ) - imcb_file_canceled( tf->ic, tf->ft, "Error transmitting bytestream request" ); + if (!jabber_write_packet(tf->ic, iq)) { + imcb_file_canceled(tf->ic, tf->ft, "Error transmitting bytestream request"); + } return TRUE; } -gboolean jabber_bs_send_handshake_abort(struct bs_transfer *bt, char *error ) +gboolean jabber_bs_send_handshake_abort(struct bs_transfer *bt, char *error) { struct jabber_transfer *tf = bt->tf; struct jabber_data *jd = tf->ic->proto_data; /* TODO: did the receiver get here somehow??? */ - imcb_log( tf->ic, "Transferring file %s: SOCKS5 handshake failed: %s", - tf->ft->file_name, - error ); + imcb_log(tf->ic, "Transferring file %s: SOCKS5 handshake failed: %s", + tf->ft->file_name, + error); - if( jd->streamhosts==NULL ) /* we're done here unless we have a proxy to try */ - imcb_file_canceled( tf->ic, tf->ft, error ); + if (jd->streamhosts == NULL) { /* we're done here unless we have a proxy to try */ + imcb_file_canceled(tf->ic, tf->ft, error); + } /* MUST always return FALSE! */ return FALSE; @@ -1035,123 +1032,136 @@ gboolean jabber_bs_send_handshake_abort(struct bs_transfer *bt, char *error ) /* * SOCKS5BYTESTREAM protocol for the sender */ -gboolean jabber_bs_send_handshake( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_bs_send_handshake(gpointer data, gint fd, b_input_condition cond) { struct bs_transfer *bt = data; struct jabber_transfer *tf = bt->tf; short revents; - if ( !jabber_bs_poll( bt, fd, &revents ) ) + if (!jabber_bs_poll(bt, fd, &revents)) { return FALSE; - - switch( bt->phase ) - { + } + + switch (bt->phase) { case BS_PHASE_CONNECT: - { - struct sockaddr_storage clt_addr; - socklen_t ssize = sizeof( clt_addr ); - - /* Connect */ + { + struct sockaddr_storage clt_addr; + socklen_t ssize = sizeof(clt_addr); - ASSERTSOCKOP( tf->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" ); + /* Connect */ - closesocket( fd ); - fd = tf->fd; - sock_make_nonblocking( fd ); - - bt->phase = BS_PHASE_CONNECTED; + ASSERTSOCKOP(tf->fd = accept(fd, (struct sockaddr *) &clt_addr, &ssize), "Accepting connection"); - bt->tf->watch_in = b_input_add( fd, B_EV_IO_READ, jabber_bs_send_handshake, bt ); + closesocket(fd); + fd = tf->fd; + sock_make_nonblocking(fd); + + bt->phase = BS_PHASE_CONNECTED; + + bt->tf->watch_in = b_input_add(fd, B_EV_IO_READ, jabber_bs_send_handshake, bt); + return FALSE; + } + case BS_PHASE_CONNECTED: + { + int ret, have_noauth = FALSE; + struct { + unsigned char ver; + unsigned char method; + } socks5_auth_reply = { .ver = 5, .method = 0 }; + struct { + unsigned char ver; + unsigned char nmethods; + unsigned char method; + } socks5_hello; + + if (!(ret = jabber_bs_peek(bt, &socks5_hello, sizeof(socks5_hello)))) { return FALSE; } - case BS_PHASE_CONNECTED: - { - int ret, have_noauth=FALSE; - struct { - unsigned char ver; - unsigned char method; - } socks5_auth_reply = { .ver = 5, .method = 0 }; - struct { - unsigned char ver; - unsigned char nmethods; - unsigned char method; - } socks5_hello; - - if( !( ret = jabber_bs_peek( bt, &socks5_hello, sizeof( socks5_hello ) ) ) ) - return FALSE; - - if( ret < sizeof( socks5_hello ) ) - return TRUE; - - if( !( socks5_hello.ver == 5 ) || - !( socks5_hello.nmethods >= 1 ) || - !( socks5_hello.nmethods < 32 ) ) - return jabber_bs_abort( bt, "Invalid auth request ver=%d nmethods=%d method=%d", socks5_hello.ver, socks5_hello.nmethods, socks5_hello.method ); - - have_noauth = socks5_hello.method == 0; - - if( socks5_hello.nmethods > 1 ) - { - char mbuf[32]; - int i; - ASSERTSOCKOP( ret = recv( fd, mbuf, socks5_hello.nmethods - 1, 0 ) , "Receiving auth methods" ); - if( ret < ( socks5_hello.nmethods - 1 ) ) - return jabber_bs_abort( bt, "Partial auth request"); - for( i = 0 ; !have_noauth && ( i < socks5_hello.nmethods - 1 ) ; i ++ ) - if( mbuf[i] == 0 ) - have_noauth = TRUE; - } - - if( !have_noauth ) - return jabber_bs_abort( bt, "Auth request didn't include no authentication" ); - ASSERTSOCKOP( send( fd, &socks5_auth_reply, sizeof( socks5_auth_reply ) , 0 ), "Sending auth reply" ); + if (ret < sizeof(socks5_hello)) { + return TRUE; + } - bt->phase = BS_PHASE_REQUEST; + if (!(socks5_hello.ver == 5) || + !(socks5_hello.nmethods >= 1) || + !(socks5_hello.nmethods < 32)) { + return jabber_bs_abort(bt, "Invalid auth request ver=%d nmethods=%d method=%d", + socks5_hello.ver, socks5_hello.nmethods, socks5_hello.method); + } - return TRUE; + have_noauth = socks5_hello.method == 0; + + if (socks5_hello.nmethods > 1) { + char mbuf[32]; + int i; + ASSERTSOCKOP(ret = recv(fd, mbuf, socks5_hello.nmethods - 1, 0), "Receiving auth methods"); + if (ret < (socks5_hello.nmethods - 1)) { + return jabber_bs_abort(bt, "Partial auth request"); + } + for (i = 0; !have_noauth && (i < socks5_hello.nmethods - 1); i++) { + if (mbuf[i] == 0) { + have_noauth = TRUE; + } + } } - case BS_PHASE_REQUEST: - { - struct socks5_message socks5_connect; - int msgsize = sizeof( struct socks5_message ); - int ret; - if( !( ret = jabber_bs_peek( bt, &socks5_connect, msgsize ) ) ) - return FALSE; + if (!have_noauth) { + return jabber_bs_abort(bt, "Auth request didn't include no authentication"); + } - if( ret < msgsize ) - return TRUE; + ASSERTSOCKOP(send(fd, &socks5_auth_reply, sizeof(socks5_auth_reply), 0), "Sending auth reply"); - if( !( socks5_connect.ver == 5) || - !( socks5_connect.cmdrep.cmd == 1 ) || - !( socks5_connect.atyp == 3 ) || - !(socks5_connect.addrlen == 40 ) ) - return jabber_bs_abort( bt, "Invalid SOCKS5 Connect message (addrlen=%d, ver=%d, cmd=%d, atyp=%d)", socks5_connect.addrlen, socks5_connect.ver, socks5_connect.cmdrep.cmd, socks5_connect.atyp ); - if( !( memcmp( socks5_connect.address, bt->pseudoadr, 40 ) == 0 ) ) - return jabber_bs_abort( bt, "SOCKS5 Connect message contained wrong digest"); + bt->phase = BS_PHASE_REQUEST; - socks5_connect.cmdrep.rep = 0; + return TRUE; + } + case BS_PHASE_REQUEST: + { + struct socks5_message socks5_connect; + int msgsize = sizeof(struct socks5_message); + int ret; + + if (!(ret = jabber_bs_peek(bt, &socks5_connect, msgsize))) { + return FALSE; + } + + if (ret < msgsize) { + return TRUE; + } - ASSERTSOCKOP( send( fd, &socks5_connect, msgsize, 0 ), "Sending connect reply" ); + if (!(socks5_connect.ver == 5) || + !(socks5_connect.cmdrep.cmd == 1) || + !(socks5_connect.atyp == 3) || + !(socks5_connect.addrlen == 40)) { + return jabber_bs_abort(bt, + "Invalid SOCKS5 Connect message (addrlen=%d, ver=%d, cmd=%d, atyp=%d)", + socks5_connect.addrlen, socks5_connect.ver, socks5_connect.cmdrep.cmd, + socks5_connect.atyp); + } + if (!(memcmp(socks5_connect.address, bt->pseudoadr, 40) == 0)) { + return jabber_bs_abort(bt, "SOCKS5 Connect message contained wrong digest"); + } - bt->phase = BS_PHASE_REPLY; + socks5_connect.cmdrep.rep = 0; - imcb_log( tf->ic, "File %s: SOCKS5 handshake successful! Transfer about to start...", tf->ft->file_name ); + ASSERTSOCKOP(send(fd, &socks5_connect, msgsize, 0), "Sending connect reply"); - if( tf->accepted ) - { - /* streamhost-used message came already in(possible?), let's start sending */ - tf->ft->write_request( tf->ft ); - } + bt->phase = BS_PHASE_REPLY; - tf->watch_in = 0; - return FALSE; + imcb_log(tf->ic, "File %s: SOCKS5 handshake successful! Transfer about to start...", tf->ft->file_name); + if (tf->accepted) { + /* streamhost-used message came already in(possible?), let's start sending */ + tf->ft->write_request(tf->ft); } + + tf->watch_in = 0; + return FALSE; + + } default: /* BUG */ - imcb_log( bt->tf->ic, "BUG in file transfer code: undefined handshake phase" ); + imcb_log(bt->tf->ic, "BUG in file transfer code: undefined handshake phase"); bt->tf->watch_in = 0; return FALSE; diff --git a/protocols/jabber/sasl.c b/protocols/jabber/sasl.c index 65da529a..19ab7ec7 100644 --- a/protocols/jabber/sasl.c +++ b/protocols/jabber/sasl.c @@ -47,7 +47,7 @@ const struct oauth2_service oauth2_service_facebook = "4b100f0f244d620bf3f15f8b217d4c32", }; -xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) +xt_status sasl_pkt_mechanisms(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; @@ -56,213 +56,192 @@ xt_status sasl_pkt_mechanisms( struct xt_node *node, gpointer data ) int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0; int want_oauth = FALSE; GString *mechs; - - if( !sasl_supported( ic ) ) - { + + if (!sasl_supported(ic)) { /* Should abort this now, since we should already be doing IQ authentication. Strange things happen when you try to do both... */ - imcb_log( ic, "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!" ); + imcb_log(ic, + "XMPP 1.0 non-compliant server seems to support SASL, please report this as a BitlBee bug!"); return XT_HANDLED; } - - s = xt_find_attr( node, "xmlns" ); - if( !s || strcmp( s, XMLNS_SASL ) != 0 ) - { - imcb_log( ic, "Stream error while authenticating" ); - imc_logout( ic, FALSE ); + + s = xt_find_attr(node, "xmlns"); + if (!s || strcmp(s, XMLNS_SASL) != 0) { + imcb_log(ic, "Stream error while authenticating"); + imc_logout(ic, FALSE); return XT_ABORT; } - - want_oauth = set_getbool( &ic->acc->set, "oauth" ); - - mechs = g_string_new( "" ); + + want_oauth = set_getbool(&ic->acc->set, "oauth"); + + mechs = g_string_new(""); c = node->children; - while( ( c = xt_find_node( c, "mechanism" ) ) ) - { - if( c->text && g_strcasecmp( c->text, "PLAIN" ) == 0 ) + while ((c = xt_find_node(c, "mechanism"))) { + if (c->text && g_strcasecmp(c->text, "PLAIN") == 0) { sup_plain = 1; - else if( c->text && g_strcasecmp( c->text, "DIGEST-MD5" ) == 0 ) + } else if (c->text && g_strcasecmp(c->text, "DIGEST-MD5") == 0) { sup_digest = 1; - else if( c->text && g_strcasecmp( c->text, "X-OAUTH2" ) == 0 ) + } else if (c->text && g_strcasecmp(c->text, "X-OAUTH2") == 0) { sup_gtalk = 1; - else if( c->text && g_strcasecmp( c->text, "X-FACEBOOK-PLATFORM" ) == 0 ) + } else if (c->text && g_strcasecmp(c->text, "X-FACEBOOK-PLATFORM") == 0) { sup_fb = 1; - - if( c->text ) - g_string_append_printf( mechs, " %s", c->text ); - + } + + if (c->text) { + g_string_append_printf(mechs, " %s", c->text); + } + c = c->next; } - - if( !want_oauth && !sup_plain && !sup_digest ) - { - if( !sup_gtalk && !sup_fb ) - imcb_error( ic, "This server requires OAuth " - "(supported schemes:%s)", mechs->str ); - else - imcb_error( ic, "BitlBee does not support any of the offered SASL " - "authentication schemes:%s", mechs->str ); - imc_logout( ic, FALSE ); - g_string_free( mechs, TRUE ); + + if (!want_oauth && !sup_plain && !sup_digest) { + if (!sup_gtalk && !sup_fb) { + imcb_error(ic, "This server requires OAuth " + "(supported schemes:%s)", mechs->str); + } else { + imcb_error(ic, "BitlBee does not support any of the offered SASL " + "authentication schemes:%s", mechs->str); + } + imc_logout(ic, FALSE); + g_string_free(mechs, TRUE); return XT_ABORT; } - g_string_free( mechs, TRUE ); - - reply = xt_new_node( "auth", NULL, NULL ); - xt_add_attr( reply, "xmlns", XMLNS_SASL ); - - if( sup_gtalk && want_oauth ) - { + g_string_free(mechs, TRUE); + + reply = xt_new_node("auth", NULL, NULL); + xt_add_attr(reply, "xmlns", XMLNS_SASL); + + if (sup_gtalk && want_oauth) { int len; - + /* X-OAUTH2 is, not *the* standard OAuth2 SASL/XMPP implementation. It's currently used by GTalk and vaguely documented on http://code.google.com/apis/cloudprint/docs/rawxmpp.html . */ - xt_add_attr( reply, "mechanism", "X-OAUTH2" ); - - len = strlen( jd->username ) + strlen( jd->oauth2_access_token ) + 2; - s = g_malloc( len + 1 ); + xt_add_attr(reply, "mechanism", "X-OAUTH2"); + + len = strlen(jd->username) + strlen(jd->oauth2_access_token) + 2; + s = g_malloc(len + 1); s[0] = 0; - strcpy( s + 1, jd->username ); - strcpy( s + 2 + strlen( jd->username ), jd->oauth2_access_token ); - reply->text = base64_encode( (unsigned char *)s, len ); - reply->text_len = strlen( reply->text ); - g_free( s ); - } - else if( sup_fb && want_oauth ) - { - xt_add_attr( reply, "mechanism", "X-FACEBOOK-PLATFORM" ); + strcpy(s + 1, jd->username); + strcpy(s + 2 + strlen(jd->username), jd->oauth2_access_token); + reply->text = base64_encode((unsigned char *) s, len); + reply->text_len = strlen(reply->text); + g_free(s); + } else if (sup_fb && want_oauth) { + xt_add_attr(reply, "mechanism", "X-FACEBOOK-PLATFORM"); jd->flags |= JFLAG_SASL_FB; - } - else if( want_oauth ) - { - imcb_error( ic, "OAuth requested, but not supported by server" ); - imc_logout( ic, FALSE ); - xt_free_node( reply ); + } else if (want_oauth) { + imcb_error(ic, "OAuth requested, but not supported by server"); + imc_logout(ic, FALSE); + xt_free_node(reply); return XT_ABORT; - } - else if( sup_digest ) - { - xt_add_attr( reply, "mechanism", "DIGEST-MD5" ); - + } else if (sup_digest) { + xt_add_attr(reply, "mechanism", "DIGEST-MD5"); + /* The rest will be done later, when we receive a <challenge/>. */ - } - else if( sup_plain ) - { + } else if (sup_plain) { int len; - - xt_add_attr( reply, "mechanism", "PLAIN" ); - + + xt_add_attr(reply, "mechanism", "PLAIN"); + /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ - len = strlen( jd->username ) + strlen( ic->acc->pass ) + 2; - s = g_malloc( len + 1 ); + len = strlen(jd->username) + strlen(ic->acc->pass) + 2; + s = g_malloc(len + 1); s[0] = 0; - strcpy( s + 1, jd->username ); - strcpy( s + 2 + strlen( jd->username ), ic->acc->pass ); - reply->text = base64_encode( (unsigned char *)s, len ); - reply->text_len = strlen( reply->text ); - g_free( s ); + strcpy(s + 1, jd->username); + strcpy(s + 2 + strlen(jd->username), ic->acc->pass); + reply->text = base64_encode((unsigned char *) s, len); + reply->text_len = strlen(reply->text); + g_free(s); } - - if( reply && !jabber_write_packet( ic, reply ) ) - { - xt_free_node( reply ); + + if (reply && !jabber_write_packet(ic, reply)) { + xt_free_node(reply); return XT_ABORT; } - xt_free_node( reply ); - + xt_free_node(reply); + /* To prevent classic authentication from happening. */ jd->flags |= JFLAG_STREAM_STARTED; - + return XT_HANDLED; } /* Non-static function, but not mentioned in jabber.h because it's for internal use, just that the unittest should be able to reach it... */ -char *sasl_get_part( char *data, char *field ) +char *sasl_get_part(char *data, char *field) { int i, len; - - len = strlen( field ); - - while( g_ascii_isspace( *data ) || *data == ',' ) - data ++; - - if( g_strncasecmp( data, field, len ) == 0 && data[len] == '=' ) - { - i = strlen( field ) + 1; + + len = strlen(field); + + while (g_ascii_isspace(*data) || *data == ',') { + data++; } - else - { - for( i = 0; data[i]; i ++ ) - { + + if (g_strncasecmp(data, field, len) == 0 && data[len] == '=') { + i = strlen(field) + 1; + } else { + for (i = 0; data[i]; i++) { /* If we have a ", skip until it's closed again. */ - if( data[i] == '"' ) - { - i ++; - while( data[i] != '"' || data[i-1] == '\\' ) - i ++; + if (data[i] == '"') { + i++; + while (data[i] != '"' || data[i - 1] == '\\') { + i++; + } } - + /* If we got a comma, we got a new field. Check it, find the next key after it. */ - if( data[i] == ',' ) - { - while( g_ascii_isspace( data[i] ) || data[i] == ',' ) - i ++; - - if( g_strncasecmp( data + i, field, len ) == 0 && - data[i+len] == '=' ) - { + if (data[i] == ',') { + while (g_ascii_isspace(data[i]) || data[i] == ',') { + i++; + } + + if (g_strncasecmp(data + i, field, len) == 0 && + data[i + len] == '=') { i += len + 1; break; } } } } - - if( data[i] == '"' ) - { + + if (data[i] == '"') { int j; char *ret; - - i ++; + + i++; len = 0; - while( data[i+len] != '"' || data[i+len-1] == '\\' ) - len ++; - - ret = g_strndup( data + i, len ); - for( i = j = 0; ret[i]; i ++ ) - { - if( ret[i] == '\\' ) - { + while (data[i + len] != '"' || data[i + len - 1] == '\\') { + len++; + } + + ret = g_strndup(data + i, len); + for (i = j = 0; ret[i]; i++) { + if (ret[i] == '\\') { ret[j++] = ret[++i]; - } - else - { + } else { ret[j++] = ret[i]; } } ret[j] = 0; - + return ret; - } - else if( data[i] ) - { + } else if (data[i]) { len = 0; - while( data[i+len] && data[i+len] != ',' ) - len ++; - - return g_strndup( data + i, len ); - } - else - { + while (data[i + len] && data[i + len] != ',') { + len++; + } + + return g_strndup(data + i, len); + } else { return NULL; } } -xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) +xt_status sasl_pkt_challenge(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; @@ -273,259 +252,262 @@ xt_status sasl_pkt_challenge( struct xt_node *node, gpointer data ) char *dec = NULL; char *s = NULL, *reply = NULL; xt_status ret = XT_ABORT; - - if( node->text_len == 0 ) + + if (node->text_len == 0) { goto error; - - dec = frombase64( node->text ); - - if( jd->flags & JFLAG_SASL_FB ) - { + } + + dec = frombase64(node->text); + + if (jd->flags & JFLAG_SASL_FB) { /* New-style Facebook OAauth2 support. Instead of sending a refresh token, they just send an access token that should never expire. */ GSList *p_in = NULL, *p_out = NULL; char time[33]; - - oauth_params_parse( &p_in, dec ); - oauth_params_add( &p_out, "nonce", oauth_params_get( &p_in, "nonce" ) ); - oauth_params_add( &p_out, "method", oauth_params_get( &p_in, "method" ) ); - oauth_params_free( &p_in ); - - g_snprintf( time, sizeof( time ), "%lld", (long long) ( gettime() * 1000 ) ); - oauth_params_add( &p_out, "call_id", time ); - oauth_params_add( &p_out, "api_key", oauth2_service_facebook.consumer_key ); - oauth_params_add( &p_out, "v", "1.0" ); - oauth_params_add( &p_out, "format", "XML" ); - oauth_params_add( &p_out, "access_token", jd->oauth2_access_token ); - - reply = oauth_params_string( p_out ); - oauth_params_free( &p_out ); - } - else if( !( s = sasl_get_part( dec, "rspauth" ) ) ) - { + + oauth_params_parse(&p_in, dec); + oauth_params_add(&p_out, "nonce", oauth_params_get(&p_in, "nonce")); + oauth_params_add(&p_out, "method", oauth_params_get(&p_in, "method")); + oauth_params_free(&p_in); + + g_snprintf(time, sizeof(time), "%lld", (long long) (gettime() * 1000)); + oauth_params_add(&p_out, "call_id", time); + oauth_params_add(&p_out, "api_key", oauth2_service_facebook.consumer_key); + oauth_params_add(&p_out, "v", "1.0"); + oauth_params_add(&p_out, "format", "XML"); + oauth_params_add(&p_out, "access_token", jd->oauth2_access_token); + + reply = oauth_params_string(p_out); + oauth_params_free(&p_out); + } else if (!(s = sasl_get_part(dec, "rspauth"))) { /* See RFC 2831 for for information. */ md5_state_t A1, A2, H; md5_byte_t A1r[16], A2r[16], Hr[16]; char A1h[33], A2h[33], Hh[33]; int i; - - nonce = sasl_get_part( dec, "nonce" ); - realm = sasl_get_part( dec, "realm" ); - - if( !nonce ) + + nonce = sasl_get_part(dec, "nonce"); + realm = sasl_get_part(dec, "realm"); + + if (!nonce) { goto error; - + } + /* Jabber.Org considers the realm part optional and doesn't specify one. Oh well, actually they're right, but still, don't know if this is right... */ - if( !realm ) - realm = g_strdup( jd->server ); - - random_bytes( cnonce_bin, sizeof( cnonce_bin ) ); - cnonce = base64_encode( cnonce_bin, sizeof( cnonce_bin ) ); - digest_uri = g_strdup_printf( "%s/%s", "xmpp", jd->server ); - + if (!realm) { + realm = g_strdup(jd->server); + } + + random_bytes(cnonce_bin, sizeof(cnonce_bin)); + cnonce = base64_encode(cnonce_bin, sizeof(cnonce_bin)); + digest_uri = g_strdup_printf("%s/%s", "xmpp", jd->server); + /* Generate the MD5 hash of username:realm:password, I decided to call it H. */ - md5_init( &H ); - s = g_strdup_printf( "%s:%s:%s", jd->username, realm, ic->acc->pass ); - md5_append( &H, (unsigned char *) s, strlen( s ) ); - g_free( s ); - md5_finish( &H, Hr ); - + md5_init(&H); + s = g_strdup_printf("%s:%s:%s", jd->username, realm, ic->acc->pass); + md5_append(&H, (unsigned char *) s, strlen(s)); + g_free(s); + md5_finish(&H, Hr); + /* Now generate the hex. MD5 hash of H:nonce:cnonce, called A1. */ - md5_init( &A1 ); - s = g_strdup_printf( ":%s:%s", nonce, cnonce ); - md5_append( &A1, Hr, 16 ); - md5_append( &A1, (unsigned char *) s, strlen( s ) ); - g_free( s ); - md5_finish( &A1, A1r ); - for( i = 0; i < 16; i ++ ) - sprintf( A1h + i * 2, "%02x", A1r[i] ); - + md5_init(&A1); + s = g_strdup_printf(":%s:%s", nonce, cnonce); + md5_append(&A1, Hr, 16); + md5_append(&A1, (unsigned char *) s, strlen(s)); + g_free(s); + md5_finish(&A1, A1r); + for (i = 0; i < 16; i++) { + sprintf(A1h + i * 2, "%02x", A1r[i]); + } + /* A2... */ - md5_init( &A2 ); - s = g_strdup_printf( "%s:%s", "AUTHENTICATE", digest_uri ); - md5_append( &A2, (unsigned char *) s, strlen( s ) ); - g_free( s ); - md5_finish( &A2, A2r ); - for( i = 0; i < 16; i ++ ) - sprintf( A2h + i * 2, "%02x", A2r[i] ); - + md5_init(&A2); + s = g_strdup_printf("%s:%s", "AUTHENTICATE", digest_uri); + md5_append(&A2, (unsigned char *) s, strlen(s)); + g_free(s); + md5_finish(&A2, A2r); + for (i = 0; i < 16; i++) { + sprintf(A2h + i * 2, "%02x", A2r[i]); + } + /* Final result: A1:nonce:00000001:cnonce:auth:A2. Let's reuse H for it. */ - md5_init( &H ); - s = g_strdup_printf( "%s:%s:%s:%s:%s:%s", A1h, nonce, "00000001", cnonce, "auth", A2h ); - md5_append( &H, (unsigned char *) s, strlen( s ) ); - g_free( s ); - md5_finish( &H, Hr ); - for( i = 0; i < 16; i ++ ) - sprintf( Hh + i * 2, "%02x", Hr[i] ); - + md5_init(&H); + s = g_strdup_printf("%s:%s:%s:%s:%s:%s", A1h, nonce, "00000001", cnonce, "auth", A2h); + md5_append(&H, (unsigned char *) s, strlen(s)); + g_free(s); + md5_finish(&H, Hr); + for (i = 0; i < 16; i++) { + sprintf(Hh + i * 2, "%02x", Hr[i]); + } + /* Now build the SASL response string: */ - reply = g_strdup_printf( "username=\"%s\",realm=\"%s\",nonce=\"%s\",cnonce=\"%s\"," - "nc=%08x,qop=auth,digest-uri=\"%s\",response=%s,charset=%s", - jd->username, realm, nonce, cnonce, 1, digest_uri, Hh, "utf-8" ); - } - else - { + reply = g_strdup_printf("username=\"%s\",realm=\"%s\",nonce=\"%s\",cnonce=\"%s\"," + "nc=%08x,qop=auth,digest-uri=\"%s\",response=%s,charset=%s", + jd->username, realm, nonce, cnonce, 1, digest_uri, Hh, "utf-8"); + } else { /* We found rspauth, but don't really care... */ - g_free( s ); + g_free(s); } - - s = reply ? tobase64( reply ) : NULL; - reply_pkt = xt_new_node( "response", s, NULL ); - xt_add_attr( reply_pkt, "xmlns", XMLNS_SASL ); - - if( !jabber_write_packet( ic, reply_pkt ) ) + + s = reply ? tobase64(reply) : NULL; + reply_pkt = xt_new_node("response", s, NULL); + xt_add_attr(reply_pkt, "xmlns", XMLNS_SASL); + + if (!jabber_write_packet(ic, reply_pkt)) { goto silent_error; - + } + ret = XT_HANDLED; goto silent_error; error: - imcb_error( ic, "Incorrect SASL challenge received" ); - imc_logout( ic, FALSE ); + imcb_error(ic, "Incorrect SASL challenge received"); + imc_logout(ic, FALSE); silent_error: - g_free( digest_uri ); - g_free( cnonce ); - g_free( nonce ); - g_free( reply ); - g_free( realm ); - g_free( dec ); - g_free( s ); - xt_free_node( reply_pkt ); - + g_free(digest_uri); + g_free(cnonce); + g_free(nonce); + g_free(reply); + g_free(realm); + g_free(dec); + g_free(s); + xt_free_node(reply_pkt); + return ret; } -xt_status sasl_pkt_result( struct xt_node *node, gpointer data ) +xt_status sasl_pkt_result(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char *s; - - s = xt_find_attr( node, "xmlns" ); - if( !s || strcmp( s, XMLNS_SASL ) != 0 ) - { - imcb_log( ic, "Stream error while authenticating" ); - imc_logout( ic, FALSE ); + + s = xt_find_attr(node, "xmlns"); + if (!s || strcmp(s, XMLNS_SASL) != 0) { + imcb_log(ic, "Stream error while authenticating"); + imc_logout(ic, FALSE); return XT_ABORT; } - - if( strcmp( node->name, "success" ) == 0 ) - { - imcb_log( ic, "Authentication finished" ); + + if (strcmp(node->name, "success") == 0) { + imcb_log(ic, "Authentication finished"); jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; - } - else if( strcmp( node->name, "failure" ) == 0 ) - { - imcb_error( ic, "Authentication failure" ); - imc_logout( ic, FALSE ); + } else if (strcmp(node->name, "failure") == 0) { + imcb_error(ic, "Authentication failure"); + imc_logout(ic, FALSE); return XT_ABORT; } - + return XT_HANDLED; } /* This one is needed to judge if we'll do authentication using IQ or SASL. It's done by checking if the <stream:stream> from the server has a version attribute. I don't know if this is the right way though... */ -gboolean sasl_supported( struct im_connection *ic ) +gboolean sasl_supported(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; - - return ( jd->xt && jd->xt->root && xt_find_attr( jd->xt->root, "version" ) ) != 0; + + return (jd->xt && jd->xt->root && xt_find_attr(jd->xt->root, "version")) != 0; } -void sasl_oauth2_init( struct im_connection *ic ) +void sasl_oauth2_init(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; char *msg, *url; - - imcb_log( ic, "Starting OAuth authentication" ); - + + imcb_log(ic, "Starting OAuth authentication"); + /* Temporary contact, just used to receive the OAuth response. */ - imcb_add_buddy( ic, JABBER_OAUTH_HANDLE, NULL ); - url = oauth2_url( jd->oauth2_service ); - msg = g_strdup_printf( "Open this URL in your browser to authenticate: %s", url ); - imcb_buddy_msg( ic, JABBER_OAUTH_HANDLE, msg, 0, 0 ); - imcb_buddy_msg( ic, JABBER_OAUTH_HANDLE, "Respond to this message with the returned " - "authorization token.", 0, 0 ); - - g_free( msg ); - g_free( url ); + imcb_add_buddy(ic, JABBER_OAUTH_HANDLE, NULL); + url = oauth2_url(jd->oauth2_service); + msg = g_strdup_printf("Open this URL in your browser to authenticate: %s", url); + imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE, msg, 0, 0); + imcb_buddy_msg(ic, JABBER_OAUTH_HANDLE, "Respond to this message with the returned " + "authorization token.", 0, 0); + + g_free(msg); + g_free(url); } -static gboolean sasl_oauth2_remove_contact( gpointer data, gint fd, b_input_condition cond ) +static gboolean sasl_oauth2_remove_contact(gpointer data, gint fd, b_input_condition cond) { struct im_connection *ic = data; - if( g_slist_find( jabber_connections, ic ) ) - imcb_remove_buddy( ic, JABBER_OAUTH_HANDLE, NULL ); + + if (g_slist_find(jabber_connections, ic)) { + imcb_remove_buddy(ic, JABBER_OAUTH_HANDLE, NULL); + } return FALSE; } -static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token, const char *error ); +static void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token, + const char *error); -int sasl_oauth2_get_refresh_token( struct im_connection *ic, const char *msg ) +int sasl_oauth2_get_refresh_token(struct im_connection *ic, const char *msg) { struct jabber_data *jd = ic->proto_data; char *code; int ret; - - imcb_log( ic, "Requesting OAuth access token" ); - + + imcb_log(ic, "Requesting OAuth access token"); + /* Don't do it here because the caller may get confused if the contact we're currently sending a message to is deleted. */ - b_timeout_add( 1, sasl_oauth2_remove_contact, ic ); - - code = g_strdup( msg ); - g_strstrip( code ); - ret = oauth2_access_token( jd->oauth2_service, OAUTH2_AUTH_CODE, - code, sasl_oauth2_got_token, ic ); - - g_free( code ); + b_timeout_add(1, sasl_oauth2_remove_contact, ic); + + code = g_strdup(msg); + g_strstrip(code); + ret = oauth2_access_token(jd->oauth2_service, OAUTH2_AUTH_CODE, + code, sasl_oauth2_got_token, ic); + + g_free(code); return ret; } -int sasl_oauth2_refresh( struct im_connection *ic, const char *refresh_token ) +int sasl_oauth2_refresh(struct im_connection *ic, const char *refresh_token) { struct jabber_data *jd = ic->proto_data; - - return oauth2_access_token( jd->oauth2_service, OAUTH2_AUTH_REFRESH, - refresh_token, sasl_oauth2_got_token, ic ); + + return oauth2_access_token(jd->oauth2_service, OAUTH2_AUTH_REFRESH, + refresh_token, sasl_oauth2_got_token, ic); } -static void sasl_oauth2_got_token( gpointer data, const char *access_token, const char *refresh_token, const char *error ) +static void sasl_oauth2_got_token(gpointer data, const char *access_token, const char *refresh_token, const char *error) { struct im_connection *ic = data; struct jabber_data *jd; GSList *auth = NULL; - - if( g_slist_find( jabber_connections, ic ) == NULL ) + + if (g_slist_find(jabber_connections, ic) == NULL) { return; - + } + jd = ic->proto_data; - - if( access_token == NULL ) - { - imcb_error( ic, "OAuth failure (%s)", error ); - imc_logout( ic, TRUE ); + + if (access_token == NULL) { + imcb_error(ic, "OAuth failure (%s)", error); + imc_logout(ic, TRUE); return; } - - oauth_params_parse( &auth, ic->acc->pass ); - if( refresh_token ) - oauth_params_set( &auth, "refresh_token", refresh_token ); - if( access_token ) - oauth_params_set( &auth, "access_token", access_token ); - - g_free( ic->acc->pass ); - ic->acc->pass = oauth_params_string( auth ); - oauth_params_free( &auth ); - - g_free( jd->oauth2_access_token ); - jd->oauth2_access_token = g_strdup( access_token ); - - jabber_connect( ic ); + + oauth_params_parse(&auth, ic->acc->pass); + if (refresh_token) { + oauth_params_set(&auth, "refresh_token", refresh_token); + } + if (access_token) { + oauth_params_set(&auth, "access_token", access_token); + } + + g_free(ic->acc->pass); + ic->acc->pass = oauth_params_string(auth); + oauth_params_free(&auth); + + g_free(jd->oauth2_access_token); + jd->oauth2_access_token = g_strdup(access_token); + + jabber_connect(ic); } diff --git a/protocols/jabber/si.c b/protocols/jabber/si.c index f3060fff..cb2487bc 100644 --- a/protocols/jabber/si.c +++ b/protocols/jabber/si.c @@ -24,147 +24,156 @@ #include "jabber.h" #include "sha1.h" -void jabber_si_answer_request( file_transfer_t *ft ); -int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf ); +void jabber_si_answer_request(file_transfer_t *ft); +int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf); /* file_transfer free() callback */ -void jabber_si_free_transfer( file_transfer_t *ft) +void jabber_si_free_transfer(file_transfer_t *ft) { struct jabber_transfer *tf = ft->data; struct jabber_data *jd = tf->ic->proto_data; - if ( tf->watch_in ) - { - b_event_remove( tf->watch_in ); + if (tf->watch_in) { + b_event_remove(tf->watch_in); tf->watch_in = 0; } - jd->filetransfers = g_slist_remove( jd->filetransfers, tf ); + jd->filetransfers = g_slist_remove(jd->filetransfers, tf); - if( tf->fd != -1 ) - { - closesocket( tf->fd ); + if (tf->fd != -1) { + closesocket(tf->fd); tf->fd = -1; } - if( tf->disco_timeout ) - b_event_remove( tf->disco_timeout ); - - g_free( tf->ini_jid ); - g_free( tf->tgt_jid ); - g_free( tf->iq_id ); - g_free( tf->sid ); - g_free( tf ); + if (tf->disco_timeout) { + b_event_remove(tf->disco_timeout); + } + + g_free(tf->ini_jid); + g_free(tf->tgt_jid); + g_free(tf->iq_id); + g_free(tf->sid); + g_free(tf); } /* file_transfer canceled() callback */ -void jabber_si_canceled( file_transfer_t *ft, char *reason ) +void jabber_si_canceled(file_transfer_t *ft, char *reason) { struct jabber_transfer *tf = ft->data; struct xt_node *reply, *iqnode; - if( tf->accepted ) + if (tf->accepted) { return; - - iqnode = jabber_make_packet( "iq", "error", tf->ini_jid, NULL ); - xt_add_attr( iqnode, "id", tf->iq_id ); - reply = jabber_make_error_packet( iqnode, "forbidden", "cancel", "403" ); - xt_free_node( iqnode ); - - if( !jabber_write_packet( tf->ic, reply ) ) - imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request" ); - xt_free_node( reply ); + } + + iqnode = jabber_make_packet("iq", "error", tf->ini_jid, NULL); + xt_add_attr(iqnode, "id", tf->iq_id); + reply = jabber_make_error_packet(iqnode, "forbidden", "cancel", "403"); + xt_free_node(iqnode); + + if (!jabber_write_packet(tf->ic, reply)) { + imcb_log(tf->ic, "WARNING: Error generating reply to file transfer request"); + } + xt_free_node(reply); } -int jabber_si_check_features( struct jabber_transfer *tf, GSList *features ) { +int jabber_si_check_features(struct jabber_transfer *tf, GSList *features) +{ int foundft = FALSE, foundbt = FALSE, foundsi = FALSE; - while ( features ) - { - if( !strcmp( features->data, XMLNS_FILETRANSFER ) ) + while (features) { + if (!strcmp(features->data, XMLNS_FILETRANSFER)) { foundft = TRUE; - if( !strcmp( features->data, XMLNS_BYTESTREAMS ) ) + } + if (!strcmp(features->data, XMLNS_BYTESTREAMS)) { foundbt = TRUE; - if( !strcmp( features->data, XMLNS_SI ) ) + } + if (!strcmp(features->data, XMLNS_SI)) { foundsi = TRUE; + } features = g_slist_next(features); } - if( !foundft ) - imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature file transfers" ); - else if( !foundbt ) - imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature byte streams (required)" ); - else if( !foundsi ) - imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)" ); - + if (!foundft) { + imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature file transfers"); + } else if (!foundbt) { + imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature byte streams (required)"); + } else if (!foundsi) { + imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)"); + } + return foundft && foundbt && foundsi; } -void jabber_si_transfer_start( struct jabber_transfer *tf ) { +void jabber_si_transfer_start(struct jabber_transfer *tf) +{ - if( !jabber_si_check_features( tf, tf->bud->features ) ) + if (!jabber_si_check_features(tf, tf->bud->features)) { return; - + } + /* send the request to our buddy */ - jabber_si_send_request( tf->ic, tf->bud->full_jid, tf ); + jabber_si_send_request(tf->ic, tf->bud->full_jid, tf); /* and start the receive logic */ - imcb_file_recv_start( tf->ic, tf->ft ); + imcb_file_recv_start(tf->ic, tf->ft); } -gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond ) +gboolean jabber_si_waitfor_disco(gpointer data, gint fd, b_input_condition cond) { struct jabber_transfer *tf = data; struct jabber_data *jd = tf->ic->proto_data; tf->disco_timeout_fired++; - if( tf->bud->features && jd->have_streamhosts==1 ) { + if (tf->bud->features && jd->have_streamhosts == 1) { tf->disco_timeout = 0; - jabber_si_transfer_start( tf ); + jabber_si_transfer_start(tf); return FALSE; } /* 8 seconds should be enough for server and buddy to respond */ - if ( tf->disco_timeout_fired < 16 ) + if (tf->disco_timeout_fired < 16) { return TRUE; - - if( !tf->bud->features && jd->have_streamhosts!=1 ) - imcb_log( tf->ic, "Couldn't get buddy's features nor discover all services of the server" ); - else if( !tf->bud->features ) - imcb_log( tf->ic, "Couldn't get buddy's features" ); - else - imcb_log( tf->ic, "Couldn't discover some of the server's services" ); - + } + + if (!tf->bud->features && jd->have_streamhosts != 1) { + imcb_log(tf->ic, "Couldn't get buddy's features nor discover all services of the server"); + } else if (!tf->bud->features) { + imcb_log(tf->ic, "Couldn't get buddy's features"); + } else { + imcb_log(tf->ic, "Couldn't discover some of the server's services"); + } + tf->disco_timeout = 0; - jabber_si_transfer_start( tf ); + jabber_si_transfer_start(tf); return FALSE; } -void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ) +void jabber_si_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *who) { struct jabber_transfer *tf; struct jabber_data *jd = ic->proto_data; struct jabber_buddy *bud; char *server = jd->server, *s; - if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) ) - bud = jabber_buddy_by_ext_jid( ic, who, 0 ); - else - bud = jabber_buddy_by_jid( ic, who, 0 ); + if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { + bud = jabber_buddy_by_ext_jid(ic, who, 0); + } else { + bud = jabber_buddy_by_jid(ic, who, 0); + } - if( bud == NULL ) - { - imcb_file_canceled( ic, ft, "Couldn't find buddy (BUG?)" ); + if (bud == NULL) { + imcb_file_canceled(ic, ft, "Couldn't find buddy (BUG?)"); return; } - - imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who ); - tf = g_new0( struct jabber_transfer, 1 ); + imcb_log(ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who); + + tf = g_new0(struct jabber_transfer, 1); tf->ic = ic; tf->ft = ft; @@ -174,27 +183,30 @@ void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, tf->bud = bud; ft->write = jabber_bs_send_write; - jd->filetransfers = g_slist_prepend( jd->filetransfers, tf ); + jd->filetransfers = g_slist_prepend(jd->filetransfers, tf); /* query buddy's features and server's streaming proxies if neccessary */ - if( !tf->bud->features ) - jabber_iq_query_features( ic, bud->full_jid ); + if (!tf->bud->features) { + jabber_iq_query_features(ic, bud->full_jid); + } /* If <auto> is not set don't check for proxies */ - if( ( jd->have_streamhosts!=1 ) && ( jd->streamhosts==NULL ) && - ( strstr( set_getstr( &ic->acc->set, "proxy" ), "<auto>" ) != NULL ) ) { + if ((jd->have_streamhosts != 1) && (jd->streamhosts == NULL) && + (strstr(set_getstr(&ic->acc->set, "proxy"), "<auto>") != NULL)) { jd->have_streamhosts = 0; - jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS ); - } else if ( jd->streamhosts!=NULL ) + jabber_iq_query_server(ic, server, XMLNS_DISCO_ITEMS); + } else if (jd->streamhosts != NULL) { jd->have_streamhosts = 1; + } - /* if we had to do a query, wait for the result. + /* if we had to do a query, wait for the result. * Otherwise fire away. */ - if( !tf->bud->features || jd->have_streamhosts!=1 ) - tf->disco_timeout = b_timeout_add( 500, jabber_si_waitfor_disco, tf ); - else - jabber_si_transfer_start( tf ); + if (!tf->bud->features || jd->have_streamhosts != 1) { + tf->disco_timeout = b_timeout_add(500, jabber_si_waitfor_disco, tf); + } else { + jabber_si_transfer_start(tf); + } } /* @@ -204,7 +216,7 @@ void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, * We choose a stream type from the options given by the initiator. * Then we wait for imcb to call the accept or cancel callbacks. */ -int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, struct xt_node *sinode) +int jabber_si_handle_request(struct im_connection *ic, struct xt_node *node, struct xt_node *sinode) { struct xt_node *c, *d, *reply; char *sid, *ini_jid, *tgt_jid, *iq_id, *s, *ext_jid, *size_s; @@ -215,107 +227,100 @@ int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, st struct jabber_transfer *tf; struct jabber_data *jd = ic->proto_data; file_transfer_t *ft; - + /* All this means we expect something like this: ( I think ) * <iq from=... to=... id=...> - * <si id=id xmlns=si profile=ft> - * <file xmlns=ft/> - * <feature xmlns=feature> - * <x xmlns=xdata type=submit> - * <field var=stream-method> + * <si id=id xmlns=si profile=ft> + * <file xmlns=ft/> + * <feature xmlns=feature> + * <x xmlns=xdata type=submit> + * <field var=stream-method> * */ - if( !( ini_jid = xt_find_attr( node, "from" ) ) || - !( tgt_jid = xt_find_attr( node, "to" ) ) || - !( iq_id = xt_find_attr( node, "id" ) ) || - !( sid = xt_find_attr( sinode, "id" ) ) || - !( cmp = xt_find_attr( sinode, "profile" ) ) || - !( 0 == strcmp( cmp, XMLNS_FILETRANSFER ) ) || - !( d = xt_find_node( sinode->children, "file" ) ) || - !( cmp = xt_find_attr( d, "xmlns" ) ) || - !( 0 == strcmp( cmp, XMLNS_FILETRANSFER ) ) || - !( name = xt_find_attr( d, "name" ) ) || - !( size_s = xt_find_attr( d, "size" ) ) || - !( 1 == sscanf( size_s, "%zd", &size ) ) || - !( d = xt_find_node( sinode->children, "feature" ) ) || - !( cmp = xt_find_attr( d, "xmlns" ) ) || - !( 0 == strcmp( cmp, XMLNS_FEATURE ) ) || - !( d = xt_find_node( d->children, "x" ) ) || - !( cmp = xt_find_attr( d, "xmlns" ) ) || - !( 0 == strcmp( cmp, XMLNS_XDATA ) ) || - !( cmp = xt_find_attr( d, "type" ) ) || - !( 0 == strcmp( cmp, "form" ) ) || - !( d = xt_find_node( d->children, "field" ) ) || - !( cmp = xt_find_attr( d, "var" ) ) || - !( 0 == strcmp( cmp, "stream-method" ) ) ) - { - imcb_log( ic, "WARNING: Received incomplete Stream Initiation request" ); - } - else - { + if (!(ini_jid = xt_find_attr(node, "from")) || + !(tgt_jid = xt_find_attr(node, "to")) || + !(iq_id = xt_find_attr(node, "id")) || + !(sid = xt_find_attr(sinode, "id")) || + !(cmp = xt_find_attr(sinode, "profile")) || + !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || + !(d = xt_find_node(sinode->children, "file")) || + !(cmp = xt_find_attr(d, "xmlns")) || + !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || + !(name = xt_find_attr(d, "name")) || + !(size_s = xt_find_attr(d, "size")) || + !(1 == sscanf(size_s, "%zd", &size)) || + !(d = xt_find_node(sinode->children, "feature")) || + !(cmp = xt_find_attr(d, "xmlns")) || + !(0 == strcmp(cmp, XMLNS_FEATURE)) || + !(d = xt_find_node(d->children, "x")) || + !(cmp = xt_find_attr(d, "xmlns")) || + !(0 == strcmp(cmp, XMLNS_XDATA)) || + !(cmp = xt_find_attr(d, "type")) || + !(0 == strcmp(cmp, "form")) || + !(d = xt_find_node(d->children, "field")) || + !(cmp = xt_find_attr(d, "var")) || + !(0 == strcmp(cmp, "stream-method"))) { + imcb_log(ic, "WARNING: Received incomplete Stream Initiation request"); + } else { /* Check if we support one of the options */ c = d->children; - while( ( c = xt_find_node( c, "option" ) ) ) - if( ( d = xt_find_node( c->children, "value" ) ) && - ( d->text != NULL ) && - ( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) - { + while ((c = xt_find_node(c, "option"))) { + if ((d = xt_find_node(c->children, "value")) && + (d->text != NULL) && + (strcmp(d->text, XMLNS_BYTESTREAMS) == 0)) { requestok = TRUE; break; - } - else - { + } else { c = c->next; } + } - if ( !requestok ) - imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid); + if (!requestok) { + imcb_log(ic, "WARNING: Unsupported file transfer request from %s", ini_jid); + } } - - if( requestok ) - { + + if (requestok) { /* Figure out who the transfer should come frome... */ ext_jid = ini_jid; - if( ( s = strchr( ini_jid, '/' ) ) ) - { - if( ( bud = jabber_buddy_by_jid( ic, ini_jid, GET_BUDDY_EXACT ) ) ) - { - bud->last_msg = time( NULL ); + if ((s = strchr(ini_jid, '/'))) { + if ((bud = jabber_buddy_by_jid(ic, ini_jid, GET_BUDDY_EXACT))) { + bud->last_msg = time(NULL); ext_jid = bud->ext_jid ? : bud->bare_jid; - } - else + } else { *s = 0; /* We need to generate a bare JID now. */ + } } - if( !( ft = imcb_file_send_start( ic, ext_jid, name, size ) ) ) - { - imcb_log( ic, "WARNING: Error handling transfer request from %s", ini_jid); + if (!(ft = imcb_file_send_start(ic, ext_jid, name, size))) { + imcb_log(ic, "WARNING: Error handling transfer request from %s", ini_jid); requestok = FALSE; } - if( s ) + if (s) { *s = '/'; + } } - - if( !requestok ) - { - reply = jabber_make_error_packet( node, "item-not-found", "cancel", NULL ); - if (!jabber_write_packet( ic, reply )) - imcb_log( ic, "WARNING: Error generating reply to file transfer request" ); - xt_free_node( reply ); + + if (!requestok) { + reply = jabber_make_error_packet(node, "item-not-found", "cancel", NULL); + if (!jabber_write_packet(ic, reply)) { + imcb_log(ic, "WARNING: Error generating reply to file transfer request"); + } + xt_free_node(reply); return XT_HANDLED; } /* Request is fine. */ - tf = g_new0( struct jabber_transfer, 1 ); + tf = g_new0(struct jabber_transfer, 1); - tf->ini_jid = g_strdup( ini_jid ); - tf->tgt_jid = g_strdup( tgt_jid ); - tf->iq_id = g_strdup( iq_id ); - tf->sid = g_strdup( sid ); + tf->ini_jid = g_strdup(ini_jid); + tf->tgt_jid = g_strdup(tgt_jid); + tf->iq_id = g_strdup(iq_id); + tf->sid = g_strdup(sid); tf->ic = ic; tf->ft = ft; tf->fd = -1; @@ -324,7 +329,7 @@ int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, st tf->ft->free = jabber_si_free_transfer; tf->ft->canceled = jabber_si_canceled; - jd->filetransfers = g_slist_prepend( jd->filetransfers, tf ); + jd->filetransfers = g_slist_prepend(jd->filetransfers, tf); return XT_HANDLED; } @@ -335,204 +340,203 @@ int jabber_si_handle_request( struct im_connection *ic, struct xt_node *node, st * In the next step, the initiator will send us a request for the given stream type. * (currently that can only be a SOCKS5 bytestream) */ -void jabber_si_answer_request( file_transfer_t *ft ) { +void jabber_si_answer_request(file_transfer_t *ft) +{ struct jabber_transfer *tf = ft->data; struct xt_node *node, *sinode, *reply; /* generate response, start with the SI tag */ - sinode = xt_new_node( "si", NULL, NULL ); - xt_add_attr( sinode, "xmlns", XMLNS_SI ); - xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER ); - xt_add_attr( sinode, "id", tf->sid ); + sinode = xt_new_node("si", NULL, NULL); + xt_add_attr(sinode, "xmlns", XMLNS_SI); + xt_add_attr(sinode, "profile", XMLNS_FILETRANSFER); + xt_add_attr(sinode, "id", tf->sid); /* now the file tag */ - node = xt_new_node( "file", NULL, NULL ); - xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER ); + node = xt_new_node("file", NULL, NULL); + xt_add_attr(node, "xmlns", XMLNS_FILETRANSFER); - xt_add_child( sinode, node ); + xt_add_child(sinode, node); /* and finally the feature tag */ - node = xt_new_node( "field", NULL, NULL ); - xt_add_attr( node, "var", "stream-method" ); - xt_add_attr( node, "type", "list-single" ); + node = xt_new_node("field", NULL, NULL); + xt_add_attr(node, "var", "stream-method"); + xt_add_attr(node, "type", "list-single"); /* Currently all we can do. One could also implement in-band (IBB) */ - xt_add_child( node, xt_new_node( "value", XMLNS_BYTESTREAMS, NULL ) ); + xt_add_child(node, xt_new_node("value", XMLNS_BYTESTREAMS, NULL)); - node = xt_new_node( "x", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_XDATA ); - xt_add_attr( node, "type", "submit" ); + node = xt_new_node("x", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_XDATA); + xt_add_attr(node, "type", "submit"); - node = xt_new_node( "feature", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_FEATURE ); + node = xt_new_node("feature", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_FEATURE); - xt_add_child( sinode, node ); + xt_add_child(sinode, node); - reply = jabber_make_packet( "iq", "result", tf->ini_jid, sinode ); - xt_add_attr( reply, "id", tf->iq_id ); - - if( !jabber_write_packet( tf->ic, reply ) ) - imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request" ); - else + reply = jabber_make_packet("iq", "result", tf->ini_jid, sinode); + xt_add_attr(reply, "id", tf->iq_id); + + if (!jabber_write_packet(tf->ic, reply)) { + imcb_log(tf->ic, "WARNING: Error generating reply to file transfer request"); + } else { tf->accepted = TRUE; - xt_free_node( reply ); + } + xt_free_node(reply); } -static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) +static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) { struct xt_node *c, *d; char *ini_jid = NULL, *tgt_jid, *iq_id, *cmp; GSList *tflist; - struct jabber_transfer *tf=NULL; + struct jabber_transfer *tf = NULL; struct jabber_data *jd = ic->proto_data; - if( !( tgt_jid = xt_find_attr( node, "from" ) ) || - !( ini_jid = xt_find_attr( node, "to" ) ) ) - { - imcb_log( ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid ); + if (!(tgt_jid = xt_find_attr(node, "from")) || + !(ini_jid = xt_find_attr(node, "to"))) { + imcb_log(ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid); return XT_HANDLED; } - + /* All this means we expect something like this: ( I think ) * <iq from=... to=... id=...> - * <si xmlns=si> - * [ <file xmlns=ft/> ] <-- not neccessary - * <feature xmlns=feature> - * <x xmlns=xdata type=submit> - * <field var=stream-method> - * <value> + * <si xmlns=si> + * [ <file xmlns=ft/> ] <-- not neccessary + * <feature xmlns=feature> + * <x xmlns=xdata type=submit> + * <field var=stream-method> + * <value> */ - if( !( tgt_jid = xt_find_attr( node, "from" ) ) || - !( ini_jid = xt_find_attr( node, "to" ) ) || - !( iq_id = xt_find_attr( node, "id" ) ) || - !( c = xt_find_node( node->children, "si" ) ) || - !( cmp = xt_find_attr( c, "xmlns" ) ) || - !( strcmp( cmp, XMLNS_SI ) == 0 ) || - !( d = xt_find_node( c->children, "feature" ) ) || - !( cmp = xt_find_attr( d, "xmlns" ) ) || - !( strcmp( cmp, XMLNS_FEATURE ) == 0 ) || - !( d = xt_find_node( d->children, "x" ) ) || - !( cmp = xt_find_attr( d, "xmlns" ) ) || - !( strcmp( cmp, XMLNS_XDATA ) == 0 ) || - !( cmp = xt_find_attr( d, "type" ) ) || - !( strcmp( cmp, "submit" ) == 0 ) || - !( d = xt_find_node( d->children, "field" ) ) || - !( cmp = xt_find_attr( d, "var" ) ) || - !( strcmp( cmp, "stream-method" ) == 0 ) || - !( d = xt_find_node( d->children, "value" ) ) ) - { - imcb_log( ic, "WARNING: Received incomplete Stream Initiation response" ); + if (!(tgt_jid = xt_find_attr(node, "from")) || + !(ini_jid = xt_find_attr(node, "to")) || + !(iq_id = xt_find_attr(node, "id")) || + !(c = xt_find_node(node->children, "si")) || + !(cmp = xt_find_attr(c, "xmlns")) || + !(strcmp(cmp, XMLNS_SI) == 0) || + !(d = xt_find_node(c->children, "feature")) || + !(cmp = xt_find_attr(d, "xmlns")) || + !(strcmp(cmp, XMLNS_FEATURE) == 0) || + !(d = xt_find_node(d->children, "x")) || + !(cmp = xt_find_attr(d, "xmlns")) || + !(strcmp(cmp, XMLNS_XDATA) == 0) || + !(cmp = xt_find_attr(d, "type")) || + !(strcmp(cmp, "submit") == 0) || + !(d = xt_find_node(d->children, "field")) || + !(cmp = xt_find_attr(d, "var")) || + !(strcmp(cmp, "stream-method") == 0) || + !(d = xt_find_node(d->children, "value"))) { + imcb_log(ic, "WARNING: Received incomplete Stream Initiation response"); return XT_HANDLED; } - if( !( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) { + if (!(strcmp(d->text, XMLNS_BYTESTREAMS) == 0)) { /* since we should only have advertised what we can do and the peer should * only have chosen what we offered, this should never happen */ - imcb_log( ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text ); - + imcb_log(ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text); + return XT_HANDLED; } - + /* Let's see if we can find out what this bytestream should be for... */ - for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) ) - { + for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) { struct jabber_transfer *tft = tflist->data; - if( ( strcmp( tft->iq_id, iq_id ) == 0 ) ) - { - tf = tft; + if ((strcmp(tft->iq_id, iq_id) == 0)) { + tf = tft; break; } } - if (!tf) - { - imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid ); + if (!tf) { + imcb_log(ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid); return XT_HANDLED; } - tf->ini_jid = g_strdup( ini_jid ); - tf->tgt_jid = g_strdup( tgt_jid ); + tf->ini_jid = g_strdup(ini_jid); + tf->tgt_jid = g_strdup(tgt_jid); - imcb_log( ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid ); + imcb_log(ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid); - jabber_bs_send_start( tf ); + jabber_bs_send_start(tf); return XT_HANDLED; } -int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf ) +int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf) { struct xt_node *node, *sinode; struct jabber_buddy *bud; /* who knows how many bits the future holds :) */ - char filesizestr[ 1 + ( int ) ( 0.301029995663981198f * sizeof( size_t ) * 8 ) ]; + char filesizestr[ 1 + ( int ) (0.301029995663981198f * sizeof(size_t) * 8) ]; - const char *methods[] = - { + const char *methods[] = + { XMLNS_BYTESTREAMS, //XMLNS_IBB, - NULL + NULL }; const char **m; char *s; /* Maybe we should hash this? */ - tf->sid = g_strdup_printf( "BitlBeeJabberSID%d", tf->ft->local_id ); - - if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) ) - bud = jabber_buddy_by_ext_jid( ic, who, 0 ); - else - bud = jabber_buddy_by_jid( ic, who, 0 ); + tf->sid = g_strdup_printf("BitlBeeJabberSID%d", tf->ft->local_id); + + if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { + bud = jabber_buddy_by_ext_jid(ic, who, 0); + } else { + bud = jabber_buddy_by_jid(ic, who, 0); + } /* start with the SI tag */ - sinode = xt_new_node( "si", NULL, NULL ); - xt_add_attr( sinode, "xmlns", XMLNS_SI ); - xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER ); - xt_add_attr( sinode, "id", tf->sid ); + sinode = xt_new_node("si", NULL, NULL); + xt_add_attr(sinode, "xmlns", XMLNS_SI); + xt_add_attr(sinode, "profile", XMLNS_FILETRANSFER); + xt_add_attr(sinode, "id", tf->sid); -/* if( mimetype ) - xt_add_attr( node, "mime-type", mimetype ); */ +/* if( mimetype ) + xt_add_attr( node, "mime-type", mimetype ); */ /* now the file tag */ /* if( desc ) - node = xt_new_node( "desc", descr, NULL ); */ - node = xt_new_node( "range", NULL, NULL ); - - sprintf( filesizestr, "%zd", tf->ft->file_size ); - node = xt_new_node( "file", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER ); - xt_add_attr( node, "name", tf->ft->file_name ); - xt_add_attr( node, "size", filesizestr ); + node = xt_new_node( "desc", descr, NULL ); */ + node = xt_new_node("range", NULL, NULL); + + sprintf(filesizestr, "%zd", tf->ft->file_size); + node = xt_new_node("file", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_FILETRANSFER); + xt_add_attr(node, "name", tf->ft->file_name); + xt_add_attr(node, "size", filesizestr); /* if (hash) - xt_add_attr( node, "hash", hash ); - if (date) - xt_add_attr( node, "date", date ); */ + xt_add_attr( node, "hash", hash ); + if (date) + xt_add_attr( node, "date", date ); */ - xt_add_child( sinode, node ); + xt_add_child(sinode, node); /* and finally the feature tag */ - node = xt_new_node( "field", NULL, NULL ); - xt_add_attr( node, "var", "stream-method" ); - xt_add_attr( node, "type", "list-single" ); + node = xt_new_node("field", NULL, NULL); + xt_add_attr(node, "var", "stream-method"); + xt_add_attr(node, "type", "list-single"); - for ( m = methods ; *m ; m ++ ) - xt_add_child( node, xt_new_node( "option", NULL, xt_new_node( "value", (char *)*m, NULL ) ) ); + for (m = methods; *m; m++) { + xt_add_child(node, xt_new_node("option", NULL, xt_new_node("value", (char *) *m, NULL))); + } - node = xt_new_node( "x", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_XDATA ); - xt_add_attr( node, "type", "form" ); + node = xt_new_node("x", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_XDATA); + xt_add_attr(node, "type", "form"); - node = xt_new_node( "feature", NULL, node ); - xt_add_attr( node, "xmlns", XMLNS_FEATURE ); + node = xt_new_node("feature", NULL, node); + xt_add_attr(node, "xmlns", XMLNS_FEATURE); - xt_add_child( sinode, node ); + xt_add_child(sinode, node); /* and we are there... */ - node = jabber_make_packet( "iq", "set", bud ? bud->full_jid : who, sinode ); - jabber_cache_add( ic, node, jabber_si_handle_response ); - tf->iq_id = g_strdup( xt_find_attr( node, "id" ) ); - - return jabber_write_packet( ic, node ); + node = jabber_make_packet("iq", "set", bud ? bud->full_jid : who, sinode); + jabber_cache_add(ic, node, jabber_si_handle_response); + tf->iq_id = g_strdup(xt_find_attr(node, "id")); + + return jabber_write_packet(ic, node); } diff --git a/protocols/msn/invitation.c b/protocols/msn/invitation.c index 7bfec4aa..c386bdb9 100644 --- a/protocols/msn/invitation.c +++ b/protocols/msn/invitation.c @@ -12,12 +12,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License with the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; if not, write to the Free Software Foundation, Inc., 51 Franklin St., @@ -32,131 +32,134 @@ #ifdef debug #undef debug #endif -#define debug(msg...) log_message( LOGLVL_INFO, msg ) +#define debug(msg ...) log_message(LOGLVL_INFO, msg) -static void msn_ftp_free( file_transfer_t *file ); -static void msn_ftpr_accept( file_transfer_t *file ); -static void msn_ftp_finished( file_transfer_t *file ); -static void msn_ftp_canceled( file_transfer_t *file, char *reason ); -static gboolean msn_ftpr_write_request( file_transfer_t *file ); +static void msn_ftp_free(file_transfer_t *file); +static void msn_ftpr_accept(file_transfer_t *file); +static void msn_ftp_finished(file_transfer_t *file); +static void msn_ftp_canceled(file_transfer_t *file, char *reason); +static gboolean msn_ftpr_write_request(file_transfer_t *file); -static gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond ); -static gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond ); -gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ); +static gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond); +static gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond); +gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len); /* * Vararg wrapper for imcb_file_canceled(). */ -gboolean msn_ftp_abort( file_transfer_t *file, char *format, ... ) +gboolean msn_ftp_abort(file_transfer_t *file, char *format, ...) { - va_list params; - va_start( params, format ); - char error[128]; - - if( vsnprintf( error, 128, format, params ) < 0 ) - sprintf( error, "internal error parsing error string (BUG)" ); - va_end( params ); - imcb_file_canceled( file, error ); + va_list params; + + va_start(params, format); + char error[128]; + + if (vsnprintf(error, 128, format, params) < 0) { + sprintf(error, "internal error parsing error string (BUG)"); + } + va_end(params); + imcb_file_canceled(file, error); return FALSE; } /* very useful */ #define ASSERTSOCKOP(op, msg) \ - if( (op) == -1 ) \ - return msn_ftp_abort( file , msg ": %s", strerror( errno ) ); + if ((op) == -1) { \ + return msn_ftp_abort(file, msg ": %s", strerror(errno)); } -void msn_ftp_invitation_cmd( struct im_connection *ic, char *who, int cookie, char *icmd, - char *trailer ) +void msn_ftp_invitation_cmd(struct im_connection *ic, char *who, int cookie, char *icmd, + char *trailer) { - struct msn_message *m = g_new0( struct msn_message, 1 ); - - m->text = g_strdup_printf( "%s" - "Invitation-Command: %s\r\n" - "Invitation-Cookie: %u\r\n" - "%s", - MSN_INVITE_HEADERS, - icmd, - cookie, - trailer); - - m->who = g_strdup( who ); - - msn_sb_write_msg( ic, m ); + struct msn_message *m = g_new0(struct msn_message, 1); + + m->text = g_strdup_printf("%s" + "Invitation-Command: %s\r\n" + "Invitation-Cookie: %u\r\n" + "%s", + MSN_INVITE_HEADERS, + icmd, + cookie, + trailer); + + m->who = g_strdup(who); + + msn_sb_write_msg(ic, m); } -void msn_ftp_cancel_invite( struct im_connection *ic, char *who, int cookie, char *code ) +void msn_ftp_cancel_invite(struct im_connection *ic, char *who, int cookie, char *code) { char buf[64]; - g_snprintf( buf, sizeof( buf ), "Cancel-Code: %s\r\n", code ); - msn_ftp_invitation_cmd( ic, who, cookie, "CANCEL", buf ); + g_snprintf(buf, sizeof(buf), "Cancel-Code: %s\r\n", code); + msn_ftp_invitation_cmd(ic, who, cookie, "CANCEL", buf); } -void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *file, char *who ) +void msn_ftp_transfer_request(struct im_connection *ic, file_transfer_t *file, char *who) { - unsigned int cookie = time( NULL ); /* TODO: randomize */ + unsigned int cookie = time(NULL); /* TODO: randomize */ char buf[2048]; - msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1 ); + msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1); + file->data = msn_file; file->free = msn_ftp_free; file->canceled = msn_ftp_canceled; file->write = msn_ftps_write; msn_file->md = ic->proto_data; msn_file->invite_cookie = cookie; - msn_file->handle = g_strdup( who ); + msn_file->handle = g_strdup(who); msn_file->dcc = file; - msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc ); + msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc); msn_file->fd = -1; msn_file->sbufpos = 3; - g_snprintf( buf, sizeof( buf ), - "Application-Name: File Transfer\r\n" - "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n" - "Application-File: %s\r\n" - "Application-FileSize: %zd\r\n", - file->file_name, - file->file_size); + g_snprintf(buf, sizeof(buf), + "Application-Name: File Transfer\r\n" + "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n" + "Application-File: %s\r\n" + "Application-FileSize: %zd\r\n", + file->file_name, + file->file_size); - msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf ); + msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf); - imcb_file_recv_start( file ); + imcb_file_recv_start(file); } -void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) +void msn_invitation_invite(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) { - char *itype = msn_findheader( body, "Application-GUID:", blen ); + char *itype = msn_findheader(body, "Application-GUID:", blen); char *name, *size, *invitecookie, *reject = NULL; user_t *u; size_t isize; file_transfer_t *file; - - if( !itype || strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) != 0 ) { + + if (!itype || strcmp(itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}") != 0) { /* Don't know what that is - don't care */ - char *iname = msn_findheader( body, "Application-Name:", blen ); - imcb_log( sb->ic, "Received unknown MSN invitation %s (%s) from %s", - itype ? : "with no GUID", iname ? iname : "no application name", handle ); - g_free( iname ); + char *iname = msn_findheader(body, "Application-Name:", blen); + imcb_log(sb->ic, "Received unknown MSN invitation %s (%s) from %s", + itype ? : "with no GUID", iname ? iname : "no application name", handle); + g_free(iname); reject = "REJECT_NOT_INSTALLED"; - } else if ( - !( name = msn_findheader( body, "Application-File:", blen )) || - !( size = msn_findheader( body, "Application-FileSize:", blen )) || - !( invitecookie = msn_findheader( body, "Invitation-Cookie:", blen)) || - !( isize = atoll( size ) ) ) { - imcb_log( sb->ic, "Received corrupted transfer request from %s" - "(name=%s, size=%s, invitecookie=%s)", - handle, name, size, invitecookie ); + } else if ( + !(name = msn_findheader(body, "Application-File:", blen)) || + !(size = msn_findheader(body, "Application-FileSize:", blen)) || + !(invitecookie = msn_findheader(body, "Invitation-Cookie:", blen)) || + !(isize = atoll(size))) { + imcb_log(sb->ic, "Received corrupted transfer request from %s" + "(name=%s, size=%s, invitecookie=%s)", + handle, name, size, invitecookie); reject = "REJECT"; - } else if ( !( u = user_findhandle( sb->ic, handle ) ) ) { - imcb_log( sb->ic, "Error in parsing transfer request, User '%s'" - "is not in contact list", handle ); + } else if (!(u = user_findhandle(sb->ic, handle))) { + imcb_log(sb->ic, "Error in parsing transfer request, User '%s'" + "is not in contact list", handle); reject = "REJECT"; - } else if ( !( file = imcb_file_send_start( sb->ic, handle, name, isize ) ) ) { - imcb_log( sb->ic, "Error initiating transfer for request from %s for %s", - handle, name ); + } else if (!(file = imcb_file_send_start(sb->ic, handle, name, isize))) { + imcb_log(sb->ic, "Error initiating transfer for request from %s for %s", + handle, name); reject = "REJECT"; } else { - msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1 ); + msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1); file->data = msn_file; file->accept = msn_ftpr_accept; file->free = msn_ftp_free; @@ -165,230 +168,251 @@ void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned i file->write_request = msn_ftpr_write_request; msn_file->md = sb->ic->proto_data; msn_file->invite_cookie = cookie; - msn_file->handle = g_strdup( handle ); + msn_file->handle = g_strdup(handle); msn_file->dcc = file; - msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc ); + msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc); msn_file->fd = -1; } - if( reject ) - msn_ftp_cancel_invite( sb->ic, sb->who, cookie, reject ); + if (reject) { + msn_ftp_cancel_invite(sb->ic, sb->who, cookie, reject); + } - g_free( name ); - g_free( size ); - g_free( invitecookie ); - g_free( itype ); + g_free(name); + g_free(size); + g_free(invitecookie); + g_free(itype); } -msn_filetransfer_t* msn_find_filetransfer( struct msn_data *md, unsigned int cookie, char *handle ) +msn_filetransfer_t* msn_find_filetransfer(struct msn_data *md, unsigned int cookie, char *handle) { GSList *l; - - for( l = md->filetransfers; l; l = l->next ) { - msn_filetransfer_t *file = ( (file_transfer_t*) l->data )->data; - if( file->invite_cookie == cookie && strcmp( handle, file->handle ) == 0 ) { + + for (l = md->filetransfers; l; l = l->next) { + msn_filetransfer_t *file = ((file_transfer_t *) l->data)->data; + if (file->invite_cookie == cookie && strcmp(handle, file->handle) == 0) { return file; } } return NULL; } -gboolean msn_ftps_connected( gpointer data, gint fd, b_input_condition cond ) +gboolean msn_ftps_connected(gpointer data, gint fd, b_input_condition cond) { file_transfer_t *file = data; msn_filetransfer_t *msn_file = file->data; struct sockaddr_storage clt_addr; - socklen_t ssize = sizeof( clt_addr ); - - debug( "Connected to MSNFTP client" ); - - ASSERTSOCKOP( msn_file->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection" ); + socklen_t ssize = sizeof(clt_addr); - closesocket( fd ); + debug("Connected to MSNFTP client"); + + ASSERTSOCKOP(msn_file->fd = accept(fd, (struct sockaddr *) &clt_addr, &ssize), "Accepting connection"); + + closesocket(fd); fd = msn_file->fd; - sock_make_nonblocking( fd ); + sock_make_nonblocking(fd); - msn_file->r_event_id = b_input_add( fd, B_EV_IO_READ, msn_ftp_read, file ); + msn_file->r_event_id = b_input_add(fd, B_EV_IO_READ, msn_ftp_read, file); return FALSE; } -void msn_invitations_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) +void msn_invitations_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, + char *body, int blen) { file_transfer_t *file = msn_file->dcc; char buf[1024]; - unsigned int acookie = time ( NULL ); - char host[HOST_NAME_MAX+1]; + unsigned int acookie = time(NULL); + char host[HOST_NAME_MAX + 1]; char port[6]; char *errmsg; msn_file->auth_cookie = acookie; - if( ( msn_file->fd = ft_listen( NULL, host, port, FALSE, &errmsg ) ) == -1 ) { - msn_ftp_abort( file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", errmsg ); + if ((msn_file->fd = ft_listen(NULL, host, port, FALSE, &errmsg)) == -1) { + msn_ftp_abort(file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", + errmsg); return; } - msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file ); + msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file); - g_snprintf( buf, sizeof( buf ), - "IP-Address: %s\r\n" - "Port: %s\r\n" - "AuthCookie: %d\r\n" - "Launch-Application: FALSE\r\n" - "Request-Data: IP-Address:\r\n\r\n", - host, - port, - msn_file->auth_cookie ); + g_snprintf(buf, sizeof(buf), + "IP-Address: %s\r\n" + "Port: %s\r\n" + "AuthCookie: %d\r\n" + "Launch-Application: FALSE\r\n" + "Request-Data: IP-Address:\r\n\r\n", + host, + port, + msn_file->auth_cookie); - msn_ftp_invitation_cmd( msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf ); + msn_ftp_invitation_cmd(msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf); } -void msn_invitationr_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) { +void msn_invitationr_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, + char *body, int blen) +{ file_transfer_t *file = msn_file->dcc; char *authcookie, *ip, *port; - if( !( authcookie = msn_findheader( body, "AuthCookie:", blen ) ) || - !( ip = msn_findheader( body, "IP-Address:", blen ) ) || - !( port = msn_findheader( body, "Port:", blen ) ) ) { - msn_ftp_abort( file, "Received invalid accept reply" ); - } else if( - ( msn_file->fd = proxy_connect( ip, atoi( port ), msn_ftp_connected, file ) ) - < 0 ) { - msn_ftp_abort( file, "Error connecting to MSN client" ); - } else - msn_file->auth_cookie = strtoul( authcookie, NULL, 10 ); - - g_free( authcookie ); - g_free( ip ); - g_free( port ); + if (!(authcookie = msn_findheader(body, "AuthCookie:", blen)) || + !(ip = msn_findheader(body, "IP-Address:", blen)) || + !(port = msn_findheader(body, "Port:", blen))) { + msn_ftp_abort(file, "Received invalid accept reply"); + } else if ( + (msn_file->fd = proxy_connect(ip, atoi(port), msn_ftp_connected, file)) + < 0) { + msn_ftp_abort(file, "Error connecting to MSN client"); + } else { + msn_file->auth_cookie = strtoul(authcookie, NULL, 10); + } + + g_free(authcookie); + g_free(ip); + g_free(port); } -void msn_invitation_accept( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) +void msn_invitation_accept(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) { - msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle ); + msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle); file_transfer_t *file = msn_file ? msn_file->dcc : NULL; - - if( !msn_file ) - imcb_log( sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)" ); - else if( file->sending ) - msn_invitations_accept( msn_file, sb, handle, cookie, body, blen ); - else - msn_invitationr_accept( msn_file, sb, handle, cookie, body, blen ); + + if (!msn_file) { + imcb_log(sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)"); + } else if (file->sending) { + msn_invitations_accept(msn_file, sb, handle, cookie, body, blen); + } else { + msn_invitationr_accept(msn_file, sb, handle, cookie, body, blen); + } } -void msn_invitation_cancel( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) +void msn_invitation_cancel(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) { - msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle ); - - if( !msn_file ) - imcb_log( sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)" ); - else - msn_ftp_abort( msn_file->dcc, msn_findheader( body, "Cancel-Code:", blen ) ); + msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle); + + if (!msn_file) { + imcb_log(sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)"); + } else { + msn_ftp_abort(msn_file->dcc, msn_findheader(body, "Cancel-Code:", blen)); + } } -int msn_ftp_write( file_transfer_t *file, char *format, ... ) +int msn_ftp_write(file_transfer_t *file, char *format, ...) { msn_filetransfer_t *msn_file = file->data; va_list params; int st; char *s; - - va_start( params, format ); - s = g_strdup_vprintf( format, params ); - va_end( params ); - - st = write( msn_file->fd, s, strlen( s ) ); - if( st != strlen( s ) ) - return msn_ftp_abort( file, "Error sending data over MSNFTP connection: %s", - strerror( errno ) ); - - g_free( s ); + + va_start(params, format); + s = g_strdup_vprintf(format, params); + va_end(params); + + st = write(msn_file->fd, s, strlen(s)); + if (st != strlen(s)) { + return msn_ftp_abort(file, "Error sending data over MSNFTP connection: %s", + strerror(errno)); + } + + g_free(s); return 1; } -gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond ) +gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond) { file_transfer_t *file = data; msn_filetransfer_t *msn_file = file->data; - - debug( "Connected to MSNFTP server, starting authentication" ); - if( !msn_ftp_write( file, "VER MSNFTP\r\n" ) ) + + debug("Connected to MSNFTP server, starting authentication"); + if (!msn_ftp_write(file, "VER MSNFTP\r\n")) { return FALSE; - - sock_make_nonblocking( msn_file->fd ); - msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); - + } + + sock_make_nonblocking(msn_file->fd); + msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file); + return FALSE; } -gboolean msn_ftp_handle_command( file_transfer_t *file, char* line ) +gboolean msn_ftp_handle_command(file_transfer_t *file, char* line) { msn_filetransfer_t *msn_file = file->data; - char **cmd = msn_linesplit( line ); + char **cmd = msn_linesplit(line); int count = 0; - if( cmd[0] ) while( cmd[++count] ); - - if( count < 1 ) - return msn_ftp_abort( file, "Missing command in MSNFTP communication" ); - - if( strcmp( cmd[0], "VER" ) == 0 ) { - if( strcmp( cmd[1], "MSNFTP" ) != 0 ) - return msn_ftp_abort( file, "Unsupported filetransfer protocol: %s", cmd[1] ); - if( file->sending ) - msn_ftp_write( file, "VER MSNFTP\r\n" ); - else - msn_ftp_write( file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie ); - } else if( strcmp( cmd[0], "FIL" ) == 0 ) { - if( strtoul( cmd[1], NULL, 10 ) != file->file_size ) - return msn_ftp_abort( file, "FIL reply contains a different file size than the size in the invitation" ); - msn_ftp_write( file, "TFR\r\n" ); + + if (cmd[0]) { + while (cmd[++count]) { + ; + } + } + + if (count < 1) { + return msn_ftp_abort(file, "Missing command in MSNFTP communication"); + } + + if (strcmp(cmd[0], "VER") == 0) { + if (strcmp(cmd[1], "MSNFTP") != 0) { + return msn_ftp_abort(file, "Unsupported filetransfer protocol: %s", cmd[1]); + } + if (file->sending) { + msn_ftp_write(file, "VER MSNFTP\r\n"); + } else { + msn_ftp_write(file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie); + } + } else if (strcmp(cmd[0], "FIL") == 0) { + if (strtoul(cmd[1], NULL, 10) != file->file_size) { + return msn_ftp_abort(file, + "FIL reply contains a different file size than the size in the invitation"); + } + msn_ftp_write(file, "TFR\r\n"); msn_file->status |= MSN_TRANSFER_RECEIVING; - } else if( strcmp( cmd[0], "USR" ) == 0 ) { - if( ( strcmp( cmd[1], msn_file->handle ) != 0 ) || - ( strtoul( cmd[2], NULL, 10 ) != msn_file->auth_cookie ) ) - msn_ftp_abort( file, "Authentication failed. " - "Expected handle: %s (got %s), cookie: %u (got %s)", - msn_file->handle, cmd[1], - msn_file->auth_cookie, cmd[2] ); - msn_ftp_write( file, "FIL %zu\r\n", file->file_size); - } else if( strcmp( cmd[0], "TFR" ) == 0 ) { - file->write_request( file ); - } else if( strcmp( cmd[0], "BYE" ) == 0 ) { + } else if (strcmp(cmd[0], "USR") == 0) { + if ((strcmp(cmd[1], msn_file->handle) != 0) || + (strtoul(cmd[2], NULL, 10) != msn_file->auth_cookie)) { + msn_ftp_abort(file, "Authentication failed. " + "Expected handle: %s (got %s), cookie: %u (got %s)", + msn_file->handle, cmd[1], + msn_file->auth_cookie, cmd[2]); + } + msn_ftp_write(file, "FIL %zu\r\n", file->file_size); + } else if (strcmp(cmd[0], "TFR") == 0) { + file->write_request(file); + } else if (strcmp(cmd[0], "BYE") == 0) { unsigned int retcode = count > 1 ? atoi(cmd[1]) : 1; - if( ( retcode==16777989 ) || ( retcode==16777987 ) ) - imcb_file_finished( file ); - else if( retcode==2147942405 ) - imcb_file_canceled( file, "Failure: receiver is out of disk space" ); - else if( retcode==2164261682 ) - imcb_file_canceled( file, "Failure: receiver cancelled the transfer" ); - else if( retcode==2164261683 ) - imcb_file_canceled( file, "Failure: sender has cancelled the transfer" ); - else if( retcode==2164261694 ) - imcb_file_canceled( file, "Failure: connection is blocked" ); - else { + if ((retcode == 16777989) || (retcode == 16777987)) { + imcb_file_finished(file); + } else if (retcode == 2147942405) { + imcb_file_canceled(file, "Failure: receiver is out of disk space"); + } else if (retcode == 2164261682) { + imcb_file_canceled(file, "Failure: receiver cancelled the transfer"); + } else if (retcode == 2164261683) { + imcb_file_canceled(file, "Failure: sender has cancelled the transfer"); + } else if (retcode == 2164261694) { + imcb_file_canceled(file, "Failure: connection is blocked"); + } else { char buf[128]; - sprintf( buf, "Failure: unknown BYE code: %d", retcode); - imcb_file_canceled( file, buf ); + sprintf(buf, "Failure: unknown BYE code: %d", retcode); + imcb_file_canceled(file, buf); } - } else if( strcmp( cmd[0], "CCL" ) == 0 ) { - imcb_file_canceled( file, "Failure: receiver cancelled the transfer" ); + } else if (strcmp(cmd[0], "CCL") == 0) { + imcb_file_canceled(file, "Failure: receiver cancelled the transfer"); } else { - msn_ftp_abort( file, "Received invalid command %s from msn client", cmd[0] ); + msn_ftp_abort(file, "Received invalid command %s from msn client", cmd[0]); } return TRUE; } -gboolean msn_ftp_send( gpointer data, gint fd, b_input_condition cond ) +gboolean msn_ftp_send(gpointer data, gint fd, b_input_condition cond) { file_transfer_t *file = data; msn_filetransfer_t *msn_file = file->data; msn_file->w_event_id = 0; - file->write_request( file ); + file->write_request(file); return FALSE; } @@ -398,106 +422,115 @@ gboolean msn_ftp_send( gpointer data, gint fd, b_input_condition cond ) * Add a write watch so we can write more during the next cycle (if possible). * This got a bit complicated because (at least) amsn expects packets of size 2045. */ -gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len ) +gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len) { msn_filetransfer_t *msn_file = file->data; - int ret, overflow; + int ret, overflow; /* what we can't send now */ overflow = msn_file->sbufpos + len - MSNFTP_PSIZE; /* append what we can do the send buffer */ - memcpy( msn_file->sbuf + msn_file->sbufpos, buffer, MIN( len, MSNFTP_PSIZE - msn_file->sbufpos ) ); - msn_file->sbufpos += MIN( len, MSNFTP_PSIZE - msn_file->sbufpos ); + memcpy(msn_file->sbuf + msn_file->sbufpos, buffer, MIN(len, MSNFTP_PSIZE - msn_file->sbufpos)); + msn_file->sbufpos += MIN(len, MSNFTP_PSIZE - msn_file->sbufpos); /* if we don't have enough for a full packet and there's more wait for it */ - if( ( msn_file->sbufpos < MSNFTP_PSIZE ) && - ( msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size ) ) { - if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); + if ((msn_file->sbufpos < MSNFTP_PSIZE) && + (msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size)) { + if (!msn_file->w_event_id) { + msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file); + } return TRUE; } /* Accumulated enough data, lets send something out */ msn_file->sbuf[0] = 0; - msn_file->sbuf[1] = ( msn_file->sbufpos - 3 ) & 0xff; - msn_file->sbuf[2] = ( ( msn_file->sbufpos - 3 ) >> 8 ) & 0xff; + msn_file->sbuf[1] = (msn_file->sbufpos - 3) & 0xff; + msn_file->sbuf[2] = ((msn_file->sbufpos - 3) >> 8) & 0xff; - ASSERTSOCKOP( ret = send( msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0 ), "Sending" ); + ASSERTSOCKOP(ret = send(msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0), "Sending"); - msn_file->data_sent += ret - 3; + msn_file->data_sent += ret - 3; - /* TODO: this should really not be fatal */ - if( ret < msn_file->sbufpos ) - return msn_ftp_abort( file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos ); + /* TODO: this should really not be fatal */ + if (ret < msn_file->sbufpos) { + return msn_ftp_abort(file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos); + } msn_file->sbufpos = 3; - if( overflow > 0 ) { - while( overflow > ( MSNFTP_PSIZE - 3 ) ) { - if( !msn_ftps_write( file, buffer + len - overflow, MSNFTP_PSIZE - 3 ) ) + if (overflow > 0) { + while (overflow > (MSNFTP_PSIZE - 3)) { + if (!msn_ftps_write(file, buffer + len - overflow, MSNFTP_PSIZE - 3)) { return FALSE; + } overflow -= MSNFTP_PSIZE - 3; } - return msn_ftps_write( file, buffer + len - overflow, overflow ); + return msn_ftps_write(file, buffer + len - overflow, overflow); } - if( msn_file->data_sent == file->file_size ) { - if( msn_file->w_event_id ) { - b_event_remove( msn_file->w_event_id ); + if (msn_file->data_sent == file->file_size) { + if (msn_file->w_event_id) { + b_event_remove(msn_file->w_event_id); msn_file->w_event_id = 0; } } else { /* we might already be listening if this is data from an overflow */ - if( !msn_file->w_event_id ) - msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); + if (!msn_file->w_event_id) { + msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file); + } } - return TRUE; + return TRUE; } /* Binary part of the file transfer protocol */ -gboolean msn_ftpr_read( file_transfer_t *file ) +gboolean msn_ftpr_read(file_transfer_t *file) { msn_filetransfer_t *msn_file = file->data; int st; unsigned char buf[3]; - if( msn_file->data_remaining ) { + if (msn_file->data_remaining) { msn_file->r_event_id = 0; - ASSERTSOCKOP( st = read( msn_file->fd, file->buffer, MIN( sizeof( file->buffer ), msn_file->data_remaining ) ), "Receiving" ); + ASSERTSOCKOP(st = read(msn_file->fd, file->buffer, MIN(sizeof(file->buffer), + msn_file->data_remaining)), "Receiving"); - if( st == 0 ) - return msn_ftp_abort( file, "Remote end closed connection"); + if (st == 0) { + return msn_ftp_abort(file, "Remote end closed connection"); + } msn_file->data_sent += st; msn_file->data_remaining -= st; - file->write( file, file->buffer, st ); + file->write(file, file->buffer, st); - if( msn_file->data_sent >= file->file_size ) - imcb_file_finished( file ); + if (msn_file->data_sent >= file->file_size) { + imcb_file_finished(file); + } return FALSE; } else { - ASSERTSOCKOP( st = read( msn_file->fd, buf, 1 ), "Receiving" ); - if( st == 0 ) { - return msn_ftp_abort( file, "read returned EOF while reading data header from msn client" ); - } else if( buf[0] == '\r' || buf[0] == '\n' ) { - debug( "Discarding extraneous newline" ); - } else if( buf[0] != 0 ) { - msn_ftp_abort( file, "Remote end canceled the transfer"); + ASSERTSOCKOP(st = read(msn_file->fd, buf, 1), "Receiving"); + if (st == 0) { + return msn_ftp_abort(file, "read returned EOF while reading data header from msn client"); + } else if (buf[0] == '\r' || buf[0] == '\n') { + debug("Discarding extraneous newline"); + } else if (buf[0] != 0) { + msn_ftp_abort(file, "Remote end canceled the transfer"); /* don't really care about these last 2 (should be 0,0) */ - read( msn_file->fd, buf, 2 ); + read(msn_file->fd, buf, 2); return FALSE; } else { unsigned int size; - ASSERTSOCKOP( st = read( msn_file->fd, buf, 2 ), "Receiving" ); - if( st < 2 ) - return msn_ftp_abort( file, "read returned EOF while reading data header from msn client" ); + ASSERTSOCKOP(st = read(msn_file->fd, buf, 2), "Receiving"); + if (st < 2) { + return msn_ftp_abort(file, + "read returned EOF while reading data header from msn client"); + } size = buf[0] + ((unsigned int) buf[1] << 8); msn_file->data_remaining = size; @@ -507,116 +540,126 @@ gboolean msn_ftpr_read( file_transfer_t *file ) } /* Text mode part of the file transfer protocol */ -gboolean msn_ftp_txtproto( file_transfer_t *file ) +gboolean msn_ftp_txtproto(file_transfer_t *file) { msn_filetransfer_t *msn_file = file->data; int i = msn_file->tbufpos, st; char *tbuf = msn_file->tbuf; - ASSERTSOCKOP( st = read( msn_file->fd, - tbuf + msn_file->tbufpos, - sizeof( msn_file->tbuf ) - msn_file->tbufpos ), - "Receiving" ); + ASSERTSOCKOP(st = read(msn_file->fd, + tbuf + msn_file->tbufpos, + sizeof(msn_file->tbuf) - msn_file->tbufpos), + "Receiving"); - if( st == 0 ) - return msn_ftp_abort( file, "read returned EOF while reading text from msn client" ); + if (st == 0) { + return msn_ftp_abort(file, "read returned EOF while reading text from msn client"); + } msn_file->tbufpos += st; do { - for( ;i < msn_file->tbufpos; i++ ) { - if( tbuf[i] == '\n' || tbuf[i] == '\r' ) { + for (; i < msn_file->tbufpos; i++) { + if (tbuf[i] == '\n' || tbuf[i] == '\r') { tbuf[i] = '\0'; - if( i > 0 ) - msn_ftp_handle_command( file, tbuf ); - else - while( tbuf[i] == '\n' || tbuf[i] == '\r' ) i++; - memmove( tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1 ); + if (i > 0) { + msn_ftp_handle_command(file, tbuf); + } else { + while (tbuf[i] == '\n' || tbuf[i] == '\r') { + i++; + } + } + memmove(tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1); msn_file->tbufpos -= i + 1; i = 0; break; } } - } while ( i < msn_file->tbufpos ); + } while (i < msn_file->tbufpos); - if( msn_file->tbufpos == sizeof( msn_file->tbuf ) ) - return msn_ftp_abort( file, - "Line exceeded %d bytes in text protocol", - sizeof( msn_file->tbuf ) ); + if (msn_file->tbufpos == sizeof(msn_file->tbuf)) { + return msn_ftp_abort(file, + "Line exceeded %d bytes in text protocol", + sizeof(msn_file->tbuf)); + } return TRUE; } -gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond ) +gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond) { file_transfer_t *file = data; msn_filetransfer_t *msn_file = file->data; - - if( msn_file->status & MSN_TRANSFER_RECEIVING ) - return msn_ftpr_read( file ); - else - return msn_ftp_txtproto( file ); + + if (msn_file->status & MSN_TRANSFER_RECEIVING) { + return msn_ftpr_read(file); + } else { + return msn_ftp_txtproto(file); + } } -void msn_ftp_free( file_transfer_t *file ) +void msn_ftp_free(file_transfer_t *file) { msn_filetransfer_t *msn_file = file->data; - - if( msn_file->r_event_id ) - b_event_remove( msn_file->r_event_id ); - if( msn_file->w_event_id ) - b_event_remove( msn_file->w_event_id ); + if (msn_file->r_event_id) { + b_event_remove(msn_file->r_event_id); + } + + if (msn_file->w_event_id) { + b_event_remove(msn_file->w_event_id); + } + + if (msn_file->fd != -1) { + closesocket(msn_file->fd); + } + + msn_file->md->filetransfers = g_slist_remove(msn_file->md->filetransfers, msn_file->dcc); - if( msn_file->fd != -1 ) - closesocket( msn_file->fd ); + g_free(msn_file->handle); - msn_file->md->filetransfers = g_slist_remove( msn_file->md->filetransfers, msn_file->dcc ); - - g_free( msn_file->handle ); - - g_free( msn_file ); + g_free(msn_file); } -void msn_ftpr_accept( file_transfer_t *file ) +void msn_ftpr_accept(file_transfer_t *file) { msn_filetransfer_t *msn_file = file->data; - msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT", - "Launch-Application: FALSE\r\n" - "Request-Data: IP-Address:\r\n"); + msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT", + "Launch-Application: FALSE\r\n" + "Request-Data: IP-Address:\r\n"); } -void msn_ftp_finished( file_transfer_t *file ) +void msn_ftp_finished(file_transfer_t *file) { - msn_ftp_write( file, "BYE 16777989\r\n" ); + msn_ftp_write(file, "BYE 16777989\r\n"); } -void msn_ftp_canceled( file_transfer_t *file, char *reason ) +void msn_ftp_canceled(file_transfer_t *file, char *reason) { msn_filetransfer_t *msn_file = file->data; - msn_ftp_cancel_invite( msn_file->md->ic, msn_file->handle, - msn_file->invite_cookie, - file->status & FT_STATUS_TRANSFERRING ? - "FTTIMEOUT" : - "FAIL" ); + msn_ftp_cancel_invite(msn_file->md->ic, msn_file->handle, + msn_file->invite_cookie, + file->status & FT_STATUS_TRANSFERRING ? + "FTTIMEOUT" : + "FAIL"); - imcb_log( msn_file->md->ic, "File transfer aborted: %s", reason ); + imcb_log(msn_file->md->ic, "File transfer aborted: %s", reason); } -gboolean msn_ftpr_write_request( file_transfer_t *file ) +gboolean msn_ftpr_write_request(file_transfer_t *file) { msn_filetransfer_t *msn_file = file->data; - if( msn_file->r_event_id != 0 ) { - msn_ftp_abort( file, - "BUG in MSN file transfer:" - "write_request called when" - "already watching for input" ); + + if (msn_file->r_event_id != 0) { + msn_ftp_abort(file, + "BUG in MSN file transfer:" + "write_request called when" + "already watching for input"); return FALSE; } - msn_file->r_event_id = - b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); + msn_file->r_event_id = + b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file); return TRUE; } diff --git a/protocols/msn/invitation.h b/protocols/msn/invitation.h index 13bbf0d3..3e3bba0f 100644 --- a/protocols/msn/invitation.h +++ b/protocols/msn/invitation.h @@ -11,12 +11,12 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License with the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; if not, write to the Free Software Foundation, Inc., 51 Franklin St., @@ -28,20 +28,19 @@ #include "msn.h" -#define MSN_INVITE_HEADERS "MIME-Version: 1.0\r\n" \ - "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" \ - "\r\n" +#define MSN_INVITE_HEADERS "MIME-Version: 1.0\r\n" \ + "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" \ + "\r\n" #define MSNFTP_PSIZE 2048 typedef enum { - MSN_TRANSFER_RECEIVING = 1, - MSN_TRANSFER_SENDING = 2 + MSN_TRANSFER_RECEIVING = 1, + MSN_TRANSFER_SENDING = 2 } msn_filetransfer_status_t; -typedef struct msn_filetransfer -{ -/* Generic invitation data */ +typedef struct msn_filetransfer { +/* Generic invitation data */ /* msn_data instance this invitation was received with. */ struct msn_data *md; /* Cookie specifying this invitation. */ @@ -64,19 +63,19 @@ typedef struct msn_filetransfer /* Buffer containing received, but unprocessed text. */ char tbuf[256]; unsigned int tbufpos; - + unsigned int data_sent; gint r_event_id; gint w_event_id; - + unsigned char sbuf[2048]; int sbufpos; } msn_filetransfer_t; -void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ); -void msn_invitation_accept( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ); -void msn_invitation_cancel( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ); +void msn_invitation_invite(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen); +void msn_invitation_accept(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen); +void msn_invitation_cancel(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen); #endif diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index 65c19276..6ab35696 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -31,407 +31,409 @@ int msn_chat_id; GSList *msn_connections; GSList *msn_switchboards; -static char *set_eval_display_name( set_t *set, char *value ); +static char *set_eval_display_name(set_t *set, char *value); -static void msn_init( account_t *acc ) +static void msn_init(account_t *acc) { set_t *s; - - s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + + s = set_add(&acc->set, "display_name", NULL, set_eval_display_name, acc); s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY; - - s = set_add( &acc->set, "server", MSN_NS_HOST, set_eval_account, acc ); + + s = set_add(&acc->set, "server", MSN_NS_HOST, set_eval_account, acc); s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; - s = set_add( &acc->set, "port", MSN_NS_PORT, set_eval_int, acc ); + s = set_add(&acc->set, "port", MSN_NS_PORT, set_eval_int, acc); s->flags |= ACC_SET_OFFLINE_ONLY; - set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); - set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc ); - + set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc); + set_add(&acc->set, "switchboard_keepalives", "false", set_eval_bool, acc); + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | ACC_FLAG_HANDLE_DOMAINS; } -static void msn_login( account_t *acc ) +static void msn_login(account_t *acc) { - struct im_connection *ic = imcb_new( acc ); - struct msn_data *md = g_new0( struct msn_data, 1 ); - + struct im_connection *ic = imcb_new(acc); + struct msn_data *md = g_new0(struct msn_data, 1); + ic->proto_data = md; ic->flags |= OPT_PONGS | OPT_PONGED; - - if( strchr( acc->user, '@' ) == NULL ) - { - imcb_error( ic, "Invalid account name" ); - imc_logout( ic, FALSE ); + + if (strchr(acc->user, '@') == NULL) { + imcb_error(ic, "Invalid account name"); + imc_logout(ic, FALSE); return; } - + md->ic = ic; md->away_state = msn_away_state_list; - md->domaintree = g_tree_new( msn_domaintree_cmp ); + md->domaintree = g_tree_new(msn_domaintree_cmp); md->ns->fd = -1; - - msn_connections = g_slist_prepend( msn_connections, ic ); - - imcb_log( ic, "Connecting" ); - msn_ns_connect( ic, md->ns, - set_getstr( &ic->acc->set, "server" ), - set_getint( &ic->acc->set, "port" ) ); + + msn_connections = g_slist_prepend(msn_connections, ic); + + imcb_log(ic, "Connecting"); + msn_ns_connect(ic, md->ns, + set_getstr(&ic->acc->set, "server"), + set_getint(&ic->acc->set, "port")); } -static void msn_logout( struct im_connection *ic ) +static void msn_logout(struct im_connection *ic) { struct msn_data *md = ic->proto_data; GSList *l; int i; - - if( md ) - { + + if (md) { /** Disabling MSN ft support for now. while( md->filetransfers ) { - imcb_file_canceled( md->filetransfers->data, "Closing connection" ); + imcb_file_canceled( md->filetransfers->data, "Closing connection" ); } */ - - msn_ns_close( md->ns ); - - while( md->switchboards ) - msn_sb_destroy( md->switchboards->data ); - - msn_msgq_purge( ic, &md->msgq ); - msn_soapq_flush( ic, FALSE ); - - for( i = 0; i < sizeof( md->tokens ) / sizeof( md->tokens[0] ); i ++ ) - g_free( md->tokens[i] ); - g_free( md->lock_key ); - g_free( md->pp_policy ); - g_free( md->uuid ); - - while( md->groups ) - { + + msn_ns_close(md->ns); + + while (md->switchboards) { + msn_sb_destroy(md->switchboards->data); + } + + msn_msgq_purge(ic, &md->msgq); + msn_soapq_flush(ic, FALSE); + + for (i = 0; i < sizeof(md->tokens) / sizeof(md->tokens[0]); i++) { + g_free(md->tokens[i]); + } + g_free(md->lock_key); + g_free(md->pp_policy); + g_free(md->uuid); + + while (md->groups) { struct msn_group *mg = md->groups->data; - g_free( mg->id ); - g_free( mg->name ); - g_free( mg ); - md->groups = g_slist_remove( md->groups, mg ); + g_free(mg->id); + g_free(mg->name); + g_free(mg); + md->groups = g_slist_remove(md->groups, mg); + } + + g_free(md->profile_rid); + + if (md->domaintree) { + g_tree_destroy(md->domaintree); } - - g_free( md->profile_rid ); - - if( md->domaintree ) - g_tree_destroy( md->domaintree ); md->domaintree = NULL; - - while( md->grpq ) - { + + while (md->grpq) { struct msn_groupadd *ga = md->grpq->data; - g_free( ga->group ); - g_free( ga->who ); - g_free( ga ); - md->grpq = g_slist_remove( md->grpq, ga ); + g_free(ga->group); + g_free(ga->who); + g_free(ga); + md->grpq = g_slist_remove(md->grpq, ga); } - - g_free( md ); + + g_free(md); + } + + for (l = ic->permit; l; l = l->next) { + g_free(l->data); + } + g_slist_free(ic->permit); + + for (l = ic->deny; l; l = l->next) { + g_free(l->data); } - - for( l = ic->permit; l; l = l->next ) - g_free( l->data ); - g_slist_free( ic->permit ); - - for( l = ic->deny; l; l = l->next ) - g_free( l->data ); - g_slist_free( ic->deny ); - - msn_connections = g_slist_remove( msn_connections, ic ); + g_slist_free(ic->deny); + + msn_connections = g_slist_remove(msn_connections, ic); } -static int msn_buddy_msg( struct im_connection *ic, char *who, char *message, int away ) +static int msn_buddy_msg(struct im_connection *ic, char *who, char *message, int away) { - struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); + struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who); struct msn_buddy_data *bd = bu ? bu->data : NULL; struct msn_switchboard *sb; - + #ifdef DEBUG - if( strcmp( who, "raw" ) == 0 ) - { - msn_ns_write( ic, -1, "%s\r\n", message ); - } - else + if (strcmp(who, "raw") == 0) { + msn_ns_write(ic, -1, "%s\r\n", message); + } else #endif - if( bd && bd->flags & MSN_BUDDY_FED ) - { - msn_ns_sendmessage( ic, bu, message ); - } - else if( ( sb = msn_sb_by_handle( ic, who ) ) ) - { - return( msn_sb_sendmessage( sb, message ) ); - } - else - { + if (bd && bd->flags & MSN_BUDDY_FED) { + msn_ns_sendmessage(ic, bu, message); + } else if ((sb = msn_sb_by_handle(ic, who))) { + return(msn_sb_sendmessage(sb, message)); + } else { struct msn_message *m; - + /* Create a message. We have to arrange a usable switchboard, and send the message later. */ - m = g_new0( struct msn_message, 1 ); - m->who = g_strdup( who ); - m->text = g_strdup( message ); - - return msn_sb_write_msg( ic, m ); + m = g_new0(struct msn_message, 1); + m->who = g_strdup(who); + m->text = g_strdup(message); + + return msn_sb_write_msg(ic, m); } - - return( 0 ); + + return(0); } -static GList *msn_away_states( struct im_connection *ic ) +static GList *msn_away_states(struct im_connection *ic) { static GList *l = NULL; int i; - - if( l == NULL ) - for( i = 0; *msn_away_state_list[i].code; i ++ ) - if( *msn_away_state_list[i].name ) - l = g_list_append( l, (void*) msn_away_state_list[i].name ); - + + if (l == NULL) { + for (i = 0; *msn_away_state_list[i].code; i++) { + if (*msn_away_state_list[i].name) { + l = g_list_append(l, (void *) msn_away_state_list[i].name); + } + } + } + return l; } -static void msn_set_away( struct im_connection *ic, char *state, char *message ) +static void msn_set_away(struct im_connection *ic, char *state, char *message) { char *uux; struct msn_data *md = ic->proto_data; - - if( state == NULL ) + + if (state == NULL) { md->away_state = msn_away_state_list; - else if( ( md->away_state = msn_away_state_by_name( state ) ) == NULL ) + } else if ((md->away_state = msn_away_state_by_name(state)) == NULL) { md->away_state = msn_away_state_list + 1; - - if( !msn_ns_write( ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2 ) ) + } + + if (!msn_ns_write(ic, -1, "CHG %d %s %d:%02d\r\n", ++md->trId, md->away_state->code, MSN_CAP1, MSN_CAP2)) { return; - - uux = g_markup_printf_escaped( "<EndpointData><Capabilities>%d:%02d" - "</Capabilities></EndpointData>", - MSN_CAP1, MSN_CAP2 ); - msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); - g_free( uux ); - - uux = g_markup_printf_escaped( "<PrivateEndpointData><EpName>%s</EpName>" - "<Idle>%s</Idle><ClientType>%d</ClientType>" - "<State>%s</State></PrivateEndpointData>", - md->uuid, - strcmp( md->away_state->code, "IDL" ) ? "false" : "true", - 1, /* ? */ - md->away_state->code ); - msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); - g_free( uux ); - - uux = g_markup_printf_escaped( "<Data><DDP></DDP><PSM>%s</PSM>" - "<CurrentMedia></CurrentMedia>" - "<MachineGuid>%s</MachineGuid></Data>", - message ? message : "", md->uuid ); - msn_ns_write( ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen( uux ), uux ); - g_free( uux ); + } + + uux = g_markup_printf_escaped("<EndpointData><Capabilities>%d:%02d" + "</Capabilities></EndpointData>", + MSN_CAP1, MSN_CAP2); + msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux); + g_free(uux); + + uux = g_markup_printf_escaped("<PrivateEndpointData><EpName>%s</EpName>" + "<Idle>%s</Idle><ClientType>%d</ClientType>" + "<State>%s</State></PrivateEndpointData>", + md->uuid, + strcmp(md->away_state->code, "IDL") ? "false" : "true", + 1, /* ? */ + md->away_state->code); + msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux); + g_free(uux); + + uux = g_markup_printf_escaped("<Data><DDP></DDP><PSM>%s</PSM>" + "<CurrentMedia></CurrentMedia>" + "<MachineGuid>%s</MachineGuid></Data>", + message ? message : "", md->uuid); + msn_ns_write(ic, -1, "UUX %d %zd\r\n%s", ++md->trId, strlen(uux), uux); + g_free(uux); } -static void msn_get_info(struct im_connection *ic, char *who) +static void msn_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - imcb_log( ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who ); + imcb_log(ic, "%s\n%s: %s%s", _("User Info"), _("For now, fetch yourself"), PROFILE_URL, who); } -static void msn_add_buddy( struct im_connection *ic, char *who, char *group ) +static void msn_add_buddy(struct im_connection *ic, char *who, char *group) { - struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); - - msn_buddy_list_add( ic, MSN_BUDDY_FL, who, who, group ); - if( bu && bu->group ) - msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, bu->group->name ); + struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who); + + msn_buddy_list_add(ic, MSN_BUDDY_FL, who, who, group); + if (bu && bu->group) { + msn_buddy_list_remove(ic, MSN_BUDDY_FL, who, bu->group->name); + } } -static void msn_remove_buddy( struct im_connection *ic, char *who, char *group ) +static void msn_remove_buddy(struct im_connection *ic, char *who, char *group) { - msn_buddy_list_remove( ic, MSN_BUDDY_FL, who, NULL ); + msn_buddy_list_remove(ic, MSN_BUDDY_FL, who, NULL); } -static void msn_chat_msg( struct groupchat *c, char *message, int flags ) +static void msn_chat_msg(struct groupchat *c, char *message, int flags) { - struct msn_switchboard *sb = msn_sb_by_chat( c ); - - if( sb ) - msn_sb_sendmessage( sb, message ); + struct msn_switchboard *sb = msn_sb_by_chat(c); + + if (sb) { + msn_sb_sendmessage(sb, message); + } /* FIXME: Error handling (although this can't happen unless something's already severely broken) disappeared here! */ } -static void msn_chat_invite( struct groupchat *c, char *who, char *message ) +static void msn_chat_invite(struct groupchat *c, char *who, char *message) { - struct msn_switchboard *sb = msn_sb_by_chat( c ); - - if( sb ) - msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, who ); + struct msn_switchboard *sb = msn_sb_by_chat(c); + + if (sb) { + msn_sb_write(sb, "CAL %d %s\r\n", ++sb->trId, who); + } } -static void msn_chat_leave( struct groupchat *c ) +static void msn_chat_leave(struct groupchat *c) { - struct msn_switchboard *sb = msn_sb_by_chat( c ); - - if( sb ) - msn_sb_write( sb, "OUT\r\n" ); + struct msn_switchboard *sb = msn_sb_by_chat(c); + + if (sb) { + msn_sb_write(sb, "OUT\r\n"); + } } -static struct groupchat *msn_chat_with( struct im_connection *ic, char *who ) +static struct groupchat *msn_chat_with(struct im_connection *ic, char *who) { struct msn_switchboard *sb; - struct groupchat *c = imcb_chat_new( ic, who ); - - if( ( sb = msn_sb_by_handle( ic, who ) ) ) - { - debug( "Converting existing switchboard to %s to a groupchat", who ); - return msn_sb_to_chat( sb ); - } - else - { + struct groupchat *c = imcb_chat_new(ic, who); + + if ((sb = msn_sb_by_handle(ic, who))) { + debug("Converting existing switchboard to %s to a groupchat", who); + return msn_sb_to_chat(sb); + } else { struct msn_message *m; - + /* Create a magic message. This is quite hackish, but who cares? :-P */ - m = g_new0( struct msn_message, 1 ); - m->who = g_strdup( who ); - m->text = g_strdup( GROUPCHAT_SWITCHBOARD_MESSAGE ); - - msn_sb_write_msg( ic, m ); + m = g_new0(struct msn_message, 1); + m->who = g_strdup(who); + m->text = g_strdup(GROUPCHAT_SWITCHBOARD_MESSAGE); + + msn_sb_write_msg(ic, m); return c; } } -static void msn_keepalive( struct im_connection *ic ) +static void msn_keepalive(struct im_connection *ic) { - msn_ns_write( ic, -1, "PNG\r\n" ); + msn_ns_write(ic, -1, "PNG\r\n"); } -static void msn_add_permit( struct im_connection *ic, char *who ) +static void msn_add_permit(struct im_connection *ic, char *who) { - msn_buddy_list_add( ic, MSN_BUDDY_AL, who, who, NULL ); + msn_buddy_list_add(ic, MSN_BUDDY_AL, who, who, NULL); } -static void msn_rem_permit( struct im_connection *ic, char *who ) +static void msn_rem_permit(struct im_connection *ic, char *who) { - msn_buddy_list_remove( ic, MSN_BUDDY_AL, who, NULL ); + msn_buddy_list_remove(ic, MSN_BUDDY_AL, who, NULL); } -static void msn_add_deny( struct im_connection *ic, char *who ) +static void msn_add_deny(struct im_connection *ic, char *who) { struct msn_switchboard *sb; - - msn_buddy_list_add( ic, MSN_BUDDY_BL, who, who, NULL ); - + + msn_buddy_list_add(ic, MSN_BUDDY_BL, who, who, NULL); + /* If there's still a conversation with this person, close it. */ - if( ( sb = msn_sb_by_handle( ic, who ) ) ) - { - msn_sb_destroy( sb ); + if ((sb = msn_sb_by_handle(ic, who))) { + msn_sb_destroy(sb); } } -static void msn_rem_deny( struct im_connection *ic, char *who ) +static void msn_rem_deny(struct im_connection *ic, char *who) { - msn_buddy_list_remove( ic, MSN_BUDDY_BL, who, NULL ); + msn_buddy_list_remove(ic, MSN_BUDDY_BL, who, NULL); } -static int msn_send_typing( struct im_connection *ic, char *who, int typing ) +static int msn_send_typing(struct im_connection *ic, char *who, int typing) { - struct bee_user *bu = bee_user_by_handle( ic->bee, ic, who ); - - if( !( bu->flags & BEE_USER_ONLINE ) ) + struct bee_user *bu = bee_user_by_handle(ic->bee, ic, who); + + if (!(bu->flags & BEE_USER_ONLINE)) { return 0; - else if( typing & OPT_TYPING ) - return( msn_buddy_msg( ic, who, TYPING_NOTIFICATION_MESSAGE, 0 ) ); - else + } else if (typing & OPT_TYPING) { + return(msn_buddy_msg(ic, who, TYPING_NOTIFICATION_MESSAGE, 0)); + } else { return 1; + } } -static char *set_eval_display_name( set_t *set, char *value ) +static char *set_eval_display_name(set_t *set, char *value) { account_t *acc = set->data; struct im_connection *ic = acc->ic; struct msn_data *md = ic->proto_data; - - if( md->flags & MSN_EMAIL_UNVERIFIED ) - imcb_log( ic, "Warning: Your e-mail address is unverified. MSN doesn't allow " - "changing your display name until your e-mail address is verified." ); - - if( md->flags & MSN_GOT_PROFILE_DN ) - msn_soap_profile_set_dn( ic, value ); - else - msn_soap_addressbook_set_display_name( ic, value ); - - return msn_ns_set_display_name( ic, value ) ? value : NULL; + + if (md->flags & MSN_EMAIL_UNVERIFIED) { + imcb_log(ic, "Warning: Your e-mail address is unverified. MSN doesn't allow " + "changing your display name until your e-mail address is verified."); + } + + if (md->flags & MSN_GOT_PROFILE_DN) { + msn_soap_profile_set_dn(ic, value); + } else { + msn_soap_addressbook_set_display_name(ic, value); + } + + return msn_ns_set_display_name(ic, value) ? value : NULL; } -static void msn_buddy_data_add( bee_user_t *bu ) +static void msn_buddy_data_add(bee_user_t *bu) { struct msn_data *md = bu->ic->proto_data; struct msn_buddy_data *bd; char *handle; - - bd = bu->data = g_new0( struct msn_buddy_data, 1 ); - g_tree_insert( md->domaintree, bu->handle, bu ); - - for( handle = bu->handle; g_ascii_isdigit( *handle ); handle ++ ); - if( *handle == ':' ) - { + + bd = bu->data = g_new0(struct msn_buddy_data, 1); + g_tree_insert(md->domaintree, bu->handle, bu); + + for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) { + ; + } + if (*handle == ':') { /* Pass a nick hint so hopefully the stupid numeric prefix won't show up to the user. */ - char *s = strchr( ++handle, '@' ); - if( s ) - { - handle = g_strndup( handle, s - handle ); - imcb_buddy_nick_hint( bu->ic, bu->handle, handle ); - g_free( handle ); + char *s = strchr(++handle, '@'); + if (s) { + handle = g_strndup(handle, s - handle); + imcb_buddy_nick_hint(bu->ic, bu->handle, handle); + g_free(handle); } - + bd->flags |= MSN_BUDDY_FED; } } -static void msn_buddy_data_free( bee_user_t *bu ) +static void msn_buddy_data_free(bee_user_t *bu) { struct msn_data *md = bu->ic->proto_data; struct msn_buddy_data *bd = bu->data; - - g_free( bd->cid ); - g_free( bd ); - - g_tree_remove( md->domaintree, bu->handle ); + + g_free(bd->cid); + g_free(bd); + + g_tree_remove(md->domaintree, bu->handle); } -GList *msn_buddy_action_list( bee_user_t *bu ) +GList *msn_buddy_action_list(bee_user_t *bu) { static GList *ret = NULL; - - if( ret == NULL ) - { + + if (ret == NULL) { static const struct buddy_action ba[2] = { { "NUDGE", "Draw attention" }, }; - - ret = g_list_prepend( ret, (void*) ba + 0 ); + + ret = g_list_prepend(ret, (void *) ba + 0); } - + return ret; } -void *msn_buddy_action( struct bee_user *bu, const char *action, char * const args[], void *data ) +void *msn_buddy_action(struct bee_user *bu, const char *action, char * const args[], void *data) { - if( g_strcasecmp( action, "NUDGE" ) == 0 ) - msn_buddy_msg( bu->ic, bu->handle, NUDGE_MESSAGE, 0 ); - + if (g_strcasecmp(action, "NUDGE") == 0) { + msn_buddy_msg(bu->ic, bu->handle, NUDGE_MESSAGE, 0); + } + return NULL; } 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; @@ -458,7 +460,7 @@ void msn_initmodule() ret->buddy_data_free = msn_buddy_data_free; ret->buddy_action_list = msn_buddy_action_list; ret->buddy_action = msn_buddy_action; - + //ret->transfer_request = msn_ftp_transfer_request; register_protocol(ret); diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 438b2174..6022bc31 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -34,9 +34,9 @@ #define SB_KEEPALIVE_MESSAGE "\r\r\rDONT HANG UP ON ME!\r\r\r" #ifdef DEBUG_MSN -#define debug( text... ) imcb_log( ic, text ); +#define debug(text ...) imcb_log(ic, text); #else -#define debug( text... ) +#define debug(text ...) #endif /* This should be MSN Messenger 7.0.0813 @@ -68,30 +68,29 @@ #define MSN_CAP2 0x0000 #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \ - "Content-Type: text/plain; charset=UTF-8\r\n" \ - "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ - "X-MMS-IM-Format: FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n" \ - "\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" \ + "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ + "X-MMS-IM-Format: FN=MS%20Shell%20Dlg; EF=; CO=0; CS=0; PF=0\r\n" \ + "\r\n" #define MSN_TYPING_HEADERS "MIME-Version: 1.0\r\n" \ - "Content-Type: text/x-msmsgscontrol\r\n" \ - "TypingUser: %s\r\n" \ - "\r\n\r\n" + "Content-Type: text/x-msmsgscontrol\r\n" \ + "TypingUser: %s\r\n" \ + "\r\n\r\n" #define MSN_NUDGE_HEADERS "MIME-Version: 1.0\r\n" \ - "Content-Type: text/x-msnmsgr-datacast\r\n" \ - "\r\n" \ - "ID: 1\r\n" \ - "\r\n" + "Content-Type: text/x-msnmsgr-datacast\r\n" \ + "\r\n" \ + "ID: 1\r\n" \ + "\r\n" #define MSN_SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \ - "Content-Type: text/x-ping\r\n" \ - "\r\n\r\n" + "Content-Type: text/x-ping\r\n" \ + "\r\n\r\n" #define PROFILE_URL "http://members.msn.com/" -typedef enum -{ +typedef enum { MSN_GOT_PROFILE = 1, MSN_GOT_PROFILE_DN = 2, MSN_DONE_ADL = 4, @@ -99,43 +98,41 @@ typedef enum MSN_EMAIL_UNVERIFIED = 16, } msn_flags_t; -struct msn_handler_data -{ +struct msn_handler_data { int fd, inpa; int rxlen; char *rxq; - + int msglen; char *cmd_text; - + /* Either ic or sb */ gpointer data; - - int (*exec_command) ( struct msn_handler_data *handler, char **cmd, int count ); - int (*exec_message) ( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count ); + + int (*exec_command) (struct msn_handler_data *handler, char **cmd, int count); + int (*exec_message) (struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int count); }; -struct msn_data -{ +struct msn_data { struct im_connection *ic; - + struct msn_handler_data ns[1]; msn_flags_t flags; - + int trId; char *tokens[4]; char *lock_key, *pp_policy; char *uuid; - + GSList *msgq, *grpq, *soapq; GSList *switchboards; int sb_failures; time_t first_sb_failure; - + const struct msn_away_state *away_state; GSList *groups; char *profile_rid; - + /* Mostly used for sending the ADL command; since MSNP13 the client is responsible for downloading the contact list and then sending it to the MSNP server. */ @@ -143,54 +140,48 @@ struct msn_data int adl_todo; }; -struct msn_switchboard -{ +struct msn_switchboard { struct im_connection *ic; - + /* The following two are also in the handler. TODO: Clean up. */ int fd; gint inp; struct msn_handler_data *handler; gint keepalive; - + int trId; int ready; - + int session; char *key; - + GSList *msgq; char *who; struct groupchat *chat; }; -struct msn_away_state -{ +struct msn_away_state { char code[4]; char name[16]; }; -struct msn_status_code -{ +struct msn_status_code { int number; char *text; int flags; }; -struct msn_message -{ +struct msn_message { char *who; char *text; }; -struct msn_groupadd -{ +struct msn_groupadd { char *who; char *group; }; -typedef enum -{ +typedef enum { MSN_BUDDY_FL = 1, /* Warning: FL,AL,BL *must* be 1,2,4. */ MSN_BUDDY_AL = 2, MSN_BUDDY_BL = 4, @@ -200,14 +191,12 @@ typedef enum MSN_BUDDY_FED = 512, } msn_buddy_flags_t; -struct msn_buddy_data -{ +struct msn_buddy_data { char *cid; msn_buddy_flags_t flags; }; -struct msn_group -{ +struct msn_group { char *name; char *id; }; @@ -215,8 +204,8 @@ struct msn_group /* Bitfield values for msn_status_code.flags */ #define STATUS_FATAL 1 #define STATUS_SB_FATAL 2 -#define STATUS_SB_IM_SPARE 4 /* Make one-to-one conversation switchboard available again, invite failed. */ -#define STATUS_SB_CHAT_SPARE 8 /* Same, but also for groupchats (not used yet). */ +#define STATUS_SB_IM_SPARE 4 /* Make one-to-one conversation switchboard available again, invite failed. */ +#define STATUS_SB_CHAT_SPARE 8 /* Same, but also for groupchats (not used yet). */ extern int msn_chat_id; extern const struct msn_away_state msn_away_state_list[]; @@ -231,47 +220,48 @@ extern GSList *msn_connections; extern GSList *msn_switchboards; /* ns.c */ -int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) G_GNUC_PRINTF( 3, 4 ); -gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ); -void msn_ns_close( struct msn_handler_data *handler ); -void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ); -void msn_auth_got_contact_list( struct im_connection *ic ); -int msn_ns_finish_login( struct im_connection *ic ); -int msn_ns_sendmessage( struct im_connection *ic, struct bee_user *bu, const char *text ); -void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ); +int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...) G_GNUC_PRINTF(3, 4); +gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port); +void msn_ns_close(struct msn_handler_data *handler); +void msn_auth_got_passport_token(struct im_connection *ic, const char *token, const char *error); +void msn_auth_got_contact_list(struct im_connection *ic); +int msn_ns_finish_login(struct im_connection *ic); +int msn_ns_sendmessage(struct im_connection *ic, struct bee_user *bu, const char *text); +void msn_ns_oim_send_queue(struct im_connection *ic, GSList **msgq); /* msn_util.c */ -int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, const char *group ); -int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ); -void msn_buddy_ask( bee_user_t *bu ); -char **msn_linesplit( char *line ); -int msn_handler( struct msn_handler_data *h ); -void msn_msgq_purge( struct im_connection *ic, GSList **list ); -char *msn_p11_challenge( char *challenge ); -gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ); -struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ); -struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ); -int msn_ns_set_display_name( struct im_connection *ic, const char *value ); -const char *msn_normalize_handle( const char *handle ); +int msn_buddy_list_add(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname_, + const char *group); +int msn_buddy_list_remove(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group); +void msn_buddy_ask(bee_user_t *bu); +char **msn_linesplit(char *line); +int msn_handler(struct msn_handler_data *h); +void msn_msgq_purge(struct im_connection *ic, GSList **list); +char *msn_p11_challenge(char *challenge); +gint msn_domaintree_cmp(gconstpointer a_, gconstpointer b_); +struct msn_group *msn_group_by_name(struct im_connection *ic, const char *name); +struct msn_group *msn_group_by_id(struct im_connection *ic, const char *id); +int msn_ns_set_display_name(struct im_connection *ic, const char *value); +const char *msn_normalize_handle(const char *handle); /* tables.c */ -const struct msn_away_state *msn_away_state_by_number( int number ); -const struct msn_away_state *msn_away_state_by_code( char *code ); -const struct msn_away_state *msn_away_state_by_name( char *name ); -const struct msn_status_code *msn_status_by_number( int number ); +const struct msn_away_state *msn_away_state_by_number(int number); +const struct msn_away_state *msn_away_state_by_code(char *code); +const struct msn_away_state *msn_away_state_by_name(char *name); +const struct msn_status_code *msn_status_by_number(int number); /* sb.c */ -int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) G_GNUC_PRINTF( 2, 3 );; -struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ); -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ); -struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ); -struct msn_switchboard *msn_sb_spare( struct im_connection *ic ); -int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ); -struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ); -void msn_sb_destroy( struct msn_switchboard *sb ); -gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ); -int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); -void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ); -void msn_sb_stop_keepalives( struct msn_switchboard *sb ); +int msn_sb_write(struct msn_switchboard *sb, const char *fmt, ...) G_GNUC_PRINTF(2, 3);; +struct msn_switchboard *msn_sb_create(struct im_connection *ic, char *host, int port, char *key, int session); +struct msn_switchboard *msn_sb_by_handle(struct im_connection *ic, const char *handle); +struct msn_switchboard *msn_sb_by_chat(struct groupchat *c); +struct msn_switchboard *msn_sb_spare(struct im_connection *ic); +int msn_sb_sendmessage(struct msn_switchboard *sb, char *text); +struct groupchat *msn_sb_to_chat(struct msn_switchboard *sb); +void msn_sb_destroy(struct msn_switchboard *sb); +gboolean msn_sb_connected(gpointer data, gint source, b_input_condition cond); +int msn_sb_write_msg(struct im_connection *ic, struct msn_message *m); +void msn_sb_start_keepalives(struct msn_switchboard *sb, gboolean initial); +void msn_sb_stop_keepalives(struct msn_switchboard *sb); #endif //_MSN_H diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index f329ae03..8f929305 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -29,68 +29,65 @@ #include "soap.h" #include <ctype.h> -static char *adlrml_entry( const char *handle_, msn_buddy_flags_t list ) +static char *adlrml_entry(const char *handle_, msn_buddy_flags_t list) { - char *domain, handle[strlen(handle_)+1]; - - strcpy( handle, handle_ ); - if( ( domain = strchr( handle, '@' ) ) ) + char *domain, handle[strlen(handle_) + 1]; + + strcpy(handle, handle_); + if ((domain = strchr(handle, '@'))) { *(domain++) = '\0'; - else + } else { return NULL; - - return g_markup_printf_escaped( "<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>", - domain, handle, list ); + } + + return g_markup_printf_escaped("<ml><d n=\"%s\"><c n=\"%s\" l=\"%d\" t=\"1\"/></d></ml>", + domain, handle, list); } -int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, const char *group ) +int msn_buddy_list_add(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *realname, + const char *group) { struct msn_data *md = ic->proto_data; char groupid[8]; bee_user_t *bu; struct msn_buddy_data *bd; char *adl; - + *groupid = '\0'; #if 0 - if( group ) - { + if (group) { int i; - for( i = 0; i < md->groupcount; i ++ ) - if( g_strcasecmp( md->grouplist[i], group ) == 0 ) - { - g_snprintf( groupid, sizeof( groupid ), " %d", i ); + for (i = 0; i < md->groupcount; i++) { + if (g_strcasecmp(md->grouplist[i], group) == 0) { + g_snprintf(groupid, sizeof(groupid), " %d", i); break; } - - if( *groupid == '\0' ) - { + } + + if (*groupid == '\0') { /* Have to create this group, it doesn't exist yet. */ struct msn_groupadd *ga; GSList *l; - - for( l = md->grpq; l; l = l->next ) - { + + for (l = md->grpq; l; l = l->next) { ga = l->data; - if( g_strcasecmp( ga->group, group ) == 0 ) + if (g_strcasecmp(ga->group, group) == 0) { break; + } } - - ga = g_new0( struct msn_groupadd, 1 ); - ga->who = g_strdup( who ); - ga->group = g_strdup( group ); - md->grpq = g_slist_prepend( md->grpq, ga ); - - if( l == NULL ) - { - char groupname[strlen(group)+1]; - strcpy( groupname, group ); - http_encode( groupname ); - g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); - return msn_write( ic, buf, strlen( buf ) ); - } - else - { + + ga = g_new0(struct msn_groupadd, 1); + ga->who = g_strdup(who); + ga->group = g_strdup(group); + md->grpq = g_slist_prepend(md->grpq, ga); + + if (l == NULL) { + char groupname[strlen(group) + 1]; + strcpy(groupname, group); + http_encode(groupname); + g_snprintf(buf, sizeof(buf), "ADG %d %s %d\r\n", ++md->trId, groupname, 0); + return msn_write(ic, buf, strlen(buf)); + } else { /* This can happen if the user's doing lots of adds to a new group at once; we're still waiting for the server to confirm group creation. */ @@ -99,155 +96,159 @@ int msn_buddy_list_add( struct im_connection *ic, msn_buddy_flags_t list, const } } #endif - - if( !( ( bu = bee_user_by_handle( ic->bee, ic, who ) ) || - ( bu = bee_user_new( ic->bee, ic, who, 0 ) ) ) || - !( bd = bu->data ) || bd->flags & list ) + + if (!((bu = bee_user_by_handle(ic->bee, ic, who)) || + (bu = bee_user_new(ic->bee, ic, who, 0))) || + !(bd = bu->data) || bd->flags & list) { return 1; - + } + bd->flags |= list; - - if( list == MSN_BUDDY_FL ) - msn_soap_ab_contact_add( ic, bu ); - else - msn_soap_memlist_edit( ic, who, TRUE, list ); - - if( ( adl = adlrml_entry( who, list ) ) ) - { - int st = msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", - ++md->trId, strlen( adl ), adl ); - g_free( adl ); - + + if (list == MSN_BUDDY_FL) { + msn_soap_ab_contact_add(ic, bu); + } else { + msn_soap_memlist_edit(ic, who, TRUE, list); + } + + if ((adl = adlrml_entry(who, list))) { + int st = msn_ns_write(ic, -1, "ADL %d %zd\r\n%s", + ++md->trId, strlen(adl), adl); + g_free(adl); + return st; } - + return 1; } -int msn_buddy_list_remove( struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group ) +int msn_buddy_list_remove(struct im_connection *ic, msn_buddy_flags_t list, const char *who, const char *group) { struct msn_data *md = ic->proto_data; char groupid[8]; bee_user_t *bu; struct msn_buddy_data *bd; char *adl; - + *groupid = '\0'; #if 0 - if( group ) - { + if (group) { int i; - for( i = 0; i < md->groupcount; i ++ ) - if( g_strcasecmp( md->grouplist[i], group ) == 0 ) - { - g_snprintf( groupid, sizeof( groupid ), " %d", i ); + for (i = 0; i < md->groupcount; i++) { + if (g_strcasecmp(md->grouplist[i], group) == 0) { + g_snprintf(groupid, sizeof(groupid), " %d", i); break; } + } } #endif - - if( !( bu = bee_user_by_handle( ic->bee, ic, who ) ) || - !( bd = bu->data ) || !( bd->flags & list ) ) + + if (!(bu = bee_user_by_handle(ic->bee, ic, who)) || + !(bd = bu->data) || !(bd->flags & list)) { return 1; - + } + bd->flags &= ~list; - - if( list == MSN_BUDDY_FL ) - msn_soap_ab_contact_del( ic, bu ); - else - msn_soap_memlist_edit( ic, who, FALSE, list ); - - if( ( adl = adlrml_entry( who, list ) ) ) - { - int st = msn_ns_write( ic, -1, "RML %d %zd\r\n%s", - ++md->trId, strlen( adl ), adl ); - g_free( adl ); - + + if (list == MSN_BUDDY_FL) { + msn_soap_ab_contact_del(ic, bu); + } else { + msn_soap_memlist_edit(ic, who, FALSE, list); + } + + if ((adl = adlrml_entry(who, list))) { + int st = msn_ns_write(ic, -1, "RML %d %zd\r\n%s", + ++md->trId, strlen(adl), adl); + g_free(adl); + return st; } - + return 1; } -struct msn_buddy_ask_data -{ +struct msn_buddy_ask_data { struct im_connection *ic; char *handle; char *realname; }; -static void msn_buddy_ask_yes( void *data ) +static void msn_buddy_ask_yes(void *data) { struct msn_buddy_ask_data *bla = data; - - msn_buddy_list_add( bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL ); - - imcb_ask_add( bla->ic, bla->handle, NULL ); - - g_free( bla->handle ); - g_free( bla->realname ); - g_free( bla ); + + msn_buddy_list_add(bla->ic, MSN_BUDDY_AL, bla->handle, bla->realname, NULL); + + imcb_ask_add(bla->ic, bla->handle, NULL); + + g_free(bla->handle); + g_free(bla->realname); + g_free(bla); } -static void msn_buddy_ask_no( void *data ) +static void msn_buddy_ask_no(void *data) { struct msn_buddy_ask_data *bla = data; - - msn_buddy_list_add( bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL ); - - g_free( bla->handle ); - g_free( bla->realname ); - g_free( bla ); + + msn_buddy_list_add(bla->ic, MSN_BUDDY_BL, bla->handle, bla->realname, NULL); + + g_free(bla->handle); + g_free(bla->realname); + g_free(bla); } -void msn_buddy_ask( bee_user_t *bu ) +void msn_buddy_ask(bee_user_t *bu) { struct msn_buddy_ask_data *bla; struct msn_buddy_data *bd = bu->data; char buf[1024]; - - if( !( bd->flags & MSN_BUDDY_PL ) ) + + if (!(bd->flags & MSN_BUDDY_PL)) { return; - - bla = g_new0( struct msn_buddy_ask_data, 1 ); + } + + bla = g_new0(struct msn_buddy_ask_data, 1); bla->ic = bu->ic; - bla->handle = g_strdup( bu->handle ); - bla->realname = g_strdup( bu->fullname ); - - g_snprintf( buf, sizeof( buf ), - "The user %s (%s) wants to add you to his/her buddy list.", - bu->handle, bu->fullname ); - imcb_ask( bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no ); + bla->handle = g_strdup(bu->handle); + bla->realname = g_strdup(bu->fullname); + + g_snprintf(buf, sizeof(buf), + "The user %s (%s) wants to add you to his/her buddy list.", + bu->handle, bu->fullname); + imcb_ask(bu->ic, buf, bla, msn_buddy_ask_yes, msn_buddy_ask_no); } /* *NOT* thread-safe, but that's not a problem for now... */ -char **msn_linesplit( char *line ) +char **msn_linesplit(char *line) { static char **ret = NULL; static int size = 3; int i, n = 0; - - if( ret == NULL ) - ret = g_new0( char*, size ); - - for( i = 0; line[i] && line[i] == ' '; i ++ ); - if( line[i] ) - { + + if (ret == NULL) { + ret = g_new0(char*, size); + } + + for (i = 0; line[i] && line[i] == ' '; i++) { + ; + } + if (line[i]) { ret[n++] = line + i; - for( i ++; line[i]; i ++ ) - { - if( line[i] == ' ' ) + for (i++; line[i]; i++) { + if (line[i] == ' ') { line[i] = 0; - else if( line[i] != ' ' && !line[i-1] ) + } else if (line[i] != ' ' && !line[i - 1]) { ret[n++] = line + i; - - if( n >= size ) - ret = g_renew( char*, ret, size += 2 ); + } + + if (n >= size) { + ret = g_renew(char*, ret, size += 2); + } } } ret[n] = NULL; - - return( ret ); + + return(ret); } /* This one handles input from a MSN Messenger server. Both the NS and SB servers usually give @@ -258,152 +259,154 @@ char **msn_linesplit( char *line ) 0: Command reported error; Abort *immediately*. (The connection does not exist anymore) 1: OK */ -int msn_handler( struct msn_handler_data *h ) +int msn_handler(struct msn_handler_data *h) { int st; - - h->rxq = g_renew( char, h->rxq, h->rxlen + 1024 ); - st = read( h->fd, h->rxq + h->rxlen, 1024 ); + + h->rxq = g_renew(char, h->rxq, h->rxlen + 1024); + st = read(h->fd, h->rxq + h->rxlen, 1024); h->rxlen += st; - - if( st <= 0 ) - return( -1 ); - - if( getenv( "BITLBEE_DEBUG" ) ) - { - write( 2, "->C:", 4 ); - write( 2, h->rxq + h->rxlen - st, st ); + + if (st <= 0) { + return(-1); + } + + if (getenv("BITLBEE_DEBUG")) { + write(2, "->C:", 4); + write(2, h->rxq + h->rxlen - st, st); } - - while( st ) - { + + while (st) { int i; - - if( h->msglen == 0 ) - { - for( i = 0; i < h->rxlen; i ++ ) - { - if( h->rxq[i] == '\r' || h->rxq[i] == '\n' ) - { + + if (h->msglen == 0) { + for (i = 0; i < h->rxlen; i++) { + if (h->rxq[i] == '\r' || h->rxq[i] == '\n') { char *cmd_text, **cmd; int count; - - cmd_text = g_strndup( h->rxq, i ); - cmd = msn_linesplit( cmd_text ); - for( count = 0; cmd[count]; count ++ ); - st = h->exec_command( h, cmd, count ); - g_free( cmd_text ); - + + cmd_text = g_strndup(h->rxq, i); + cmd = msn_linesplit(cmd_text); + for (count = 0; cmd[count]; count++) { + ; + } + st = h->exec_command(h, cmd, count); + g_free(cmd_text); + /* If the connection broke, don't continue. We don't even exist anymore. */ - if( !st ) - return( 0 ); - - if( h->msglen ) - h->cmd_text = g_strndup( h->rxq, i ); - + if (!st) { + return(0); + } + + if (h->msglen) { + h->cmd_text = g_strndup(h->rxq, i); + } + /* Skip to the next non-emptyline */ - while( i < h->rxlen && ( h->rxq[i] == '\r' || h->rxq[i] == '\n' ) ) i ++; - + while (i < h->rxlen && (h->rxq[i] == '\r' || h->rxq[i] == '\n')) { + i++; + } + break; } } - + /* If we reached the end of the buffer, there's still an incomplete command there. Return and wait for more data. */ - if( i == h->rxlen && h->rxq[i-1] != '\r' && h->rxq[i-1] != '\n' ) + if (i == h->rxlen && h->rxq[i - 1] != '\r' && h->rxq[i - 1] != '\n') { break; - } - else - { + } + } else { char *msg, **cmd; int count; - + /* Do we have the complete message already? */ - if( h->msglen > h->rxlen ) + if (h->msglen > h->rxlen) { break; - - msg = g_strndup( h->rxq, h->msglen ); - cmd = msn_linesplit( h->cmd_text ); - for( count = 0; cmd[count]; count ++ ); - - st = h->exec_message( h, msg, h->msglen, cmd, count ); - g_free( msg ); - g_free( h->cmd_text ); + } + + msg = g_strndup(h->rxq, h->msglen); + cmd = msn_linesplit(h->cmd_text); + for (count = 0; cmd[count]; count++) { + ; + } + + st = h->exec_message(h, msg, h->msglen, cmd, count); + g_free(msg); + g_free(h->cmd_text); h->cmd_text = NULL; - - if( !st ) - return( 0 ); - + + if (!st) { + return(0); + } + i = h->msglen; h->msglen = 0; } - + /* More data after this block? */ - if( i < h->rxlen ) - { + if (i < h->rxlen) { char *tmp; - - tmp = g_memdup( h->rxq + i, h->rxlen - i ); - g_free( h->rxq ); + + tmp = g_memdup(h->rxq + i, h->rxlen - i); + g_free(h->rxq); h->rxq = tmp; h->rxlen -= i; i = 0; - } - else - /* If not, reset the rx queue and get lost. */ - { - g_free( h->rxq ); - h->rxq = g_new0( char, 1 ); + } else { + /* If not, reset the rx queue and get lost. */ + g_free(h->rxq); + h->rxq = g_new0(char, 1); h->rxlen = 0; - return( 1 ); + return(1); } } - - return( 1 ); + + return(1); } -void msn_msgq_purge( struct im_connection *ic, GSList **list ) +void msn_msgq_purge(struct im_connection *ic, GSList **list) { struct msn_message *m; GString *ret; GSList *l; int n = 0; - + l = *list; - if( l == NULL ) + if (l == NULL) { return; - + } + m = l->data; - ret = g_string_sized_new( 1024 ); - g_string_printf( ret, "Warning: Cleaning up MSN (switchboard) connection with unsent " - "messages to %s:", m->who ? m->who : "unknown recipient" ); - - while( l ) - { + ret = g_string_sized_new(1024); + g_string_printf(ret, "Warning: Cleaning up MSN (switchboard) connection with unsent " + "messages to %s:", m->who ? m->who : "unknown recipient"); + + while (l) { m = l->data; - - if( strncmp( m->text, "\r\r\r", 3 ) != 0 ) - { - g_string_append_printf( ret, "\n%s", m->text ); - n ++; + + if (strncmp(m->text, "\r\r\r", 3) != 0) { + g_string_append_printf(ret, "\n%s", m->text); + n++; } - - g_free( m->who ); - g_free( m->text ); - g_free( m ); - + + g_free(m->who); + g_free(m->text); + g_free(m); + l = l->next; } - g_slist_free( *list ); + g_slist_free(*list); *list = NULL; - - if( n > 0 ) - imcb_log( ic, "%s", ret->str ); - g_string_free( ret, TRUE ); + + if (n > 0) { + imcb_log(ic, "%s", ret->str); + } + g_string_free(ret, TRUE); } /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ -char *msn_p11_challenge( char *challenge ) +char *msn_p11_challenge(char *challenge) { char *output, buf[256]; md5_state_t md5c; @@ -414,126 +417,133 @@ char *msn_p11_challenge( char *challenge ) /* Create the MD5 hash */ md5_init(&md5c); - md5_append(&md5c, (unsigned char*) challenge, strlen(challenge)); - md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY)); + md5_append(&md5c, (unsigned char *) challenge, strlen(challenge)); + md5_append(&md5c, (unsigned char *) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY)); md5_finish(&md5c, md5Hash); /* Split it into four integers */ - md5Parts = (unsigned int *)md5Hash; - for (i = 0; i < 4; i ++) - { + md5Parts = (unsigned int *) md5Hash; + for (i = 0; i < 4; i++) { md5Parts[i] = GUINT32_TO_LE(md5Parts[i]); - + /* & each integer with 0x7FFFFFFF */ /* and save one unmodified array for later */ newHashParts[i] = md5Parts[i]; md5Parts[i] &= 0x7FFFFFFF; } - + /* make a new string and pad with '0' */ - n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID); + n = g_snprintf(buf, sizeof(buf) - 5, "%s%s00000000", challenge, MSNP11_PROD_ID); /* truncate at an 8-byte boundary */ - buf[n&=~7] = '\0'; - + buf[n &= ~7] = '\0'; + /* split into integers */ - chlStringParts = (unsigned int *)buf; - + chlStringParts = (unsigned int *) buf; + /* this is magic */ - for (i = 0; i < (n / 4) - 1; i += 2) - { + for (i = 0; i < (n / 4) - 1; i += 2) { long long temp; chlStringParts[i] = GUINT32_TO_LE(chlStringParts[i]); - chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]); + chlStringParts[i + 1] = GUINT32_TO_LE(chlStringParts[i + 1]); - temp = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; - nHigh = (md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; + temp = + (md5Parts[0] * + (((0x0E79A9C1 * + (long long) chlStringParts[i]) % 0x7FFFFFFF) + nHigh) + md5Parts[1]) % 0x7FFFFFFF; + nHigh = + (md5Parts[2] * + (((long long) chlStringParts[i + 1] + temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; nLow = nLow + nHigh + temp; } - nHigh = (nHigh+md5Parts[1]) % 0x7FFFFFFF; - nLow = (nLow+md5Parts[3]) % 0x7FFFFFFF; - + nHigh = (nHigh + md5Parts[1]) % 0x7FFFFFFF; + nLow = (nLow + md5Parts[3]) % 0x7FFFFFFF; + newHashParts[0] ^= nHigh; newHashParts[1] ^= nLow; newHashParts[2] ^= nHigh; newHashParts[3] ^= nLow; - + /* swap more bytes if big endian */ - for (i = 0; i < 4; i ++) - newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); - + for (i = 0; i < 4; i++) { + newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); + } + /* make a string of the parts */ - newHash = (unsigned char *)newHashParts; - + newHash = (unsigned char *) newHashParts; + /* convert to hexadecimal */ output = g_new(char, 33); - for (i = 0; i < 16; i ++) + for (i = 0; i < 16; i++) { sprintf(output + i * 2, "%02x", newHash[i]); - + } + return output; } -gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) +gint msn_domaintree_cmp(gconstpointer a_, gconstpointer b_) { const char *a = a_, *b = b_; gint ret; - - if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) || - ( ret = strcmp( a, b ) ) == 0 ) - ret = strcmp( a_, b_ ); - + + if (!(a = strchr(a, '@')) || !(b = strchr(b, '@')) || + (ret = strcmp(a, b)) == 0) { + ret = strcmp(a_, b_); + } + return ret; } -struct msn_group *msn_group_by_name( struct im_connection *ic, const char *name ) +struct msn_group *msn_group_by_name(struct im_connection *ic, const char *name) { struct msn_data *md = ic->proto_data; GSList *l; - - for( l = md->groups; l; l = l->next ) - { + + for (l = md->groups; l; l = l->next) { struct msn_group *mg = l->data; - - if( g_strcasecmp( mg->name, name ) == 0 ) + + if (g_strcasecmp(mg->name, name) == 0) { return mg; + } } - + return NULL; } -struct msn_group *msn_group_by_id( struct im_connection *ic, const char *id ) +struct msn_group *msn_group_by_id(struct im_connection *ic, const char *id) { struct msn_data *md = ic->proto_data; GSList *l; - - for( l = md->groups; l; l = l->next ) - { + + for (l = md->groups; l; l = l->next) { struct msn_group *mg = l->data; - - if( g_strcasecmp( mg->id, id ) == 0 ) + + if (g_strcasecmp(mg->id, id) == 0) { return mg; + } } - + return NULL; } -int msn_ns_set_display_name( struct im_connection *ic, const char *value ) +int msn_ns_set_display_name(struct im_connection *ic, const char *value) { struct msn_data *md = ic->proto_data; - char fn[strlen(value)*3+1]; - - strcpy( fn, value ); - http_encode( fn ); - + char fn[strlen(value) * 3 + 1]; + + strcpy(fn, value); + http_encode(fn); + /* Note: We don't actually know if the server accepted the new name, and won't give proper feedback yet if it doesn't. */ - return msn_ns_write( ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn ); + return msn_ns_write(ic, -1, "PRP %d MFN %s\r\n", ++md->trId, fn); } -const char *msn_normalize_handle( const char *handle ) +const char *msn_normalize_handle(const char *handle) { - if( strncmp( handle, "1:", 2 ) == 0 ) + if (strncmp(handle, "1:", 2) == 0) { return handle + 2; - else + } else { return handle; + } } diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 7646e237..f6c553a8 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -32,849 +32,753 @@ #include "soap.h" #include "xmltree.h" -static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); -static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); -static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ); -static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ); +static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond); +static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond); +static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts); +static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts); -static void msn_ns_send_adl_start( struct im_connection *ic ); -static void msn_ns_send_adl( struct im_connection *ic ); +static void msn_ns_send_adl_start(struct im_connection *ic); +static void msn_ns_send_adl(struct im_connection *ic); -int msn_ns_write( struct im_connection *ic, int fd, const char *fmt, ... ) +int msn_ns_write(struct im_connection *ic, int fd, const char *fmt, ...) { struct msn_data *md = ic->proto_data; va_list params; char *out; size_t len; int st; - - va_start( params, fmt ); - out = g_strdup_vprintf( fmt, params ); - va_end( params ); - - if( fd < 0 ) + + va_start(params, fmt); + out = g_strdup_vprintf(fmt, params); + va_end(params); + + if (fd < 0) { fd = md->ns->fd; - - if( getenv( "BITLBEE_DEBUG" ) ) - fprintf( stderr, "->NS%d:%s\n", fd, out ); - - len = strlen( out ); - st = write( fd, out, len ); - g_free( out ); - if( st != len ) - { - imcb_error( ic, "Short write() to main server" ); - imc_logout( ic, TRUE ); + } + + if (getenv("BITLBEE_DEBUG")) { + fprintf(stderr, "->NS%d:%s\n", fd, out); + } + + len = strlen(out); + st = write(fd, out, len); + g_free(out); + if (st != len) { + imcb_error(ic, "Short write() to main server"); + imc_logout(ic, TRUE); return 0; } - + return 1; } -gboolean msn_ns_connect( struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port ) +gboolean msn_ns_connect(struct im_connection *ic, struct msn_handler_data *handler, const char *host, int port) { - if( handler->fd >= 0 ) - closesocket( handler->fd ); - + if (handler->fd >= 0) { + closesocket(handler->fd); + } + handler->exec_command = msn_ns_command; handler->exec_message = msn_ns_message; handler->data = ic; - handler->fd = proxy_connect( host, port, msn_ns_connected, handler ); - if( handler->fd < 0 ) - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); + handler->fd = proxy_connect(host, port, msn_ns_connected, handler); + if (handler->fd < 0) { + imcb_error(ic, "Could not connect to server"); + imc_logout(ic, TRUE); return FALSE; } - + return TRUE; } -static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) +static gboolean msn_ns_connected(gpointer data, gint source, b_input_condition cond) { struct msn_handler_data *handler = data; struct im_connection *ic = handler->data; struct msn_data *md; - - if( !g_slist_find( msn_connections, ic ) ) + + if (!g_slist_find(msn_connections, ic)) { return FALSE; - + } + md = ic->proto_data; - - if( source == -1 ) - { - imcb_error( ic, "Could not connect to server" ); - imc_logout( ic, TRUE ); + + if (source == -1) { + imcb_error(ic, "Could not connect to server"); + imc_logout(ic, TRUE); return FALSE; } - - g_free( handler->rxq ); + + g_free(handler->rxq); handler->rxlen = 0; - handler->rxq = g_new0( char, 1 ); - - if( md->uuid == NULL ) - { + handler->rxq = g_new0(char, 1); + + if (md->uuid == NULL) { struct utsname name; sha1_state_t sha[1]; - + /* UUID == SHA1("BitlBee" + my hostname + MSN username) */ - sha1_init( sha ); - sha1_append( sha, (void*) "BitlBee", 7 ); - if( uname( &name ) == 0 ) - { - sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) ); + sha1_init(sha); + sha1_append(sha, (void *) "BitlBee", 7); + if (uname(&name) == 0) { + sha1_append(sha, (void *) name.nodename, strlen(name.nodename)); } - sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) ); - md->uuid = sha1_random_uuid( sha ); - memcpy( md->uuid, "b171be3e", 8 ); /* :-P */ + sha1_append(sha, (void *) ic->acc->user, strlen(ic->acc->user)); + md->uuid = sha1_random_uuid(sha); + memcpy(md->uuid, "b171be3e", 8); /* :-P */ } - - if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) ) - { - handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler ); - imcb_log( ic, "Connected to server, waiting for reply" ); + + if (msn_ns_write(ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER)) { + handler->inpa = b_input_add(handler->fd, B_EV_IO_READ, msn_ns_callback, handler); + imcb_log(ic, "Connected to server, waiting for reply"); } - + return FALSE; } -void msn_ns_close( struct msn_handler_data *handler ) +void msn_ns_close(struct msn_handler_data *handler) { - if( handler->fd >= 0 ) - { - closesocket( handler->fd ); - b_event_remove( handler->inpa ); + if (handler->fd >= 0) { + closesocket(handler->fd); + b_event_remove(handler->inpa); } - + handler->fd = handler->inpa = -1; - g_free( handler->rxq ); - g_free( handler->cmd_text ); - + g_free(handler->rxq); + g_free(handler->cmd_text); + handler->rxlen = 0; handler->rxq = NULL; handler->cmd_text = NULL; } -static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ) +static gboolean msn_ns_callback(gpointer data, gint source, b_input_condition cond) { struct msn_handler_data *handler = data; struct im_connection *ic = handler->data; - - if( msn_handler( handler ) == -1 ) /* Don't do this on ret == 0, it's already done then. */ - { - imcb_error( ic, "Error while reading from server" ); - imc_logout( ic, TRUE ); - + + if (msn_handler(handler) == -1) { /* Don't do this on ret == 0, it's already done then. */ + imcb_error(ic, "Error while reading from server"); + imc_logout(ic, TRUE); + return FALSE; - } - else + } else { return TRUE; + } } -static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts ) +static int msn_ns_command(struct msn_handler_data *handler, char **cmd, int num_parts) { struct im_connection *ic = handler->data; struct msn_data *md = ic->proto_data; - - if( num_parts == 0 ) - { + + if (num_parts == 0) { /* Hrrm... Empty command...? Ignore? */ - return( 1 ); + return(1); } - - if( strcmp( cmd[0], "VER" ) == 0 ) - { - if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 ) - { - imcb_error( ic, "Unsupported protocol" ); - imc_logout( ic, FALSE ); - return( 0 ); + + if (strcmp(cmd[0], "VER") == 0) { + if (cmd[2] && strncmp(cmd[2], MSNP_VER, 5) != 0) { + imcb_error(ic, "Unsupported protocol"); + imc_logout(ic, FALSE); + return(0); } - - return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", - ++md->trId, ic->acc->user ) ); - } - else if( strcmp( cmd[0], "CVR" ) == 0 ) - { + + return(msn_ns_write(ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n", + ++md->trId, ic->acc->user)); + } else if (strcmp(cmd[0], "CVR") == 0) { /* We don't give a damn about the information we just received */ - return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); - } - else if( strcmp( cmd[0], "XFR" ) == 0 ) - { + return msn_ns_write(ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user); + } else if (strcmp(cmd[0], "XFR") == 0) { char *server; int port; - - if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) - { - b_event_remove( handler->inpa ); + + if (num_parts >= 6 && strcmp(cmd[2], "NS") == 0) { + b_event_remove(handler->inpa); handler->inpa = -1; - - server = strchr( cmd[3], ':' ); - if( !server ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + server = strchr(cmd[3], ':'); + if (!server) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } *server = 0; - port = atoi( server + 1 ); + port = atoi(server + 1); server = cmd[3]; - - imcb_log( ic, "Transferring to other server" ); - return msn_ns_connect( ic, handler, server, port ); - } - else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) - { + + imcb_log(ic, "Transferring to other server"); + return msn_ns_connect(ic, handler, server, port); + } else if (num_parts >= 6 && strcmp(cmd[2], "SB") == 0) { struct msn_switchboard *sb; - - server = strchr( cmd[3], ':' ); - if( !server ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + server = strchr(cmd[3], ':'); + if (!server) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } *server = 0; - port = atoi( server + 1 ); + port = atoi(server + 1); server = cmd[3]; - - if( strcmp( cmd[4], "CKI" ) != 0 ) - { - imcb_error( ic, "Unknown authentication method for switchboard" ); - imc_logout( ic, TRUE ); - return( 0 ); + + if (strcmp(cmd[4], "CKI") != 0) { + imcb_error(ic, "Unknown authentication method for switchboard"); + imc_logout(ic, TRUE); + return(0); } - - debug( "Connecting to a new switchboard with key %s", cmd[5] ); - if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL ) - { + debug("Connecting to a new switchboard with key %s", cmd[5]); + + if ((sb = msn_sb_create(ic, server, port, cmd[5], MSN_SB_NEW)) == NULL) { /* Although this isn't strictly fatal for the NS connection, it's definitely something serious (we ran out of file descriptors?). */ - imcb_error( ic, "Could not create new switchboard" ); - imc_logout( ic, TRUE ); - return( 0 ); + imcb_error(ic, "Could not create new switchboard"); + imc_logout(ic, TRUE); + return(0); } - - if( md->msgq ) - { + + if (md->msgq) { struct msn_message *m = md->msgq->data; GSList *l; - - sb->who = g_strdup( m->who ); - + + sb->who = g_strdup(m->who); + /* Move all the messages to the first user in the message queue to the switchboard message queue. */ l = md->msgq; - while( l ) - { + while (l) { m = l->data; l = l->next; - if( strcmp( m->who, sb->who ) == 0 ) - { - sb->msgq = g_slist_append( sb->msgq, m ); - md->msgq = g_slist_remove( md->msgq, m ); + if (strcmp(m->who, sb->who) == 0) { + sb->msgq = g_slist_append(sb->msgq, m); + md->msgq = g_slist_remove(md->msgq, m); } } } - } - else - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - } - else if( strcmp( cmd[0], "USR" ) == 0 ) - { - if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && - strcmp( cmd[3], "S" ) == 0 ) - { - g_free( md->pp_policy ); - md->pp_policy = g_strdup( cmd[4] ); - msn_soap_passport_sso_request( ic, cmd[5] ); - } - else if( strcmp( cmd[2], "OK" ) == 0 ) - { + } else { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); + } + } else if (strcmp(cmd[0], "USR") == 0) { + if (num_parts >= 6 && strcmp(cmd[2], "SSO") == 0 && + strcmp(cmd[3], "S") == 0) { + g_free(md->pp_policy); + md->pp_policy = g_strdup(cmd[4]); + msn_soap_passport_sso_request(ic, cmd[5]); + } else if (strcmp(cmd[2], "OK") == 0) { /* If the number after the handle is 0, the e-mail address is unverified, which means we can't change the display name. */ - if( cmd[4][0] == '0' ) + if (cmd[4][0] == '0') { md->flags |= MSN_EMAIL_UNVERIFIED; - - imcb_log( ic, "Authenticated, getting buddy list" ); - msn_soap_memlist_request( ic ); - } - else - { - imcb_error( ic, "Unknown authentication type" ); - imc_logout( ic, FALSE ); - return( 0 ); - } - } - else if( strcmp( cmd[0], "MSG" ) == 0 ) - { - if( num_parts < 4 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - - handler->msglen = atoi( cmd[3] ); - - if( handler->msglen <= 0 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - } - else if( strcmp( cmd[0], "BLP" ) == 0 ) - { - msn_ns_send_adl_start( ic ); - return msn_ns_finish_login( ic ); - } - else if( strcmp( cmd[0], "ADL" ) == 0 ) - { - if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) - { - msn_ns_send_adl( ic ); - return msn_ns_finish_login( ic ); - } - else if( num_parts >= 3 ) - { - handler->msglen = atoi( cmd[2] ); + } + + imcb_log(ic, "Authenticated, getting buddy list"); + msn_soap_memlist_request(ic); + } else { + imcb_error(ic, "Unknown authentication type"); + imc_logout(ic, FALSE); + return(0); + } + } else if (strcmp(cmd[0], "MSG") == 0) { + if (num_parts < 4) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } - } - else if( strcmp( cmd[0], "PRP" ) == 0 ) - { - imcb_connected( ic ); - } - else if( strcmp( cmd[0], "CHL" ) == 0 ) - { + + handler->msglen = atoi(cmd[3]); + + if (handler->msglen <= 0) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); + } + } else if (strcmp(cmd[0], "BLP") == 0) { + msn_ns_send_adl_start(ic); + return msn_ns_finish_login(ic); + } else if (strcmp(cmd[0], "ADL") == 0) { + if (num_parts >= 3 && strcmp(cmd[2], "OK") == 0) { + msn_ns_send_adl(ic); + return msn_ns_finish_login(ic); + } else if (num_parts >= 3) { + handler->msglen = atoi(cmd[2]); + } + } else if (strcmp(cmd[0], "PRP") == 0) { + imcb_connected(ic); + } else if (strcmp(cmd[0], "CHL") == 0) { char *resp; int st; - - if( num_parts < 3 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + if (num_parts < 3) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } - - resp = msn_p11_challenge( cmd[2] ); - - st = msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s", - ++md->trId, MSNP11_PROD_ID, - strlen( resp ), resp ); - g_free( resp ); + + resp = msn_p11_challenge(cmd[2]); + + st = msn_ns_write(ic, -1, "QRY %d %s %zd\r\n%s", + ++md->trId, MSNP11_PROD_ID, + strlen(resp), resp); + g_free(resp); return st; - } - else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 ) - { + } else if (strcmp(cmd[0], "ILN") == 0 || strcmp(cmd[0], "NLN") == 0) { const struct msn_away_state *st; const char *handle; int cap = 0; - - if( num_parts < 6 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + if (num_parts < 6) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } /* ILN and NLN are more or less the same, except ILN has a trId - at the start, and NLN has a capability field at the end. + at the start, and NLN has a capability field at the end. Does ILN still exist BTW? */ - if( cmd[0][1] == 'I' ) - cmd ++; - else - cap = atoi( cmd[4] ); + if (cmd[0][1] == 'I') { + cmd++; + } else { + cap = atoi(cmd[4]); + } - handle = msn_normalize_handle( cmd[2] ); - if( strcmp( handle, ic->acc->user ) == 0 ) + handle = msn_normalize_handle(cmd[2]); + if (strcmp(handle, ic->acc->user) == 0) { return 1; /* That's me! */ - - http_decode( cmd[3] ); - imcb_rename_buddy( ic, handle, cmd[3] ); - - st = msn_away_state_by_code( cmd[1] ); - if( !st ) - { + + } + http_decode(cmd[3]); + imcb_rename_buddy(ic, handle, cmd[3]); + + st = msn_away_state_by_code(cmd[1]); + if (!st) { /* FIXME: Warn/Bomb about unknown away state? */ st = msn_away_state_list + 1; } - - imcb_buddy_status( ic, handle, OPT_LOGGED_IN | - ( st != msn_away_state_list ? OPT_AWAY : 0 ) | - ( cap & 1 ? OPT_MOBILE : 0 ), - st->name, NULL ); - - msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) ); - } - else if( strcmp( cmd[0], "FLN" ) == 0 ) - { + + imcb_buddy_status(ic, handle, OPT_LOGGED_IN | + (st != msn_away_state_list ? OPT_AWAY : 0) | + (cap & 1 ? OPT_MOBILE : 0), + st->name, NULL); + + msn_sb_stop_keepalives(msn_sb_by_handle(ic, handle)); + } else if (strcmp(cmd[0], "FLN") == 0) { const char *handle; - - if( cmd[1] == NULL ) + + if (cmd[1] == NULL) { return 1; - - handle = msn_normalize_handle( cmd[1] ); - imcb_buddy_status( ic, handle, 0, NULL, NULL ); - msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE ); - } - else if( strcmp( cmd[0], "RNG" ) == 0 ) - { + } + + handle = msn_normalize_handle(cmd[1]); + imcb_buddy_status(ic, handle, 0, NULL, NULL); + msn_sb_start_keepalives(msn_sb_by_handle(ic, handle), TRUE); + } else if (strcmp(cmd[0], "RNG") == 0) { struct msn_switchboard *sb; char *server; int session, port; - - if( num_parts < 7 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + if (num_parts < 7) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } - - session = atoi( cmd[1] ); - - server = strchr( cmd[2], ':' ); - if( !server ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + session = atoi(cmd[1]); + + server = strchr(cmd[2], ':'); + if (!server) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } *server = 0; - port = atoi( server + 1 ); + port = atoi(server + 1); server = cmd[2]; - - if( strcmp( cmd[3], "CKI" ) != 0 ) - { - imcb_error( ic, "Unknown authentication method for switchboard" ); - imc_logout( ic, TRUE ); - return( 0 ); + + if (strcmp(cmd[3], "CKI") != 0) { + imcb_error(ic, "Unknown authentication method for switchboard"); + imc_logout(ic, TRUE); + return(0); } - - debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] ); - - if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL ) - { + + debug("Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4]); + + if ((sb = msn_sb_create(ic, server, port, cmd[4], session)) == NULL) { /* Although this isn't strictly fatal for the NS connection, it's definitely something serious (we ran out of file descriptors?). */ - imcb_error( ic, "Could not create new switchboard" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - else - { - sb->who = g_strdup( msn_normalize_handle( cmd[5] ) ); + imcb_error(ic, "Could not create new switchboard"); + imc_logout(ic, TRUE); + return(0); + } else { + sb->who = g_strdup(msn_normalize_handle(cmd[5])); } - } - else if( strcmp( cmd[0], "OUT" ) == 0 ) - { + } else if (strcmp(cmd[0], "OUT") == 0) { int allow_reconnect = TRUE; - - if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 ) - { - imcb_error( ic, "Someone else logged in with your account" ); + + if (cmd[1] && strcmp(cmd[1], "OTH") == 0) { + imcb_error(ic, "Someone else logged in with your account"); allow_reconnect = FALSE; + } else if (cmd[1] && strcmp(cmd[1], "SSD") == 0) { + imcb_error(ic, "Terminating session because of server shutdown"); + } else { + imcb_error(ic, "Session terminated by remote server (%s)", + cmd[1] ? cmd[1] : "reason unknown)"); } - else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 ) - { - imcb_error( ic, "Terminating session because of server shutdown" ); - } - else - { - imcb_error( ic, "Session terminated by remote server (%s)", - cmd[1] ? cmd[1] : "reason unknown)" ); - } - - imc_logout( ic, allow_reconnect ); - return( 0 ); - } - else if( strcmp( cmd[0], "IPG" ) == 0 ) - { - imcb_error( ic, "Received IPG command, we don't handle them yet." ); - - handler->msglen = atoi( cmd[1] ); - - if( handler->msglen <= 0 ) - { - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); - return( 0 ); + + imc_logout(ic, allow_reconnect); + return(0); + } else if (strcmp(cmd[0], "IPG") == 0) { + imcb_error(ic, "Received IPG command, we don't handle them yet."); + + handler->msglen = atoi(cmd[1]); + + if (handler->msglen <= 0) { + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); + return(0); } } #if 0 - else if( strcmp( cmd[0], "ADG" ) == 0 ) - { - char *group = g_strdup( cmd[3] ); + else if (strcmp(cmd[0], "ADG") == 0) { + char *group = g_strdup(cmd[3]); int groupnum, i; GSList *l, *next; - - http_decode( group ); - if( sscanf( cmd[4], "%d", &groupnum ) == 1 ) - { - if( groupnum >= md->groupcount ) - { - md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 ); - for( i = md->groupcount; i <= groupnum; i ++ ) + + http_decode(group); + if (sscanf(cmd[4], "%d", &groupnum) == 1) { + if (groupnum >= md->groupcount) { + md->grouplist = g_renew(char *, md->grouplist, groupnum + 1); + for (i = md->groupcount; i <= groupnum; i++) { md->grouplist[i] = NULL; + } md->groupcount = groupnum + 1; } - g_free( md->grouplist[groupnum] ); + g_free(md->grouplist[groupnum]); md->grouplist[groupnum] = group; - } - else - { + } else { /* Shouldn't happen, but if it does, give up on the group. */ - g_free( group ); - imcb_error( ic, "Syntax error" ); - imc_logout( ic, TRUE ); + g_free(group); + imcb_error(ic, "Syntax error"); + imc_logout(ic, TRUE); return 0; } - - for( l = md->grpq; l; l = next ) - { + + for (l = md->grpq; l; l = next) { struct msn_groupadd *ga = l->data; next = l->next; - if( g_strcasecmp( ga->group, group ) == 0 ) - { - if( !msn_buddy_list_add( ic, "FL", ga->who, ga->who, group ) ) + if (g_strcasecmp(ga->group, group) == 0) { + if (!msn_buddy_list_add(ic, "FL", ga->who, ga->who, group)) { return 0; - - g_free( ga->group ); - g_free( ga->who ); - g_free( ga ); - md->grpq = g_slist_remove( md->grpq, ga ); + } + + g_free(ga->group); + g_free(ga->who); + g_free(ga); + md->grpq = g_slist_remove(md->grpq, ga); } } } #endif - else if( strcmp( cmd[0], "GCF" ) == 0 ) - { + else if (strcmp(cmd[0], "GCF") == 0) { /* Coming up is cmd[2] bytes of stuff we're supposed to censore. Meh. */ - handler->msglen = atoi( cmd[2] ); - } - else if( strcmp( cmd[0], "UBX" ) == 0 ) - { + handler->msglen = atoi(cmd[2]); + } else if (strcmp(cmd[0], "UBX") == 0) { /* Status message. */ - if( num_parts >= 3 ) - handler->msglen = atoi( cmd[2] ); - } - else if( strcmp( cmd[0], "NOT" ) == 0 ) - { + if (num_parts >= 3) { + handler->msglen = atoi(cmd[2]); + } + } else if (strcmp(cmd[0], "NOT") == 0) { /* Some kind of notification, poorly documented but apparently used to announce address book changes. */ - if( num_parts >= 2 ) - handler->msglen = atoi( cmd[1] ); - } - else if( strcmp( cmd[0], "UBM" ) == 0 ) - { - if( num_parts >= 7 ) - handler->msglen = atoi( cmd[6] ); - } - else if( strcmp( cmd[0], "QNG" ) == 0 ) - { + if (num_parts >= 2) { + handler->msglen = atoi(cmd[1]); + } + } else if (strcmp(cmd[0], "UBM") == 0) { + if (num_parts >= 7) { + handler->msglen = atoi(cmd[6]); + } + } else if (strcmp(cmd[0], "QNG") == 0) { ic->flags |= OPT_PONGED; - } - else if( g_ascii_isdigit( cmd[0][0] ) ) - { - int num = atoi( cmd[0] ); - const struct msn_status_code *err = msn_status_by_number( num ); - - imcb_error( ic, "Error reported by MSN server: %s", err->text ); - - if( err->flags & STATUS_FATAL ) - { - imc_logout( ic, TRUE ); - return( 0 ); + } else if (g_ascii_isdigit(cmd[0][0])) { + int num = atoi(cmd[0]); + const struct msn_status_code *err = msn_status_by_number(num); + + imcb_error(ic, "Error reported by MSN server: %s", err->text); + + if (err->flags & STATUS_FATAL) { + imc_logout(ic, TRUE); + return(0); } - + /* Oh yes, errors can have payloads too now. Discard them for now. */ - if( num_parts >= 3 ) - handler->msglen = atoi( cmd[2] ); - } - else - { + if (num_parts >= 3) { + handler->msglen = atoi(cmd[2]); + } + } else { /* debug( "Received unknown command from main server: %s", cmd[0] ); */ } - - return( 1 ); + + return(1); } -static int msn_ns_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ) +static int msn_ns_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts) { struct im_connection *ic = handler->data; char *body; int blen = 0; - - if( !num_parts ) - return( 1 ); - - if( ( body = strstr( msg, "\r\n\r\n" ) ) ) - { + + if (!num_parts) { + return(1); + } + + if ((body = strstr(msg, "\r\n\r\n"))) { body += 4; - blen = msglen - ( body - msg ); + blen = msglen - (body - msg); } - - if( strcmp( cmd[0], "MSG" ) == 0 ) - { - if( g_strcasecmp( cmd[1], "Hotmail" ) == 0 ) - { - char *ct = get_rfc822_header( msg, "Content-Type:", msglen ); - - if( !ct ) - return( 1 ); - - if( g_strncasecmp( ct, "application/x-msmsgssystemmessage", 33 ) == 0 ) - { + + if (strcmp(cmd[0], "MSG") == 0) { + if (g_strcasecmp(cmd[1], "Hotmail") == 0) { + char *ct = get_rfc822_header(msg, "Content-Type:", msglen); + + if (!ct) { + return(1); + } + + if (g_strncasecmp(ct, "application/x-msmsgssystemmessage", 33) == 0) { char *mtype; char *arg1; - - if( !body ) - return( 1 ); - - mtype = get_rfc822_header( body, "Type:", blen ); - arg1 = get_rfc822_header( body, "Arg1:", blen ); - - if( mtype && strcmp( mtype, "1" ) == 0 ) - { - if( arg1 ) - imcb_log( ic, "The server is going down for maintenance in %s minutes.", arg1 ); + + if (!body) { + return(1); } - - g_free( arg1 ); - g_free( mtype ); - } - else if( g_strncasecmp( ct, "text/x-msmsgsprofile", 20 ) == 0 ) - { + + mtype = get_rfc822_header(body, "Type:", blen); + arg1 = get_rfc822_header(body, "Arg1:", blen); + + if (mtype && strcmp(mtype, "1") == 0) { + if (arg1) { + imcb_log(ic, "The server is going down for maintenance in %s minutes.", + arg1); + } + } + + g_free(arg1); + g_free(mtype); + } else if (g_strncasecmp(ct, "text/x-msmsgsprofile", 20) == 0) { /* We don't care about this profile for now... */ - } - else if( g_strncasecmp( ct, "text/x-msmsgsinitialemailnotification", 37 ) == 0 ) - { - if( set_getbool( &ic->acc->set, "mail_notifications" ) ) - { - char *inbox = get_rfc822_header( body, "Inbox-Unread:", blen ); - char *folders = get_rfc822_header( body, "Folders-Unread:", blen ); - - if( inbox && folders ) - imcb_log( ic, "INBOX contains %s new messages, plus %s messages in other folders.", inbox, folders ); - - g_free( inbox ); - g_free( folders ); + } else if (g_strncasecmp(ct, "text/x-msmsgsinitialemailnotification", 37) == 0) { + if (set_getbool(&ic->acc->set, "mail_notifications")) { + char *inbox = get_rfc822_header(body, "Inbox-Unread:", blen); + char *folders = get_rfc822_header(body, "Folders-Unread:", blen); + + if (inbox && folders) { + imcb_log(ic, + "INBOX contains %s new messages, plus %s messages in other folders.", inbox, + folders); + } + + g_free(inbox); + g_free(folders); } - } - else if( g_strncasecmp( ct, "text/x-msmsgsemailnotification", 30 ) == 0 ) - { - if( set_getbool( &ic->acc->set, "mail_notifications" ) ) - { - char *from = get_rfc822_header( body, "From-Addr:", blen ); - char *fromname = get_rfc822_header( body, "From:", blen ); - - if( from && fromname ) - imcb_log( ic, "Received an e-mail message from %s <%s>.", fromname, from ); - - g_free( from ); - g_free( fromname ); + } else if (g_strncasecmp(ct, "text/x-msmsgsemailnotification", 30) == 0) { + if (set_getbool(&ic->acc->set, "mail_notifications")) { + char *from = get_rfc822_header(body, "From-Addr:", blen); + char *fromname = get_rfc822_header(body, "From:", blen); + + if (from && fromname) { + imcb_log(ic, "Received an e-mail message from %s <%s>.", fromname, + from); + } + + g_free(from); + g_free(fromname); } - } - else if( g_strncasecmp( ct, "text/x-msmsgsactivemailnotification", 35 ) == 0 ) - { - } - else if( g_strncasecmp( ct, "text/x-msmsgsinitialmdatanotification", 37 ) == 0 || - g_strncasecmp( ct, "text/x-msmsgsoimnotification", 28 ) == 0 ) - { + } else if (g_strncasecmp(ct, "text/x-msmsgsactivemailnotification", 35) == 0) { + } else if (g_strncasecmp(ct, "text/x-msmsgsinitialmdatanotification", 37) == 0 || + g_strncasecmp(ct, "text/x-msmsgsoimnotification", 28) == 0) { /* We received an offline message. Or at least notification that there is one waiting for us. Fetching the message(s) and purging them from the server is a lot of SOAPy work not worth doing IMHO. Also I thought it was possible to have the notification server send them directly, I was pretty sure I saw Pidgin do it.. - + At least give a notification for now, seems like a reasonable thing to do. Only problem is, they'll keep coming back at login time until you read them using a different client. :-( */ - - char *xml = get_rfc822_header( body, "Mail-Data:", blen ); + + char *xml = get_rfc822_header(body, "Mail-Data:", blen); struct xt_node *md, *m; - - if( !xml ) + + if (!xml) { return 1; - md = xt_from_string( xml, 0 ); - if( !md ) + } + md = xt_from_string(xml, 0); + if (!md) { return 1; - - for( m = md->children; ( m = xt_find_node( m, "M" ) ); m = m->next ) - { - struct xt_node *e = xt_find_node( m->children, "E" ); - struct xt_node *rt = xt_find_node( m->children, "RT" ); + } + + for (m = md->children; (m = xt_find_node(m, "M")); m = m->next) { + struct xt_node *e = xt_find_node(m->children, "E"); + struct xt_node *rt = xt_find_node(m->children, "RT"); struct tm tp; time_t msgtime = 0; - - if( !e || !e->text ) + + if (!e || !e->text) { continue; - - memset( &tp, 0, sizeof( tp ) ); - if( rt && rt->text && - sscanf( rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", - &tp.tm_year, &tp.tm_mon, &tp.tm_mday, - &tp.tm_hour, &tp.tm_min, &tp.tm_sec ) == 6 ) - { + } + + memset(&tp, 0, sizeof(tp)); + if (rt && rt->text && + sscanf(rt->text, "%4d-%2d-%2dT%2d:%2d:%2d.", + &tp.tm_year, &tp.tm_mon, &tp.tm_mday, + &tp.tm_hour, &tp.tm_min, &tp.tm_sec) == 6) { tp.tm_year -= 1900; - tp.tm_mon --; - msgtime = mktime_utc( &tp ); - + tp.tm_mon--; + msgtime = mktime_utc(&tp); + } - imcb_buddy_msg( ic, e->text, "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, msgtime ); + imcb_buddy_msg(ic, e->text, + "<< \002BitlBee\002 - Received offline message. BitlBee can't show these. >>", 0, + msgtime); } - - g_free( xml ); - xt_free_node( md ); - } - else - { - debug( "Can't handle %s packet from notification server", ct ); + + g_free(xml); + xt_free_node(md); + } else { + debug("Can't handle %s packet from notification server", ct); } - - g_free( ct ); + + g_free(ct); } - } - else if( strcmp( cmd[0], "UBX" ) == 0 ) - { + } else if (strcmp(cmd[0], "UBX") == 0) { struct xt_node *ubx, *psm; char *psm_text = NULL; - - ubx = xt_from_string( msg, msglen ); - if( ubx && strcmp( ubx->name, "Data" ) == 0 && - ( psm = xt_find_node( ubx->children, "PSM" ) ) ) + + ubx = xt_from_string(msg, msglen); + if (ubx && strcmp(ubx->name, "Data") == 0 && + (psm = xt_find_node(ubx->children, "PSM"))) { psm_text = psm->text; - - imcb_buddy_status_msg( ic, msn_normalize_handle( cmd[1] ), psm_text ); - xt_free_node( ubx ); - } - else if( strcmp( cmd[0], "ADL" ) == 0 ) - { + } + + imcb_buddy_status_msg(ic, msn_normalize_handle(cmd[1]), psm_text); + xt_free_node(ubx); + } else if (strcmp(cmd[0], "ADL") == 0) { struct xt_node *adl, *d, *c; - - if( !( adl = xt_from_string( msg, msglen ) ) ) + + if (!(adl = xt_from_string(msg, msglen))) { return 1; - - for( d = adl->children; d; d = d->next ) - { + } + + for (d = adl->children; d; d = d->next) { char *dn; - if( strcmp( d->name, "d" ) != 0 || - ( dn = xt_find_attr( d, "n" ) ) == NULL ) + if (strcmp(d->name, "d") != 0 || + (dn = xt_find_attr(d, "n")) == NULL) { continue; - for( c = d->children; c; c = c->next ) - { + } + for (c = d->children; c; c = c->next) { bee_user_t *bu; struct msn_buddy_data *bd; char *cn, *handle, *f, *l; int flags; - - if( strcmp( c->name, "c" ) != 0 || - ( l = xt_find_attr( c, "l" ) ) == NULL || - ( cn = xt_find_attr( c, "n" ) ) == NULL ) + + if (strcmp(c->name, "c") != 0 || + (l = xt_find_attr(c, "l")) == NULL || + (cn = xt_find_attr(c, "n")) == NULL) { continue; - + } + /* FIXME: Use "t" here, guess I should just add it as a prefix like elsewhere in the protocol. */ - handle = g_strdup_printf( "%s@%s", cn, dn ); - if( !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || - ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) - { - g_free( handle ); + handle = g_strdup_printf("%s@%s", cn, dn); + if (!((bu = bee_user_by_handle(ic->bee, ic, handle)) || + (bu = bee_user_new(ic->bee, ic, handle, 0)))) { + g_free(handle); continue; } - g_free( handle ); + g_free(handle); bd = bu->data; - - if( ( f = xt_find_attr( c, "f" ) ) ) - { - http_decode( f ); - imcb_rename_buddy( ic, bu->handle, f ); + + if ((f = xt_find_attr(c, "f"))) { + http_decode(f); + imcb_rename_buddy(ic, bu->handle, f); } - - flags = atoi( l ) & 15; - if( bd->flags != flags ) - { + + flags = atoi(l) & 15; + if (bd->flags != flags) { bd->flags = flags; - msn_buddy_ask( bu ); + msn_buddy_ask(bu); } } } - } - else if( strcmp( cmd[0], "UBM" ) == 0 ) - { + } else if (strcmp(cmd[0], "UBM") == 0) { /* This one will give us msgs from federated networks. Technically it should also get us offline messages, but I don't know how I can signal MSN servers to use it. */ char *ct, *handle; - - if( strcmp( cmd[1], ic->acc->user ) == 0 ) - { + + if (strcmp(cmd[1], ic->acc->user) == 0) { /* With MPOP, you'll get copies of your own msgs from other sessions. Discard those at least for now. */ return 1; } - - ct = get_rfc822_header( msg, "Content-Type", msglen ); - if( strncmp( ct, "text/plain", 10 ) != 0 ) - { + + ct = get_rfc822_header(msg, "Content-Type", msglen); + if (strncmp(ct, "text/plain", 10) != 0) { /* Typing notification or something? */ - g_free( ct ); + g_free(ct); return 1; } - if( strcmp( cmd[2], "1" ) != 0 ) - handle = g_strdup_printf( "%s:%s", cmd[2], cmd[1] ); - else - handle = g_strdup( cmd[1] ); - - imcb_buddy_msg( ic, handle, body, 0, 0 ); - g_free( handle ); + if (strcmp(cmd[2], "1") != 0) { + handle = g_strdup_printf("%s:%s", cmd[2], cmd[1]); + } else { + handle = g_strdup(cmd[1]); + } + + imcb_buddy_msg(ic, handle, body, 0, 0); + g_free(handle); } - + return 1; } -void msn_auth_got_passport_token( struct im_connection *ic, const char *token, const char *error ) +void msn_auth_got_passport_token(struct im_connection *ic, const char *token, const char *error) { struct msn_data *md; - + /* Dead connection? */ - if( g_slist_find( msn_connections, ic ) == NULL ) + if (g_slist_find(msn_connections, ic) == NULL) { return; - - md = ic->proto_data; - - if( token ) - { - msn_ns_write( ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid ); } - else - { - imcb_error( ic, "Error during Passport authentication: %s", error ); - imc_logout( ic, TRUE ); + + md = ic->proto_data; + + if (token) { + msn_ns_write(ic, -1, "USR %d SSO S %s %s {%s}\r\n", ++md->trId, md->tokens[0], token, md->uuid); + } else { + imcb_error(ic, "Error during Passport authentication: %s", error); + imc_logout(ic, TRUE); } } -void msn_auth_got_contact_list( struct im_connection *ic ) +void msn_auth_got_contact_list(struct im_connection *ic) { struct msn_data *md; - + /* Dead connection? */ - if( g_slist_find( msn_connections, ic ) == NULL ) + if (g_slist_find(msn_connections, ic) == NULL) { return; - + } + md = ic->proto_data; - msn_ns_write( ic, -1, "BLP %d %s\r\n", ++md->trId, "BL" ); + msn_ns_write(ic, -1, "BLP %d %s\r\n", ++md->trId, "BL"); } -static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) +static gboolean msn_ns_send_adl_1(gpointer key, gpointer value, gpointer data) { struct xt_node *adl = data, *d, *c; struct bee_user *bu = value; @@ -883,159 +787,166 @@ static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) char handle[strlen(bu->handle) + 1]; char *domain; char l[4]; - - if( ( bd->flags & 7 ) == 0 || ( bd->flags & MSN_BUDDY_ADL_SYNCED ) ) + + if ((bd->flags & 7) == 0 || (bd->flags & MSN_BUDDY_ADL_SYNCED)) { + return FALSE; + } + + strcpy(handle, bu->handle); + if ((domain = strchr(handle, '@')) == NULL) { /* WTF */ return FALSE; - - strcpy( handle, bu->handle ); - if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ - return FALSE; + } *domain = '\0'; - domain ++; - - if( ( d = adl->children ) == NULL || - g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 ) - { - d = xt_new_node( "d", NULL, NULL ); - xt_add_attr( d, "n", domain ); - xt_insert_child( adl, d ); + domain++; + + if ((d = adl->children) == NULL || + g_strcasecmp(xt_find_attr(d, "n"), domain) != 0) { + d = xt_new_node("d", NULL, NULL); + xt_add_attr(d, "n", domain); + xt_insert_child(adl, d); } - - g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 ); - c = xt_new_node( "c", NULL, NULL ); - xt_add_attr( c, "n", handle ); - xt_add_attr( c, "l", l ); - xt_add_attr( c, "t", "1" ); /* FIXME: Network type, i.e. 32 for Y!MSG */ - xt_insert_child( d, c ); - + + g_snprintf(l, sizeof(l), "%d", bd->flags & 7); + c = xt_new_node("c", NULL, NULL); + xt_add_attr(c, "n", handle); + xt_add_attr(c, "l", l); + xt_add_attr(c, "t", "1"); /* FIXME: Network type, i.e. 32 for Y!MSG */ + xt_insert_child(d, c); + /* Do this in batches of 100. */ bd->flags |= MSN_BUDDY_ADL_SYNCED; return (--md->adl_todo % 140) == 0; } -static void msn_ns_send_adl( struct im_connection *ic ) +static void msn_ns_send_adl(struct im_connection *ic) { struct xt_node *adl; struct msn_data *md = ic->proto_data; char *adls; - - adl = xt_new_node( "ml", NULL, NULL ); - xt_add_attr( adl, "l", "1" ); - g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); - if( adl->children == NULL ) - { + + adl = xt_new_node("ml", NULL, NULL); + xt_add_attr(adl, "l", "1"); + g_tree_foreach(md->domaintree, msn_ns_send_adl_1, adl); + if (adl->children == NULL) { /* This tells the caller that we're done now. */ md->adl_todo = -1; - xt_free_node( adl ); + xt_free_node(adl); return; } - - adls = xt_to_string( adl ); - xt_free_node( adl ); - msn_ns_write( ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen( adls ), adls ); - g_free( adls ); + + adls = xt_to_string(adl); + xt_free_node(adl); + msn_ns_write(ic, -1, "ADL %d %zd\r\n%s", ++md->trId, strlen(adls), adls); + g_free(adls); } -static void msn_ns_send_adl_start( struct im_connection *ic ) +static void msn_ns_send_adl_start(struct im_connection *ic) { struct msn_data *md; GSList *l; - + /* Dead connection? */ - if( g_slist_find( msn_connections, ic ) == NULL ) + if (g_slist_find(msn_connections, ic) == NULL) { return; - + } + md = ic->proto_data; md->adl_todo = 0; - for( l = ic->bee->users; l; l = l->next ) - { + for (l = ic->bee->users; l; l = l->next) { bee_user_t *bu = l->data; struct msn_buddy_data *bd = bu->data; - - if( bu->ic != ic || ( bd->flags & 7 ) == 0 ) + + if (bu->ic != ic || (bd->flags & 7) == 0) { continue; - + } + bd->flags &= ~MSN_BUDDY_ADL_SYNCED; md->adl_todo++; } - - msn_ns_send_adl( ic ); + + msn_ns_send_adl(ic); } -int msn_ns_finish_login( struct im_connection *ic ) +int msn_ns_finish_login(struct im_connection *ic) { struct msn_data *md = ic->proto_data; - - if( ic->flags & OPT_LOGGED_IN ) + + if (ic->flags & OPT_LOGGED_IN) { return 1; - - if( md->adl_todo < 0 ) + } + + if (md->adl_todo < 0) { md->flags |= MSN_DONE_ADL; - - if( ( md->flags & MSN_DONE_ADL ) && ( md->flags & MSN_GOT_PROFILE ) ) - { - if( md->flags & MSN_EMAIL_UNVERIFIED ) - imcb_connected( ic ); - else - return msn_ns_set_display_name( ic, set_getstr( &ic->acc->set, "display_name" ) ); } - + + if ((md->flags & MSN_DONE_ADL) && (md->flags & MSN_GOT_PROFILE)) { + if (md->flags & MSN_EMAIL_UNVERIFIED) { + imcb_connected(ic); + } else { + return msn_ns_set_display_name(ic, set_getstr(&ic->acc->set, "display_name")); + } + } + return 1; } -int msn_ns_sendmessage( struct im_connection *ic, bee_user_t *bu, const char *text ) +int msn_ns_sendmessage(struct im_connection *ic, bee_user_t *bu, const char *text) { struct msn_data *md = ic->proto_data; int type = 0; char *buf, *handle; - - if( strncmp( text, "\r\r\r", 3 ) == 0 ) + + if (strncmp(text, "\r\r\r", 3) == 0) { /* Err. Shouldn't happen but I guess it can. Don't send others any of the "SHAKE THAT THING" messages. :-D */ return 1; - + } + /* This might be a federated contact. Get its network number, prefixed to bu->handle with a colon. Default is 1. */ - for( handle = bu->handle; g_ascii_isdigit( *handle ); handle ++ ) + for (handle = bu->handle; g_ascii_isdigit(*handle); handle++) { type = type * 10 + *handle - '0'; - if( *handle == ':' ) - handle ++; - else + } + if (*handle == ':') { + handle++; + } else { type = 1; - - buf = g_strdup_printf( "%s%s", MSN_MESSAGE_HEADERS, text ); - - if( msn_ns_write( ic, -1, "UUM %d %s %d %d %zd\r\n%s", - ++md->trId, handle, type, - 1, /* type == IM (not nudge/typing) */ - strlen( buf ), buf ) ) + } + + buf = g_strdup_printf("%s%s", MSN_MESSAGE_HEADERS, text); + + if (msn_ns_write(ic, -1, "UUM %d %s %d %d %zd\r\n%s", + ++md->trId, handle, type, + 1, /* type == IM (not nudge/typing) */ + strlen(buf), buf)) { return 1; - else + } else { return 0; + } } -void msn_ns_oim_send_queue( struct im_connection *ic, GSList **msgq ) +void msn_ns_oim_send_queue(struct im_connection *ic, GSList **msgq) { GSList *l; - - for( l = *msgq; l; l = l->next ) - { + + for (l = *msgq; l; l = l->next) { struct msn_message *m = l->data; - bee_user_t *bu = bee_user_by_handle( ic->bee, ic, m->who ); - - if( bu ) - if( !msn_ns_sendmessage( ic, bu, m->text ) ) + bee_user_t *bu = bee_user_by_handle(ic->bee, ic, m->who); + + if (bu) { + if (!msn_ns_sendmessage(ic, bu, m->text)) { return; + } + } } - - while( *msgq != NULL ) - { + + while (*msgq != NULL) { struct msn_message *m = (*msgq)->data; - - g_free( m->who ); - g_free( m->text ); - g_free( m ); - - *msgq = g_slist_remove( *msgq, m ); + + g_free(m->who); + g_free(m->text); + g_free(m); + + *msgq = g_slist_remove(*msgq, m); } } diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index 40e4e00d..d0412961 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -30,336 +30,328 @@ #include "soap.h" #include "invitation.h" -static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ); -static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts ); -static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ); +static gboolean msn_sb_callback(gpointer data, gint source, b_input_condition cond); +static int msn_sb_command(struct msn_handler_data *handler, char **cmd, int num_parts); +static int msn_sb_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts); -int msn_sb_write( struct msn_switchboard *sb, const char *fmt, ... ) +int msn_sb_write(struct msn_switchboard *sb, const char *fmt, ...) { va_list params; char *out; size_t len; int st; - - va_start( params, fmt ); - out = g_strdup_vprintf( fmt, params ); - va_end( params ); - - if( getenv( "BITLBEE_DEBUG" ) ) - fprintf( stderr, "->SB%d:%s\n", sb->fd, out ); - - len = strlen( out ); - st = write( sb->fd, out, len ); - g_free( out ); - if( st != len ) - { - msn_sb_destroy( sb ); + + va_start(params, fmt); + out = g_strdup_vprintf(fmt, params); + va_end(params); + + if (getenv("BITLBEE_DEBUG")) { + fprintf(stderr, "->SB%d:%s\n", sb->fd, out); + } + + len = strlen(out); + st = write(sb->fd, out, len); + g_free(out); + if (st != len) { + msn_sb_destroy(sb); return 0; } - + return 1; } -int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ) +int msn_sb_write_msg(struct im_connection *ic, struct msn_message *m) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; /* FIXME: *CHECK* the reliability of using spare sb's! */ - if( ( sb = msn_sb_spare( ic ) ) ) - { - debug( "Trying to use a spare switchboard to message %s", m->who ); - - sb->who = g_strdup( m->who ); - if( msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, m->who ) ) - { + if ((sb = msn_sb_spare(ic))) { + debug("Trying to use a spare switchboard to message %s", m->who); + + sb->who = g_strdup(m->who); + if (msn_sb_write(sb, "CAL %d %s\r\n", ++sb->trId, m->who)) { /* He/She should join the switchboard soon, let's queue the message. */ - sb->msgq = g_slist_append( sb->msgq, m ); - return( 1 ); + sb->msgq = g_slist_append(sb->msgq, m); + return(1); } } - - debug( "Creating a new switchboard to message %s", m->who ); - + + debug("Creating a new switchboard to message %s", m->who); + /* If we reach this line, there was no spare switchboard, so let's make one. */ - if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) ) - { - g_free( m->who ); - g_free( m->text ); - g_free( m ); - - return( 0 ); + if (!msn_ns_write(ic, -1, "XFR %d SB\r\n", ++md->trId)) { + g_free(m->who); + g_free(m->text); + g_free(m); + + return(0); } - + /* And queue the message to md. We'll pick it up when the switchboard comes up. */ - md->msgq = g_slist_append( md->msgq, m ); - + md->msgq = g_slist_append(md->msgq, m); + /* FIXME: If the switchboard creation fails, the message will not be sent. */ - - return( 1 ); + + return(1); } -struct msn_switchboard *msn_sb_create( struct im_connection *ic, char *host, int port, char *key, int session ) +struct msn_switchboard *msn_sb_create(struct im_connection *ic, char *host, int port, char *key, int session) { struct msn_data *md = ic->proto_data; - struct msn_switchboard *sb = g_new0( struct msn_switchboard, 1 ); - - sb->fd = proxy_connect( host, port, msn_sb_connected, sb ); - if( sb->fd < 0 ) - { - g_free( sb ); - return( NULL ); + struct msn_switchboard *sb = g_new0(struct msn_switchboard, 1); + + sb->fd = proxy_connect(host, port, msn_sb_connected, sb); + if (sb->fd < 0) { + g_free(sb); + return(NULL); } - + sb->ic = ic; - sb->key = g_strdup( key ); + sb->key = g_strdup(key); sb->session = session; - - msn_switchboards = g_slist_append( msn_switchboards, sb ); - md->switchboards = g_slist_append( md->switchboards, sb ); - - return( sb ); + + msn_switchboards = g_slist_append(msn_switchboards, sb); + md->switchboards = g_slist_append(md->switchboards, sb); + + return(sb); } -struct msn_switchboard *msn_sb_by_handle( struct im_connection *ic, const char *handle ) +struct msn_switchboard *msn_sb_by_handle(struct im_connection *ic, const char *handle) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; GSList *l; - - for( l = md->switchboards; l; l = l->next ) - { + + for (l = md->switchboards; l; l = l->next) { sb = l->data; - if( sb->who && strcmp( sb->who, handle ) == 0 ) - return( sb ); + if (sb->who && strcmp(sb->who, handle) == 0) { + return(sb); + } } - - return( NULL ); + + return(NULL); } -struct msn_switchboard *msn_sb_by_chat( struct groupchat *c ) +struct msn_switchboard *msn_sb_by_chat(struct groupchat *c) { struct msn_data *md = c->ic->proto_data; struct msn_switchboard *sb; GSList *l; - - for( l = md->switchboards; l; l = l->next ) - { + + for (l = md->switchboards; l; l = l->next) { sb = l->data; - if( sb->chat == c ) - return( sb ); + if (sb->chat == c) { + return(sb); + } } - - return( NULL ); + + return(NULL); } -struct msn_switchboard *msn_sb_spare( struct im_connection *ic ) +struct msn_switchboard *msn_sb_spare(struct im_connection *ic) { struct msn_data *md = ic->proto_data; struct msn_switchboard *sb; GSList *l; - - for( l = md->switchboards; l; l = l->next ) - { + + for (l = md->switchboards; l; l = l->next) { sb = l->data; - if( !sb->who && !sb->chat ) - return( sb ); + if (!sb->who && !sb->chat) { + return(sb); + } } - - return( NULL ); + + return(NULL); } -int msn_sb_sendmessage( struct msn_switchboard *sb, char *text ) +int msn_sb_sendmessage(struct msn_switchboard *sb, char *text) { - if( sb->ready ) - { + if (sb->ready) { char *buf; int i, j; - + /* Build the message. Convert LF to CR-LF for normal messages. */ - if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 ) - { - i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user ); - buf = g_new0( char, i ); - i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user ); - } - else if( strcmp( text, NUDGE_MESSAGE ) == 0 ) - { - buf = g_strdup( MSN_NUDGE_HEADERS ); - i = strlen( buf ); - } - else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 ) - { - buf = g_strdup( MSN_SB_KEEPALIVE_HEADERS ); - i = strlen( buf ); - } - else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 ) - { - buf = g_strdup( text ); - i = strlen( buf ); - } - else - { - buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 ); - i = strlen( MSN_MESSAGE_HEADERS ); - - strcpy( buf, MSN_MESSAGE_HEADERS ); - for( j = 0; text[j]; j ++ ) - { - if( text[j] == '\n' ) + if (strcmp(text, TYPING_NOTIFICATION_MESSAGE) == 0) { + i = strlen(MSN_TYPING_HEADERS) + strlen(sb->ic->acc->user); + buf = g_new0(char, i); + i = g_snprintf(buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user); + } else if (strcmp(text, NUDGE_MESSAGE) == 0) { + buf = g_strdup(MSN_NUDGE_HEADERS); + i = strlen(buf); + } else if (strcmp(text, SB_KEEPALIVE_MESSAGE) == 0) { + buf = g_strdup(MSN_SB_KEEPALIVE_HEADERS); + i = strlen(buf); + } else if (strncmp(text, MSN_INVITE_HEADERS, sizeof(MSN_INVITE_HEADERS) - 1) == 0) { + buf = g_strdup(text); + i = strlen(buf); + } else { + buf = g_new0(char, sizeof(MSN_MESSAGE_HEADERS) + strlen(text) * 2 + 1); + i = strlen(MSN_MESSAGE_HEADERS); + + strcpy(buf, MSN_MESSAGE_HEADERS); + for (j = 0; text[j]; j++) { + if (text[j] == '\n') { buf[i++] = '\r'; - + } + buf[i++] = text[j]; } } - + /* Build the final packet (MSG command + the message). */ - if( msn_sb_write( sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf ) ) - { - g_free( buf ); + if (msn_sb_write(sb, "MSG %d N %d\r\n%s", ++sb->trId, i, buf)) { + g_free(buf); return 1; - } - else - { - g_free( buf ); + } else { + g_free(buf); return 0; } - } - else if( sb->who ) - { - struct msn_message *m = g_new0( struct msn_message, 1 ); - - m->who = g_strdup( "" ); - m->text = g_strdup( text ); - sb->msgq = g_slist_append( sb->msgq, m ); - - return( 1 ); - } - else - { - return( 0 ); + } else if (sb->who) { + struct msn_message *m = g_new0(struct msn_message, 1); + + m->who = g_strdup(""); + m->text = g_strdup(text); + sb->msgq = g_slist_append(sb->msgq, m); + + return(1); + } else { + return(0); } } -struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb ) +struct groupchat *msn_sb_to_chat(struct msn_switchboard *sb) { struct im_connection *ic = sb->ic; struct groupchat *c = NULL; char buf[1024]; - + /* Create the groupchat structure. */ - g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - if( sb->who ) - c = bee_chat_by_title( ic->bee, ic, sb->who ); - if( c && !msn_sb_by_chat( c ) ) + g_snprintf(buf, sizeof(buf), "MSN groupchat session %d", sb->session); + if (sb->who) { + c = bee_chat_by_title(ic->bee, ic, sb->who); + } + if (c && !msn_sb_by_chat(c)) { sb->chat = c; - else - sb->chat = imcb_chat_new( ic, buf ); - + } else { + sb->chat = imcb_chat_new(ic, buf); + } + /* Populate the channel. */ - if( sb->who ) imcb_chat_add_buddy( sb->chat, sb->who ); - imcb_chat_add_buddy( sb->chat, ic->acc->user ); - + if (sb->who) { + imcb_chat_add_buddy(sb->chat, sb->who); + } + imcb_chat_add_buddy(sb->chat, ic->acc->user); + /* And make sure the switchboard doesn't look like a regular chat anymore. */ - if( sb->who ) - { - g_free( sb->who ); + if (sb->who) { + g_free(sb->who); sb->who = NULL; } - + return sb->chat; } -void msn_sb_destroy( struct msn_switchboard *sb ) +void msn_sb_destroy(struct msn_switchboard *sb) { struct im_connection *ic = sb->ic; struct msn_data *md = ic->proto_data; - - debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" ); - - msn_msgq_purge( ic, &sb->msgq ); - msn_sb_stop_keepalives( sb ); - - if( sb->key ) g_free( sb->key ); - if( sb->who ) g_free( sb->who ); - - if( sb->chat ) - { - imcb_chat_free( sb->chat ); + + debug("Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : ""); + + msn_msgq_purge(ic, &sb->msgq); + msn_sb_stop_keepalives(sb); + + if (sb->key) { + g_free(sb->key); + } + if (sb->who) { + g_free(sb->who); } - - if( sb->handler ) - { - if( sb->handler->rxq ) g_free( sb->handler->rxq ); - if( sb->handler->cmd_text ) g_free( sb->handler->cmd_text ); - g_free( sb->handler ); + + if (sb->chat) { + imcb_chat_free(sb->chat); } - - if( sb->inp ) b_event_remove( sb->inp ); - closesocket( sb->fd ); - - msn_switchboards = g_slist_remove( msn_switchboards, sb ); - md->switchboards = g_slist_remove( md->switchboards, sb ); - g_free( sb ); + + if (sb->handler) { + if (sb->handler->rxq) { + g_free(sb->handler->rxq); + } + if (sb->handler->cmd_text) { + g_free(sb->handler->cmd_text); + } + g_free(sb->handler); + } + + if (sb->inp) { + b_event_remove(sb->inp); + } + closesocket(sb->fd); + + msn_switchboards = g_slist_remove(msn_switchboards, sb); + md->switchboards = g_slist_remove(md->switchboards, sb); + g_free(sb); } -gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond ) +gboolean msn_sb_connected(gpointer data, gint source, b_input_condition cond) { struct msn_switchboard *sb = data; struct im_connection *ic; struct msn_data *md; char buf[1024]; - + /* Are we still alive? */ - if( !g_slist_find( msn_switchboards, sb ) ) + if (!g_slist_find(msn_switchboards, sb)) { return FALSE; - + } + ic = sb->ic; md = ic->proto_data; - - if( source != sb->fd ) - { - debug( "Error %d while connecting to switchboard server", 1 ); - msn_sb_destroy( sb ); + + if (source != sb->fd) { + debug("Error %d while connecting to switchboard server", 1); + msn_sb_destroy(sb); return FALSE; } - + /* Prepare the callback */ - sb->handler = g_new0( struct msn_handler_data, 1 ); + sb->handler = g_new0(struct msn_handler_data, 1); sb->handler->fd = sb->fd; - sb->handler->rxq = g_new0( char, 1 ); + sb->handler->rxq = g_new0(char, 1); sb->handler->data = sb; sb->handler->exec_command = msn_sb_command; sb->handler->exec_message = msn_sb_message; - - if( sb->session == MSN_SB_NEW ) - g_snprintf( buf, sizeof( buf ), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key ); - else - g_snprintf( buf, sizeof( buf ), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key, sb->session ); - - if( msn_sb_write( sb, "%s", buf ) ) - sb->inp = b_input_add( sb->fd, B_EV_IO_READ, msn_sb_callback, sb ); - else - debug( "Error %d while connecting to switchboard server", 2 ); - + + if (sb->session == MSN_SB_NEW) { + g_snprintf(buf, sizeof(buf), "USR %d %s;{%s} %s\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key); + } else { + g_snprintf(buf, sizeof(buf), "ANS %d %s;{%s} %s %d\r\n", ++sb->trId, ic->acc->user, md->uuid, sb->key, + sb->session); + } + + if (msn_sb_write(sb, "%s", buf)) { + sb->inp = b_input_add(sb->fd, B_EV_IO_READ, msn_sb_callback, sb); + } else { + debug("Error %d while connecting to switchboard server", 2); + } + return FALSE; } -static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition cond ) +static gboolean msn_sb_callback(gpointer data, gint source, b_input_condition cond) { struct msn_switchboard *sb = data; struct im_connection *ic = sb->ic; struct msn_data *md = ic->proto_data; - - if( msn_handler( sb->handler ) != -1 ) + + if (msn_handler(sb->handler) != -1) { return TRUE; - - if( sb->msgq != NULL ) - { - time_t now = time( NULL ); - - if( now - md->first_sb_failure > 600 ) - { + } + + if (sb->msgq != NULL) { + time_t now = time(NULL); + + if (now - md->first_sb_failure > 600) { /* It's not really the first one, but the start of this "series". With this, the warning below will be shown only if this happens at least three times in ten minutes. This algorithm isn't @@ -367,457 +359,393 @@ static gboolean msn_sb_callback( gpointer data, gint source, b_input_condition c md->first_sb_failure = now; md->sb_failures = 0; } - - debug( "Error: Switchboard died" ); - if( ++ md->sb_failures >= 3 ) - imcb_log( ic, "Warning: Many switchboard failures on MSN connection. " - "There might be problems delivering your messages." ); - - if( md->msgq == NULL ) - { - md->msgq = sb->msgq; + + debug("Error: Switchboard died"); + if (++md->sb_failures >= 3) { + imcb_log(ic, "Warning: Many switchboard failures on MSN connection. " + "There might be problems delivering your messages."); } - else - { + + if (md->msgq == NULL) { + md->msgq = sb->msgq; + } else { GSList *l; - - for( l = md->msgq; l->next; l = l->next ); + + for (l = md->msgq; l->next; l = l->next) { + ; + } l->next = sb->msgq; } sb->msgq = NULL; - - debug( "Moved queued messages back to the main queue, " - "creating a new switchboard to retry." ); - if( !msn_ns_write( ic, -1, "XFR %d SB\r\n", ++md->trId ) ) + + debug("Moved queued messages back to the main queue, " + "creating a new switchboard to retry."); + if (!msn_ns_write(ic, -1, "XFR %d SB\r\n", ++md->trId)) { return FALSE; + } } - - msn_sb_destroy( sb ); + + msn_sb_destroy(sb); return FALSE; } -static int msn_sb_command( struct msn_handler_data *handler, char **cmd, int num_parts ) +static int msn_sb_command(struct msn_handler_data *handler, char **cmd, int num_parts) { struct msn_switchboard *sb = handler->data; struct im_connection *ic = sb->ic; - - if( !num_parts ) - { + + if (!num_parts) { /* Hrrm... Empty command...? Ignore? */ - return( 1 ); - } - - if( strcmp( cmd[0], "XFR" ) == 0 ) - { - imcb_error( ic, "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!" ); - imc_logout( ic, TRUE ); - return( 0 ); - } - else if( strcmp( cmd[0], "USR" ) == 0 ) - { - if( num_parts < 5 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - if( strcmp( cmd[2], "OK" ) != 0 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - if( sb->who ) - return msn_sb_write( sb, "CAL %d %s\r\n", ++sb->trId, sb->who ); - else - debug( "Just created a switchboard, but I don't know what to do with it." ); + return(1); } - else if( strcmp( cmd[0], "IRO" ) == 0 ) - { + + if (strcmp(cmd[0], "XFR") == 0) { + imcb_error(ic, + "Received an XFR from a switchboard server, unable to comply! This is likely to be a bug, please report it!"); + imc_logout(ic, TRUE); + return(0); + } else if (strcmp(cmd[0], "USR") == 0) { + if (num_parts < 5) { + msn_sb_destroy(sb); + return(0); + } + + if (strcmp(cmd[2], "OK") != 0) { + msn_sb_destroy(sb); + return(0); + } + + if (sb->who) { + return msn_sb_write(sb, "CAL %d %s\r\n", ++sb->trId, sb->who); + } else { + debug("Just created a switchboard, but I don't know what to do with it."); + } + } else if (strcmp(cmd[0], "IRO") == 0) { int num, tot; - - if( num_parts < 6 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - num = atoi( cmd[2] ); - tot = atoi( cmd[3] ); - - if( tot <= 0 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - else if( tot > 1 ) - { + + if (num_parts < 6) { + msn_sb_destroy(sb); + return(0); + } + + num = atoi(cmd[2]); + tot = atoi(cmd[3]); + + if (tot <= 0) { + msn_sb_destroy(sb); + return(0); + } else if (tot > 1) { char buf[1024]; - + /* For as much as I understand this MPOP stuff now, a switchboard has two (or more) roster entries per participant. One "bare JID" and one JID;UUID. Ignore the latter. */ - if( !strchr( cmd[4], ';' ) ) - { + if (!strchr(cmd[4], ';')) { /* HACK: Since even 1:1 chats now have >2 participants (ourselves included) it gets hard to tell them apart from rooms. Let's hope this is enough: */ - if( sb->chat == NULL && num != tot ) - { - g_snprintf( buf, sizeof( buf ), "MSN groupchat session %d", sb->session ); - sb->chat = imcb_chat_new( ic, buf ); - - g_free( sb->who ); + if (sb->chat == NULL && num != tot) { + g_snprintf(buf, sizeof(buf), "MSN groupchat session %d", sb->session); + sb->chat = imcb_chat_new(ic, buf); + + g_free(sb->who); sb->who = NULL; } - - if( sb->chat ) - imcb_chat_add_buddy( sb->chat, cmd[4] ); + + if (sb->chat) { + imcb_chat_add_buddy(sb->chat, cmd[4]); + } } - + /* We have the full roster, start showing the channel to the user. */ - if( num == tot && sb->chat ) - { - imcb_chat_add_buddy( sb->chat, ic->acc->user ); + if (num == tot && sb->chat) { + imcb_chat_add_buddy(sb->chat, ic->acc->user); } } - } - else if( strcmp( cmd[0], "ANS" ) == 0 ) - { - if( num_parts < 3 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - if( strcmp( cmd[2], "OK" ) != 0 ) - { - debug( "Switchboard server sent a negative ANS reply" ); - msn_sb_destroy( sb ); - return( 0 ); - } - + } else if (strcmp(cmd[0], "ANS") == 0) { + if (num_parts < 3) { + msn_sb_destroy(sb); + return(0); + } + + if (strcmp(cmd[2], "OK") != 0) { + debug("Switchboard server sent a negative ANS reply"); + msn_sb_destroy(sb); + return(0); + } + sb->ready = 1; - - msn_sb_start_keepalives( sb, FALSE ); - } - else if( strcmp( cmd[0], "CAL" ) == 0 ) - { - if( num_parts < 4 || !g_ascii_isdigit( cmd[3][0] ) ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - sb->session = atoi( cmd[3] ); - } - else if( strcmp( cmd[0], "JOI" ) == 0 ) - { - if( num_parts < 3 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - + + msn_sb_start_keepalives(sb, FALSE); + } else if (strcmp(cmd[0], "CAL") == 0) { + if (num_parts < 4 || !g_ascii_isdigit(cmd[3][0])) { + msn_sb_destroy(sb); + return(0); + } + + sb->session = atoi(cmd[3]); + } else if (strcmp(cmd[0], "JOI") == 0) { + if (num_parts < 3) { + msn_sb_destroy(sb); + return(0); + } + /* See IRO above. Handle "bare JIDs" only. */ - if( strchr( cmd[1], ';' ) ) + if (strchr(cmd[1], ';')) { return 1; - - if( sb->who && g_strcasecmp( cmd[1], sb->who ) == 0 ) - { + } + + if (sb->who && g_strcasecmp(cmd[1], sb->who) == 0) { /* The user we wanted to talk to is finally there, let's send the queued messages then. */ struct msn_message *m; GSList *l; int st = 1; - - debug( "%s arrived in the switchboard session, now sending queued message(s)", cmd[1] ); - + + debug("%s arrived in the switchboard session, now sending queued message(s)", cmd[1]); + /* Without this, sendmessage() will put everything back on the queue... */ sb->ready = 1; - - while( ( l = sb->msgq ) ) - { + + while ((l = sb->msgq)) { m = l->data; - if( st ) - { + if (st) { /* This hack is meant to convert a regular new chat into a groupchat */ - if( strcmp( m->text, GROUPCHAT_SWITCHBOARD_MESSAGE ) == 0 ) - msn_sb_to_chat( sb ); - else - st = msn_sb_sendmessage( sb, m->text ); + if (strcmp(m->text, GROUPCHAT_SWITCHBOARD_MESSAGE) == 0) { + msn_sb_to_chat(sb); + } else { + st = msn_sb_sendmessage(sb, m->text); + } } - g_free( m->text ); - g_free( m->who ); - g_free( m ); - - sb->msgq = g_slist_remove( sb->msgq, m ); + g_free(m->text); + g_free(m->who); + g_free(m); + + sb->msgq = g_slist_remove(sb->msgq, m); } - - msn_sb_start_keepalives( sb, FALSE ); - - return( st ); - } - else if( strcmp( cmd[1], ic->acc->user ) == 0 ) - { + + msn_sb_start_keepalives(sb, FALSE); + + return(st); + } else if (strcmp(cmd[1], ic->acc->user) == 0) { /* Well, gee thanks. Thanks for letting me know I've arrived.. */ - } - else if( sb->who ) - { - debug( "Converting chat with %s to a groupchat because %s joined the session.", sb->who, cmd[1] ); - + } else if (sb->who) { + debug("Converting chat with %s to a groupchat because %s joined the session.", sb->who, cmd[1]); + /* This SB is a one-to-one chat right now, but someone else is joining. */ - msn_sb_to_chat( sb ); - - imcb_chat_add_buddy( sb->chat, cmd[1] ); - } - else if( sb->chat ) - { - imcb_chat_add_buddy( sb->chat, cmd[1] ); + msn_sb_to_chat(sb); + + imcb_chat_add_buddy(sb->chat, cmd[1]); + } else if (sb->chat) { + imcb_chat_add_buddy(sb->chat, cmd[1]); sb->ready = 1; - } - else - { + } else { /* PANIC! */ } - } - else if( strcmp( cmd[0], "MSG" ) == 0 ) - { - if( num_parts < 4 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - - sb->handler->msglen = atoi( cmd[3] ); - - if( sb->handler->msglen <= 0 ) - { - debug( "Received a corrupted message on the switchboard, the switchboard will be closed" ); - msn_sb_destroy( sb ); - return( 0 ); - } - } - else if( strcmp( cmd[0], "NAK" ) == 0 ) - { - if( sb->who ) - { - imcb_log( ic, "The MSN servers could not deliver one of your messages to %s.", sb->who ); + } else if (strcmp(cmd[0], "MSG") == 0) { + if (num_parts < 4) { + msn_sb_destroy(sb); + return(0); } - else - { - imcb_log( ic, "The MSN servers could not deliver one of your groupchat messages to all participants." ); + + sb->handler->msglen = atoi(cmd[3]); + + if (sb->handler->msglen <= 0) { + debug("Received a corrupted message on the switchboard, the switchboard will be closed"); + msn_sb_destroy(sb); + return(0); + } + } else if (strcmp(cmd[0], "NAK") == 0) { + if (sb->who) { + imcb_log(ic, "The MSN servers could not deliver one of your messages to %s.", sb->who); + } else { + imcb_log(ic, + "The MSN servers could not deliver one of your groupchat messages to all participants."); + } + } else if (strcmp(cmd[0], "BYE") == 0) { + if (num_parts < 2) { + msn_sb_destroy(sb); + return(0); } - } - else if( strcmp( cmd[0], "BYE" ) == 0 ) - { - if( num_parts < 2 ) - { - msn_sb_destroy( sb ); - return( 0 ); - } - + /* if( cmd[2] && *cmd[2] == '1' ) -=> Chat is being cleaned up because of idleness */ - - if( sb->who ) - { - msn_sb_stop_keepalives( sb ); - + + if (sb->who) { + msn_sb_stop_keepalives(sb); + /* This is a single-person chat, and the other person is leaving. */ - g_free( sb->who ); + g_free(sb->who); sb->who = NULL; sb->ready = 0; - - debug( "Person %s left the one-to-one switchboard connection. Keeping it around as a spare...", cmd[1] ); - + + debug("Person %s left the one-to-one switchboard connection. Keeping it around as a spare...", + cmd[1]); + /* We could clean up the switchboard now, but keeping it around as a spare for a next conversation sounds more sane to me. The server will clean it up when it's idle for too long. */ - } - else if( sb->chat && !strchr( cmd[1], ';' ) ) - { - imcb_chat_remove_buddy( sb->chat, cmd[1], "" ); - } - else - { + } else if (sb->chat && !strchr(cmd[1], ';')) { + imcb_chat_remove_buddy(sb->chat, cmd[1], ""); + } else { /* PANIC! */ } - } - else if( g_ascii_isdigit( cmd[0][0] ) ) - { - int num = atoi( cmd[0] ); - const struct msn_status_code *err = msn_status_by_number( num ); - + } else if (g_ascii_isdigit(cmd[0][0])) { + int num = atoi(cmd[0]); + const struct msn_status_code *err = msn_status_by_number(num); + /* If the person is offline, send an offline message instead, and don't report an error. */ - if( num == 217 ) - msn_ns_oim_send_queue( ic, &sb->msgq ); - else - imcb_error( ic, "Error reported by switchboard server: %s", err->text ); - - if( err->flags & STATUS_SB_FATAL ) - { - msn_sb_destroy( sb ); - return 0; + if (num == 217) { + msn_ns_oim_send_queue(ic, &sb->msgq); + } else { + imcb_error(ic, "Error reported by switchboard server: %s", err->text); } - else if( err->flags & STATUS_FATAL ) - { - imc_logout( ic, TRUE ); + + if (err->flags & STATUS_SB_FATAL) { + msn_sb_destroy(sb); return 0; - } - else if( err->flags & STATUS_SB_IM_SPARE ) - { - if( sb->who ) - { + } else if (err->flags & STATUS_FATAL) { + imc_logout(ic, TRUE); + return 0; + } else if (err->flags & STATUS_SB_IM_SPARE) { + if (sb->who) { /* Apparently some invitation failed. We might want to use this board later, so keep it as a spare. */ - g_free( sb->who ); + g_free(sb->who); sb->who = NULL; - + /* Also clear the msgq, otherwise someone else might get them. */ - msn_msgq_purge( ic, &sb->msgq ); + msn_msgq_purge(ic, &sb->msgq); } - + /* Do NOT return 0 here, we want to keep this sb. */ } - } - else - { + } else { /* debug( "Received unknown command from switchboard server: %s", cmd[0] ); */ } - - return( 1 ); + + return(1); } -static int msn_sb_message( struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts ) +static int msn_sb_message(struct msn_handler_data *handler, char *msg, int msglen, char **cmd, int num_parts) { struct msn_switchboard *sb = handler->data; struct im_connection *ic = sb->ic; char *body; - - if( !num_parts ) - return( 1 ); - - if( ( body = strstr( msg, "\r\n\r\n" ) ) ) + + if (!num_parts) { + return(1); + } + + if ((body = strstr(msg, "\r\n\r\n"))) { body += 4; - - if( strcmp( cmd[0], "MSG" ) == 0 ) - { - char *ct = get_rfc822_header( msg, "Content-Type:", msglen ); - - if( !ct ) - return( 1 ); - - if( g_strncasecmp( ct, "text/plain", 10 ) == 0 ) - { - g_free( ct ); - - if( !body ) - return( 1 ); - - if( sb->who ) - { - imcb_buddy_msg( ic, cmd[1], body, 0, 0 ); - } - else if( sb->chat ) - { - imcb_chat_msg( sb->chat, cmd[1], body, 0, 0 ); + } + + if (strcmp(cmd[0], "MSG") == 0) { + char *ct = get_rfc822_header(msg, "Content-Type:", msglen); + + if (!ct) { + return(1); + } + + if (g_strncasecmp(ct, "text/plain", 10) == 0) { + g_free(ct); + + if (!body) { + return(1); } - else - { + + if (sb->who) { + imcb_buddy_msg(ic, cmd[1], body, 0, 0); + } else if (sb->chat) { + imcb_chat_msg(sb->chat, cmd[1], body, 0, 0); + } else { /* PANIC! */ } } #if 0 // Disable MSN ft support for now. - else if( g_strncasecmp( ct, "text/x-msmsgsinvite", 19 ) == 0 ) - { - char *command = get_rfc822_header( body, "Invitation-Command:", blen ); - char *cookie = get_rfc822_header( body, "Invitation-Cookie:", blen ); + else if (g_strncasecmp(ct, "text/x-msmsgsinvite", 19) == 0) { + char *command = get_rfc822_header(body, "Invitation-Command:", blen); + char *cookie = get_rfc822_header(body, "Invitation-Cookie:", blen); unsigned int icookie; - - g_free( ct ); - + + g_free(ct); + /* Every invite should have both a Command and Cookie header */ - if( !command || !cookie ) { - g_free( command ); - g_free( cookie ); - imcb_log( ic, "Warning: No command or cookie from %s", sb->who ); + if (!command || !cookie) { + g_free(command); + g_free(cookie); + imcb_log(ic, "Warning: No command or cookie from %s", sb->who); return 1; } - - icookie = strtoul( cookie, NULL, 10 ); - g_free( cookie ); - - if( g_strncasecmp( command, "INVITE", 6 ) == 0 ) { - msn_invitation_invite( sb, cmd[1], icookie, body, blen ); - } else if( g_strncasecmp( command, "ACCEPT", 6 ) == 0 ) { - msn_invitation_accept( sb, cmd[1], icookie, body, blen ); - } else if( g_strncasecmp( command, "CANCEL", 6 ) == 0 ) { - msn_invitation_cancel( sb, cmd[1], icookie, body, blen ); + + icookie = strtoul(cookie, NULL, 10); + g_free(cookie); + + if (g_strncasecmp(command, "INVITE", 6) == 0) { + msn_invitation_invite(sb, cmd[1], icookie, body, blen); + } else if (g_strncasecmp(command, "ACCEPT", 6) == 0) { + msn_invitation_accept(sb, cmd[1], icookie, body, blen); + } else if (g_strncasecmp(command, "CANCEL", 6) == 0) { + msn_invitation_cancel(sb, cmd[1], icookie, body, blen); } else { - imcb_log( ic, "Warning: Received invalid invitation with " - "command %s from %s", command, sb->who ); + imcb_log(ic, "Warning: Received invalid invitation with " + "command %s from %s", command, sb->who); } - - g_free( command ); + + g_free(command); } #endif - else if( g_strncasecmp( ct, "application/x-msnmsgrp2p", 24 ) == 0 ) - { + else if (g_strncasecmp(ct, "application/x-msnmsgrp2p", 24) == 0) { /* Not currently implemented. Don't warn about it since this seems to be used for avatars now. */ - g_free( ct ); - } - else if( g_strncasecmp( ct, "text/x-msmsgscontrol", 20 ) == 0 ) - { - char *who = get_rfc822_header( msg, "TypingUser:", msglen ); - - if( who ) - { - imcb_buddy_typing( ic, who, OPT_TYPING ); - g_free( who ); + g_free(ct); + } else if (g_strncasecmp(ct, "text/x-msmsgscontrol", 20) == 0) { + char *who = get_rfc822_header(msg, "TypingUser:", msglen); + + if (who) { + imcb_buddy_typing(ic, who, OPT_TYPING); + g_free(who); } - - g_free( ct ); - } - else - { - g_free( ct ); + + g_free(ct); + } else { + g_free(ct); } } - - return( 1 ); + + return(1); } -static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond ) +static gboolean msn_sb_keepalive(gpointer data, gint source, b_input_condition cond) { struct msn_switchboard *sb = data; - return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE ); + + return sb->ready && msn_sb_sendmessage(sb, SB_KEEPALIVE_MESSAGE); } -void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ) +void msn_sb_start_keepalives(struct msn_switchboard *sb, gboolean initial) { bee_user_t *bu; - - if( sb && sb->who && sb->keepalive == 0 && - ( bu = bee_user_by_handle( sb->ic->bee, sb->ic, sb->who ) ) && - !( bu->flags & BEE_USER_ONLINE ) && - set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) ) - { - if( initial ) - msn_sb_keepalive( sb, 0, 0 ); - - sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb ); + + if (sb && sb->who && sb->keepalive == 0 && + (bu = bee_user_by_handle(sb->ic->bee, sb->ic, sb->who)) && + !(bu->flags & BEE_USER_ONLINE) && + set_getbool(&sb->ic->acc->set, "switchboard_keepalives")) { + if (initial) { + msn_sb_keepalive(sb, 0, 0); + } + + sb->keepalive = b_timeout_add(20000, msn_sb_keepalive, sb); } } -void msn_sb_stop_keepalives( struct msn_switchboard *sb ) +void msn_sb_stop_keepalives(struct msn_switchboard *sb) { - if( sb && sb->keepalive > 0 ) - { - b_event_remove( sb->keepalive ); + if (sb && sb->keepalive > 0) { + b_event_remove(sb->keepalive); sb->keepalive = 0; } } diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c index 175b4546..f948decb 100644 --- a/protocols/msn/soap.c +++ b/protocols/msn/soap.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -43,8 +43,7 @@ parts of the response, and a function to run when the full response was received and parsed. See the various examples below. */ -typedef enum -{ +typedef enum { MSN_SOAP_OK, MSN_SOAP_RETRY, MSN_SOAP_REAUTH, @@ -52,35 +51,34 @@ typedef enum } msn_soap_result_t; struct msn_soap_req_data; -typedef int (*msn_soap_func) ( struct msn_soap_req_data * ); +typedef int (*msn_soap_func) (struct msn_soap_req_data *); -struct msn_soap_req_data -{ +struct msn_soap_req_data { void *data; struct im_connection *ic; int ttl; char *error; - + char *url, *action, *payload; struct http_request *http_req; - + const struct xt_handler_entry *xml_parser; msn_soap_func build_request, handle_response, free_data; }; -static int msn_soap_send_request( struct msn_soap_req_data *req ); -static void msn_soap_free( struct msn_soap_req_data *soap_req ); -static void msn_soap_debug_print( const char *headers, const char *payload ); +static int msn_soap_send_request(struct msn_soap_req_data *req); +static void msn_soap_free(struct msn_soap_req_data *soap_req); +static void msn_soap_debug_print(const char *headers, const char *payload); -static int msn_soap_start( struct im_connection *ic, - void *data, - msn_soap_func build_request, - const struct xt_handler_entry *xml_parser, - msn_soap_func handle_response, - msn_soap_func free_data ) +static int msn_soap_start(struct im_connection *ic, + void *data, + msn_soap_func build_request, + const struct xt_handler_entry *xml_parser, + msn_soap_func handle_response, + msn_soap_func free_data) { - struct msn_soap_req_data *req = g_new0( struct msn_soap_req_data, 1 ); - + struct msn_soap_req_data *req = g_new0(struct msn_soap_req_data, 1); + req->ic = ic; req->data = data; req->xml_parser = xml_parser; @@ -88,199 +86,190 @@ static int msn_soap_start( struct im_connection *ic, req->handle_response = handle_response; req->free_data = free_data; req->ttl = 3; - - return msn_soap_send_request( req ); + + return msn_soap_send_request(req); } -static void msn_soap_handle_response( struct http_request *http_req ); +static void msn_soap_handle_response(struct http_request *http_req); -static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_send_request(struct msn_soap_req_data *soap_req) { char *http_req; char *soap_action = NULL; url_t url; - - soap_req->build_request( soap_req ); - - if( soap_req->action ) - soap_action = g_strdup_printf( "SOAPAction: \"%s\"\r\n", soap_req->action ); - - url_set( &url, soap_req->url ); - http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host, - soap_action ? soap_action : "", - strlen( soap_req->payload ), soap_req->payload ); - - msn_soap_debug_print( http_req, soap_req->payload ); - - soap_req->http_req = http_dorequest( url.host, url.port, url.proto == PROTO_HTTPS, - http_req, msn_soap_handle_response, soap_req ); - - g_free( http_req ); - g_free( soap_action ); - + + soap_req->build_request(soap_req); + + if (soap_req->action) { + soap_action = g_strdup_printf("SOAPAction: \"%s\"\r\n", soap_req->action); + } + + url_set(&url, soap_req->url); + http_req = g_strdup_printf(SOAP_HTTP_REQUEST, url.file, url.host, + soap_action ? soap_action : "", + strlen(soap_req->payload), soap_req->payload); + + msn_soap_debug_print(http_req, soap_req->payload); + + soap_req->http_req = http_dorequest(url.host, url.port, url.proto == PROTO_HTTPS, + http_req, msn_soap_handle_response, soap_req); + + g_free(http_req); + g_free(soap_action); + return soap_req->http_req != NULL; } -static void msn_soap_handle_response( struct http_request *http_req ) +static void msn_soap_handle_response(struct http_request *http_req) { struct msn_soap_req_data *soap_req = http_req->data; int st; - - if( g_slist_find( msn_connections, soap_req->ic ) == NULL ) - { - msn_soap_free( soap_req ); + + if (g_slist_find(msn_connections, soap_req->ic) == NULL) { + msn_soap_free(soap_req); return; } - - msn_soap_debug_print( http_req->reply_headers, http_req->reply_body ); - - if( http_req->body_size > 0 ) - { + + msn_soap_debug_print(http_req->reply_headers, http_req->reply_body); + + if (http_req->body_size > 0) { struct xt_parser *parser; struct xt_node *err; - - parser = xt_new( soap_req->xml_parser, soap_req ); - xt_feed( parser, http_req->reply_body, http_req->body_size ); - if( http_req->status_code == 500 && - ( err = xt_find_path( parser->root, "soap:Body/soap:Fault/detail/errorcode" ) ) && - err->text_len > 0 ) - { - if( strcmp( err->text, "PassportAuthFail" ) == 0 ) - { - xt_free( parser ); + + parser = xt_new(soap_req->xml_parser, soap_req); + xt_feed(parser, http_req->reply_body, http_req->body_size); + if (http_req->status_code == 500 && + (err = xt_find_path(parser->root, "soap:Body/soap:Fault/detail/errorcode")) && + err->text_len > 0) { + if (strcmp(err->text, "PassportAuthFail") == 0) { + xt_free(parser); st = MSN_SOAP_REAUTH; goto fail; } /* TODO: Handle/report other errors. */ } - - xt_handle( parser, NULL, -1 ); - xt_free( parser ); + + xt_handle(parser, NULL, -1); + xt_free(parser); } - - if( http_req->status_code != 200 ) - soap_req->error = g_strdup( http_req->status_string ); - - st = soap_req->handle_response( soap_req ); - -fail: - g_free( soap_req->url ); - g_free( soap_req->action ); - g_free( soap_req->payload ); - g_free( soap_req->error ); - soap_req->url = soap_req->action = soap_req->payload = soap_req->error = NULL; - - if( st == MSN_SOAP_RETRY && --soap_req->ttl ) - { - msn_soap_send_request( soap_req ); + + if (http_req->status_code != 200) { + soap_req->error = g_strdup(http_req->status_string); } - else if( st == MSN_SOAP_REAUTH ) - { + + st = soap_req->handle_response(soap_req); + +fail: + g_free(soap_req->url); + g_free(soap_req->action); + g_free(soap_req->payload); + g_free(soap_req->error); + soap_req->url = soap_req->action = soap_req->payload = soap_req->error = NULL; + + if (st == MSN_SOAP_RETRY && --soap_req->ttl) { + msn_soap_send_request(soap_req); + } else if (st == MSN_SOAP_REAUTH) { struct msn_data *md = soap_req->ic->proto_data; - - if( !( md->flags & MSN_REAUTHING ) ) - { + + if (!(md->flags & MSN_REAUTHING)) { /* Nonce shouldn't actually be touched for re-auths. */ - msn_soap_passport_sso_request( soap_req->ic, "blaataap" ); - md->flags |= MSN_REAUTHING; + msn_soap_passport_sso_request(soap_req->ic, "blaataap"); + md->flags |= MSN_REAUTHING; } - md->soapq = g_slist_append( md->soapq, soap_req ); - } - else - { - soap_req->free_data( soap_req ); - g_free( soap_req ); + md->soapq = g_slist_append(md->soapq, soap_req); + } else { + soap_req->free_data(soap_req); + g_free(soap_req); } } -static char *msn_soap_abservice_build( const char *body_fmt, const char *scenario, const char *ticket, ... ) +static char *msn_soap_abservice_build(const char *body_fmt, const char *scenario, const char *ticket, ...) { va_list params; char *ret, *format, *body; - - format = g_markup_printf_escaped( SOAP_ABSERVICE_PAYLOAD, scenario, ticket ); - - va_start( params, ticket ); - body = g_strdup_vprintf( body_fmt, params ); - va_end( params ); - - ret = g_strdup_printf( format, body ); - g_free( body ); - g_free( format ); - + + format = g_markup_printf_escaped(SOAP_ABSERVICE_PAYLOAD, scenario, ticket); + + va_start(params, ticket); + body = g_strdup_vprintf(body_fmt, params); + va_end(params); + + ret = g_strdup_printf(format, body); + g_free(body); + g_free(format); + return ret; } -static void msn_soap_debug_print( const char *headers, const char *payload ) +static void msn_soap_debug_print(const char *headers, const char *payload) { char *s; - - if( !getenv( "BITLBEE_DEBUG" ) ) + + if (!getenv("BITLBEE_DEBUG")) { return; - - if( headers ) - { - if( ( s = strstr( headers, "\r\n\r\n" ) ) ) - write( 2, headers, s - headers + 4 ); - else - write( 2, headers, strlen( headers ) ); } - - if( payload ) - { - struct xt_node *xt = xt_from_string( payload, 0 ); - if( xt ) - xt_print( xt ); - xt_free_node( xt ); + + if (headers) { + if ((s = strstr(headers, "\r\n\r\n"))) { + write(2, headers, s - headers + 4); + } else { + write(2, headers, strlen(headers)); + } + } + + if (payload) { + struct xt_node *xt = xt_from_string(payload, 0); + if (xt) { + xt_print(xt); + } + xt_free_node(xt); } } -int msn_soapq_flush( struct im_connection *ic, gboolean resend ) +int msn_soapq_flush(struct im_connection *ic, gboolean resend) { struct msn_data *md = ic->proto_data; - - while( md->soapq ) - { - if( resend ) - msn_soap_send_request( (struct msn_soap_req_data*) md->soapq->data ); - else - msn_soap_free( (struct msn_soap_req_data*) md->soapq->data ); - md->soapq = g_slist_remove( md->soapq, md->soapq->data ); + + while (md->soapq) { + if (resend) { + msn_soap_send_request((struct msn_soap_req_data*) md->soapq->data); + } else { + msn_soap_free((struct msn_soap_req_data*) md->soapq->data); + } + md->soapq = g_slist_remove(md->soapq, md->soapq->data); } - + return MSN_SOAP_OK; } -static void msn_soap_free( struct msn_soap_req_data *soap_req ) +static void msn_soap_free(struct msn_soap_req_data *soap_req) { - soap_req->free_data( soap_req ); - g_free( soap_req->url ); - g_free( soap_req->action ); - g_free( soap_req->payload ); - g_free( soap_req->error ); - g_free( soap_req ); + soap_req->free_data(soap_req); + g_free(soap_req->url); + g_free(soap_req->action); + g_free(soap_req->payload); + g_free(soap_req->error); + g_free(soap_req); } /* passport_sso: Authentication MSNP15+ */ -struct msn_soap_passport_sso_data -{ +struct msn_soap_passport_sso_data { char *nonce; char *secret; char *error; char *redirect; }; -static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_passport_sso_build_request(struct msn_soap_req_data *soap_req) { struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; struct msn_data *md = ic->proto_data; - char pass[MAX_PASSPORT_PWLEN+1]; - - if( sd->redirect ) - { + char pass[MAX_PASSPORT_PWLEN + 1]; + + if (sd->redirect) { soap_req->url = sd->redirect; sd->redirect = NULL; } @@ -288,63 +277,66 @@ static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_r one works, forwarding us to a msn.com URL that works. Takes an extra second, but that's better than not being able to log in at all. :-/ else if( g_str_has_suffix( ic->acc->user, "@msn.com" ) ) - soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL_MSN ); + soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL_MSN ); */ - else - soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); - - strncpy( pass, ic->acc->pass, MAX_PASSPORT_PWLEN ); + else { + soap_req->url = g_strdup(SOAP_PASSPORT_SSO_URL); + } + + strncpy(pass, ic->acc->pass, MAX_PASSPORT_PWLEN); pass[MAX_PASSPORT_PWLEN] = '\0'; - soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD, - ic->acc->user, pass, md->pp_policy ); - + soap_req->payload = g_markup_printf_escaped(SOAP_PASSPORT_SSO_PAYLOAD, + ic->acc->user, pass, md->pp_policy); + return MSN_SOAP_OK; } -static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer data ) +static xt_status msn_soap_passport_sso_token(struct xt_node *node, gpointer data) { struct msn_soap_req_data *soap_req = data; struct msn_soap_passport_sso_data *sd = soap_req->data; struct msn_data *md = soap_req->ic->proto_data; struct xt_node *p; char *id; - - if( ( id = xt_find_attr( node, "Id" ) ) == NULL ) + + if ((id = xt_find_attr(node, "Id")) == NULL) { return XT_HANDLED; - id += strlen( id ) - 1; - if( *id == '1' && - ( p = xt_find_path( node, "../../wst:RequestedProofToken/wst:BinarySecret" ) ) && - p->text ) - sd->secret = g_strdup( p->text ); - + } + id += strlen(id) - 1; + if (*id == '1' && + (p = xt_find_path(node, "../../wst:RequestedProofToken/wst:BinarySecret")) && + p->text) { + sd->secret = g_strdup(p->text); + } + *id -= '1'; - if( *id >= 0 && *id < sizeof( md->tokens ) / sizeof( md->tokens[0] ) ) - { - g_free( md->tokens[(int)*id] ); - md->tokens[(int)*id] = g_strdup( node->text ); + if (*id >= 0 && *id < sizeof(md->tokens) / sizeof(md->tokens[0])) { + g_free(md->tokens[(int) *id]); + md->tokens[(int) *id] = g_strdup(node->text); } - + return XT_HANDLED; } -static xt_status msn_soap_passport_failure( struct xt_node *node, gpointer data ) +static xt_status msn_soap_passport_failure(struct xt_node *node, gpointer data) { struct msn_soap_req_data *soap_req = data; struct msn_soap_passport_sso_data *sd = soap_req->data; - struct xt_node *code = xt_find_node( node->children, "faultcode" ); - struct xt_node *string = xt_find_node( node->children, "faultstring" ); + struct xt_node *code = xt_find_node(node->children, "faultcode"); + struct xt_node *string = xt_find_node(node->children, "faultstring"); struct xt_node *url; - - if( code == NULL || code->text_len == 0 ) - sd->error = g_strdup( "Unknown error" ); - else if( strcmp( code->text, "psf:Redirect" ) == 0 && - ( url = xt_find_node( node->children, "psf:redirectUrl" ) ) && - url->text_len > 0 ) - sd->redirect = g_strdup( url->text ); - else - sd->error = g_strdup_printf( "%s (%s)", code->text, string && string->text_len ? - string->text : "no description available" ); - + + if (code == NULL || code->text_len == 0) { + sd->error = g_strdup("Unknown error"); + } else if (strcmp(code->text, "psf:Redirect") == 0 && + (url = xt_find_node(node->children, "psf:redirectUrl")) && + url->text_len > 0) { + sd->redirect = g_strdup(url->text); + } else { + sd->error = g_strdup_printf("%s (%s)", code->text, string && string->text_len ? + string->text : "no description available"); + } + return XT_HANDLED; } @@ -354,27 +346,27 @@ static const struct xt_handler_entry msn_soap_passport_sso_parser[] = { { NULL, NULL, NULL } }; -static char *msn_key_fuckery( char *key, int key_len, char *type ) +static char *msn_key_fuckery(char *key, int key_len, char *type) { - unsigned char hash1[20+strlen(type)+1]; + unsigned char hash1[20 + strlen(type) + 1]; unsigned char hash2[20]; char *ret; - - sha1_hmac( key, key_len, type, 0, hash1 ); - strcpy( (char*) hash1 + 20, type ); - sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash2 ); - + + sha1_hmac(key, key_len, type, 0, hash1); + strcpy((char *) hash1 + 20, type); + sha1_hmac(key, key_len, (char *) hash1, sizeof(hash1) - 1, hash2); + /* This is okay as hash1 is read completely before it's overwritten. */ - sha1_hmac( key, key_len, (char*) hash1, 20, hash1 ); - sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash1 ); - - ret = g_malloc( 24 ); - memcpy( ret, hash2, 20 ); - memcpy( ret + 20, hash1, 4 ); + sha1_hmac(key, key_len, (char *) hash1, 20, hash1); + sha1_hmac(key, key_len, (char *) hash1, sizeof(hash1) - 1, hash1); + + ret = g_malloc(24); + memcpy(ret, hash2, 20); + memcpy(ret + 20, hash1, 4); return ret; } -static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_passport_sso_handle_response(struct msn_soap_req_data *soap_req) { struct msn_soap_passport_sso_data *sd = soap_req->data; struct im_connection *ic = soap_req->ic; @@ -382,8 +374,8 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap char *key1, *key2, *key3, *blurb64; int key1_len; unsigned char *padnonce, *des3res; - struct - { + + struct { unsigned int uStructHeaderSize; // 28. Does not count data unsigned int uCryptMode; // CRYPT_MODE_CBC (1) unsigned int uCipherType; // TripleDES (0x6603) @@ -395,98 +387,97 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap unsigned char hash[20]; unsigned char cipherbytes[72]; } blurb = { - GUINT32_TO_LE( 28 ), - GUINT32_TO_LE( 1 ), - GUINT32_TO_LE( 0x6603 ), - GUINT32_TO_LE( 0x8004 ), - GUINT32_TO_LE( 8 ), - GUINT32_TO_LE( 20 ), - GUINT32_TO_LE( 72 ), + GUINT32_TO_LE(28), + GUINT32_TO_LE(1), + GUINT32_TO_LE(0x6603), + GUINT32_TO_LE(0x8004), + GUINT32_TO_LE(8), + GUINT32_TO_LE(20), + GUINT32_TO_LE(72), }; - - if( sd->redirect ) + + if (sd->redirect) { return MSN_SOAP_RETRY; - - if( md->soapq ) - { - md->flags &= ~MSN_REAUTHING; - return msn_soapq_flush( ic, TRUE ); } - - if( sd->secret == NULL ) - { - msn_auth_got_passport_token( ic, NULL, sd->error ? sd->error : soap_req->error ); + + if (md->soapq) { + md->flags &= ~MSN_REAUTHING; + return msn_soapq_flush(ic, TRUE); + } + + if (sd->secret == NULL) { + msn_auth_got_passport_token(ic, NULL, sd->error ? sd->error : soap_req->error); return MSN_SOAP_OK; } - key1_len = base64_decode( sd->secret, (unsigned char**) &key1 ); - - key2 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY HASH" ); - key3 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION" ); - - sha1_hmac( key2, 24, sd->nonce, 0, blurb.hash ); - padnonce = g_malloc( strlen( sd->nonce ) + 8 ); - strcpy( (char*) padnonce, sd->nonce ); - memset( padnonce + strlen( sd->nonce ), 8, 8 ); - - random_bytes( blurb.iv, 8 ); - - ssl_des3_encrypt( (unsigned char*) key3, 24, padnonce, strlen( sd->nonce ) + 8, blurb.iv, &des3res ); - memcpy( blurb.cipherbytes, des3res, 72 ); - - blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) ); - msn_auth_got_passport_token( ic, blurb64, NULL ); - - g_free( padnonce ); - g_free( blurb64 ); - g_free( des3res ); - g_free( key1 ); - g_free( key2 ); - g_free( key3 ); - + key1_len = base64_decode(sd->secret, (unsigned char **) &key1); + + key2 = msn_key_fuckery(key1, key1_len, "WS-SecureConversationSESSION KEY HASH"); + key3 = msn_key_fuckery(key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION"); + + sha1_hmac(key2, 24, sd->nonce, 0, blurb.hash); + padnonce = g_malloc(strlen(sd->nonce) + 8); + strcpy((char *) padnonce, sd->nonce); + memset(padnonce + strlen(sd->nonce), 8, 8); + + random_bytes(blurb.iv, 8); + + ssl_des3_encrypt((unsigned char *) key3, 24, padnonce, strlen(sd->nonce) + 8, blurb.iv, &des3res); + memcpy(blurb.cipherbytes, des3res, 72); + + blurb64 = base64_encode((unsigned char *) &blurb, sizeof(blurb)); + msn_auth_got_passport_token(ic, blurb64, NULL); + + g_free(padnonce); + g_free(blurb64); + g_free(des3res); + g_free(key1); + g_free(key2); + g_free(key3); + return MSN_SOAP_OK; } -static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_passport_sso_free_data(struct msn_soap_req_data *soap_req) { struct msn_soap_passport_sso_data *sd = soap_req->data; - - g_free( sd->nonce ); - g_free( sd->secret ); - g_free( sd->error ); - g_free( sd->redirect ); - g_free( sd ); - + + g_free(sd->nonce); + g_free(sd->secret); + g_free(sd->error); + g_free(sd->redirect); + g_free(sd); + return MSN_SOAP_OK; } -int msn_soap_passport_sso_request( struct im_connection *ic, const char *nonce ) +int msn_soap_passport_sso_request(struct im_connection *ic, const char *nonce) { - struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 ); - - sd->nonce = g_strdup( nonce ); - - return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request, - msn_soap_passport_sso_parser, - msn_soap_passport_sso_handle_response, - msn_soap_passport_sso_free_data ); + struct msn_soap_passport_sso_data *sd = g_new0(struct msn_soap_passport_sso_data, 1); + + sd->nonce = g_strdup(nonce); + + return msn_soap_start(ic, sd, msn_soap_passport_sso_build_request, + msn_soap_passport_sso_parser, + msn_soap_passport_sso_handle_response, + msn_soap_passport_sso_free_data); } /* memlist: Fetching the membership list (NOT address book) */ -static int msn_soap_memlist_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - - soap_req->url = g_strdup( SOAP_MEMLIST_URL ); - soap_req->action = g_strdup( SOAP_MEMLIST_ACTION ); - soap_req->payload = msn_soap_abservice_build( SOAP_MEMLIST_PAYLOAD, "Initial", md->tokens[1] ); - + + soap_req->url = g_strdup(SOAP_MEMLIST_URL); + soap_req->action = g_strdup(SOAP_MEMLIST_ACTION); + soap_req->payload = msn_soap_abservice_build(SOAP_MEMLIST_PAYLOAD, "Initial", md->tokens[1]); + return 1; } -static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) +static xt_status msn_soap_memlist_member(struct xt_node *node, gpointer data) { bee_user_t *bu; struct msn_buddy_data *bd; @@ -494,37 +485,38 @@ static xt_status msn_soap_memlist_member( struct xt_node *node, gpointer data ) char *role = NULL, *handle = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; - - if( ( p = xt_find_path( node, "../../MemberRole" ) ) ) + + if ((p = xt_find_path(node, "../../MemberRole"))) { role = p->text; - - if( ( p = xt_find_node( node->children, "PassportName" ) ) ) + } + + if ((p = xt_find_node(node->children, "PassportName"))) { handle = p->text; - - if( !role || !handle || - !( ( bu = bee_user_by_handle( ic->bee, ic, handle ) ) || - ( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) ) + } + + if (!role || !handle || + !((bu = bee_user_by_handle(ic->bee, ic, handle)) || + (bu = bee_user_new(ic->bee, ic, handle, 0)))) { return XT_HANDLED; - + } + bd = bu->data; - if( strcmp( role, "Allow" ) == 0 ) - { + if (strcmp(role, "Allow") == 0) { bd->flags |= MSN_BUDDY_AL; - ic->permit = g_slist_prepend( ic->permit, g_strdup( handle ) ); - } - else if( strcmp( role, "Block" ) == 0 ) - { + ic->permit = g_slist_prepend(ic->permit, g_strdup(handle)); + } else if (strcmp(role, "Block") == 0) { bd->flags |= MSN_BUDDY_BL; - ic->deny = g_slist_prepend( ic->deny, g_strdup( handle ) ); - } - else if( strcmp( role, "Reverse" ) == 0 ) + ic->deny = g_slist_prepend(ic->deny, g_strdup(handle)); + } else if (strcmp(role, "Reverse") == 0) { bd->flags |= MSN_BUDDY_RL; - else if( strcmp( role, "Pending" ) == 0 ) + } else if (strcmp(role, "Pending") == 0) { bd->flags |= MSN_BUDDY_PL; - - if( getenv( "BITLBEE_DEBUG" ) ) - fprintf( stderr, "%p %s %d\n", bu, handle, bd->flags ); - + } + + if (getenv("BITLBEE_DEBUG")) { + fprintf(stderr, "%p %s %d\n", bu, handle, bd->flags); + } + return XT_HANDLED; } @@ -533,53 +525,48 @@ static const struct xt_handler_entry msn_soap_memlist_parser[] = { { NULL, NULL, NULL } }; -static int msn_soap_memlist_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_handle_response(struct msn_soap_req_data *soap_req) { - msn_soap_addressbook_request( soap_req->ic ); - + msn_soap_addressbook_request(soap_req->ic); + return MSN_SOAP_OK; } -static int msn_soap_memlist_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_free_data(struct msn_soap_req_data *soap_req) { return 0; } -int msn_soap_memlist_request( struct im_connection *ic ) +int msn_soap_memlist_request(struct im_connection *ic) { - return msn_soap_start( ic, NULL, msn_soap_memlist_build_request, - msn_soap_memlist_parser, - msn_soap_memlist_handle_response, - msn_soap_memlist_free_data ); + return msn_soap_start(ic, NULL, msn_soap_memlist_build_request, + msn_soap_memlist_parser, + msn_soap_memlist_handle_response, + msn_soap_memlist_free_data); } /* Variant: Adding/Removing people */ -struct msn_soap_memlist_edit_data -{ +struct msn_soap_memlist_edit_data { char *handle; gboolean add; msn_buddy_flags_t list; }; -static int msn_soap_memlist_edit_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_edit_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; struct msn_soap_memlist_edit_data *med = soap_req->data; char *add, *scenario, *list; - - soap_req->url = g_strdup( SOAP_MEMLIST_URL ); - if( med->add ) - { - soap_req->action = g_strdup( SOAP_MEMLIST_ADD_ACTION ); + + soap_req->url = g_strdup(SOAP_MEMLIST_URL); + if (med->add) { + soap_req->action = g_strdup(SOAP_MEMLIST_ADD_ACTION); add = "Add"; - } - else - { - soap_req->action = g_strdup( SOAP_MEMLIST_DEL_ACTION ); + } else { + soap_req->action = g_strdup(SOAP_MEMLIST_DEL_ACTION); add = "Delete"; } - switch( med->list ) - { + switch (med->list) { case MSN_BUDDY_AL: scenario = "BlockUnblock"; list = "Allow"; @@ -598,141 +585,153 @@ static int msn_soap_memlist_edit_build_request( struct msn_soap_req_data *soap_r list = "Pending"; break; } - soap_req->payload = msn_soap_abservice_build( SOAP_MEMLIST_EDIT_PAYLOAD, - scenario, md->tokens[1], add, list, med->handle, add ); - + soap_req->payload = msn_soap_abservice_build(SOAP_MEMLIST_EDIT_PAYLOAD, + scenario, md->tokens[1], add, list, med->handle, add); + return 1; } -static int msn_soap_memlist_edit_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_edit_handle_response(struct msn_soap_req_data *soap_req) { return MSN_SOAP_OK; } -static int msn_soap_memlist_edit_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_memlist_edit_free_data(struct msn_soap_req_data *soap_req) { struct msn_soap_memlist_edit_data *med = soap_req->data; - - g_free( med->handle ); - g_free( med ); - + + g_free(med->handle); + g_free(med); + return 0; } -int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list ) +int msn_soap_memlist_edit(struct im_connection *ic, const char *handle, gboolean add, int list) { struct msn_soap_memlist_edit_data *med; - - med = g_new0( struct msn_soap_memlist_edit_data, 1 ); - med->handle = g_strdup( handle ); + + med = g_new0(struct msn_soap_memlist_edit_data, 1); + med->handle = g_strdup(handle); med->add = add; med->list = list; - - return msn_soap_start( ic, med, msn_soap_memlist_edit_build_request, - NULL, - msn_soap_memlist_edit_handle_response, - msn_soap_memlist_edit_free_data ); + + return msn_soap_start(ic, med, msn_soap_memlist_edit_build_request, + NULL, + msn_soap_memlist_edit_handle_response, + msn_soap_memlist_edit_free_data); } /* addressbook: Fetching the membership list (NOT address book) */ -static int msn_soap_addressbook_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_addressbook_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - - soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); - soap_req->action = g_strdup( SOAP_ADDRESSBOOK_ACTION ); - soap_req->payload = msn_soap_abservice_build( SOAP_ADDRESSBOOK_PAYLOAD, "Initial", md->tokens[1] ); - + + soap_req->url = g_strdup(SOAP_ADDRESSBOOK_URL); + soap_req->action = g_strdup(SOAP_ADDRESSBOOK_ACTION); + soap_req->payload = msn_soap_abservice_build(SOAP_ADDRESSBOOK_PAYLOAD, "Initial", md->tokens[1]); + return 1; } -static xt_status msn_soap_addressbook_group( struct xt_node *node, gpointer data ) +static xt_status msn_soap_addressbook_group(struct xt_node *node, gpointer data) { struct xt_node *p; char *id = NULL, *name = NULL; struct msn_soap_req_data *soap_req = data; struct msn_data *md = soap_req->ic->proto_data; - - if( ( p = xt_find_path( node, "../groupId" ) ) ) + + if ((p = xt_find_path(node, "../groupId"))) { id = p->text; - - if( ( p = xt_find_node( node->children, "name" ) ) ) + } + + if ((p = xt_find_node(node->children, "name"))) { name = p->text; - - if( id && name ) - { - struct msn_group *mg = g_new0( struct msn_group, 1 ); - mg->id = g_strdup( id ); - mg->name = g_strdup( name ); - md->groups = g_slist_prepend( md->groups, mg ); } - - if( getenv( "BITLBEE_DEBUG" ) ) - fprintf( stderr, "%s %s\n", id, name ); - + + if (id && name) { + struct msn_group *mg = g_new0(struct msn_group, 1); + mg->id = g_strdup(id); + mg->name = g_strdup(name); + md->groups = g_slist_prepend(md->groups, mg); + } + + if (getenv("BITLBEE_DEBUG")) { + fprintf(stderr, "%s %s\n", id, name); + } + return XT_HANDLED; } -static xt_status msn_soap_addressbook_contact( struct xt_node *node, gpointer data ) +static xt_status msn_soap_addressbook_contact(struct xt_node *node, gpointer data) { bee_user_t *bu; struct msn_buddy_data *bd; struct xt_node *p; char *id = NULL, *type = NULL, *handle = NULL, *is_msgr = "false", - *display_name = NULL, *group_id = NULL; + *display_name = NULL, *group_id = NULL; struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; struct msn_group *group; - - if( ( p = xt_find_path( node, "../contactId" ) ) ) + + if ((p = xt_find_path(node, "../contactId"))) { id = p->text; - if( ( p = xt_find_node( node->children, "contactType" ) ) ) + } + if ((p = xt_find_node(node->children, "contactType"))) { type = p->text; - if( ( p = xt_find_node( node->children, "passportName" ) ) ) + } + if ((p = xt_find_node(node->children, "passportName"))) { handle = p->text; - if( ( p = xt_find_node( node->children, "displayName" ) ) ) + } + if ((p = xt_find_node(node->children, "displayName"))) { display_name = p->text; - if( ( p = xt_find_node( node->children, "isMessengerUser" ) ) ) + } + if ((p = xt_find_node(node->children, "isMessengerUser"))) { is_msgr = p->text; - if( ( p = xt_find_path( node, "groupIds/guid" ) ) ) + } + if ((p = xt_find_path(node, "groupIds/guid"))) { group_id = p->text; - - if( type && g_strcasecmp( type, "me" ) == 0 ) - { - set_t *set = set_find( &ic->acc->set, "display_name" ); - g_free( set->value ); - set->value = g_strdup( display_name ); - + } + + if (type && g_strcasecmp(type, "me") == 0) { + set_t *set = set_find(&ic->acc->set, "display_name"); + g_free(set->value); + set->value = g_strdup(display_name); + /* Try to fetch the profile; if the user has one, that's where we can find the persistent display_name. */ - if( ( p = xt_find_node( node->children, "CID" ) ) && p->text ) - msn_soap_profile_get( ic, p->text ); - + if ((p = xt_find_node(node->children, "CID")) && p->text) { + msn_soap_profile_get(ic, p->text); + } + return XT_HANDLED; } - - if( !bool2int( is_msgr ) || handle == NULL ) + + if (!bool2int(is_msgr) || handle == NULL) { return XT_HANDLED; - - if( !( bu = bee_user_by_handle( ic->bee, ic, handle ) ) && - !( bu = bee_user_new( ic->bee, ic, handle, 0 ) ) ) + } + + if (!(bu = bee_user_by_handle(ic->bee, ic, handle)) && + !(bu = bee_user_new(ic->bee, ic, handle, 0))) { return XT_HANDLED; - + } + bd = bu->data; bd->flags |= MSN_BUDDY_FL; - g_free( bd->cid ); - bd->cid = g_strdup( id ); - - imcb_rename_buddy( ic, handle, display_name ); - - if( group_id && ( group = msn_group_by_id( ic, group_id ) ) ) - imcb_add_buddy( ic, handle, group->name ); - - if( getenv( "BITLBEE_DEBUG" ) ) - fprintf( stderr, "%s %s %s %s\n", id, type, handle, display_name ); - + g_free(bd->cid); + bd->cid = g_strdup(id); + + imcb_rename_buddy(ic, handle, display_name); + + if (group_id && (group = msn_group_by_id(ic, group_id))) { + imcb_add_buddy(ic, handle, group->name); + } + + if (getenv("BITLBEE_DEBUG")) { + fprintf(stderr, "%s %s %s %s\n", id, type, handle, display_name); + } + return XT_HANDLED; } @@ -742,118 +741,116 @@ static const struct xt_handler_entry msn_soap_addressbook_parser[] = { { NULL, NULL, NULL } }; -static int msn_soap_addressbook_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_addressbook_handle_response(struct msn_soap_req_data *soap_req) { GSList *l; int wtf = 0; - - for( l = soap_req->ic->bee->users; l; l = l->next ) - { + + for (l = soap_req->ic->bee->users; l; l = l->next) { struct bee_user *bu = l->data; struct msn_buddy_data *bd = bu->data; - - if( bu->ic == soap_req->ic && bd ) - { - msn_buddy_ask( bu ); - - if( ( bd->flags & ( MSN_BUDDY_AL | MSN_BUDDY_BL ) ) == - ( MSN_BUDDY_AL | MSN_BUDDY_BL ) ) - { + + if (bu->ic == soap_req->ic && bd) { + msn_buddy_ask(bu); + + if ((bd->flags & (MSN_BUDDY_AL | MSN_BUDDY_BL)) == + (MSN_BUDDY_AL | MSN_BUDDY_BL)) { /* both allow and block, delete block, add wtf */ bd->flags &= ~MSN_BUDDY_BL; wtf++; } - if( ( bd->flags & ( MSN_BUDDY_AL | MSN_BUDDY_BL ) ) == 0 ) - { + if ((bd->flags & (MSN_BUDDY_AL | MSN_BUDDY_BL)) == 0) { /* neither allow or block, add allow */ bd->flags |= MSN_BUDDY_AL; } } } - - if( wtf ) - imcb_log( soap_req->ic, "Warning: %d contacts were in both your " - "block and your allow list. Assuming they're all " - "allowed. Use the official WLM client once to fix " - "this.", wtf ); - - msn_auth_got_contact_list( soap_req->ic ); - + + if (wtf) { + imcb_log(soap_req->ic, "Warning: %d contacts were in both your " + "block and your allow list. Assuming they're all " + "allowed. Use the official WLM client once to fix " + "this.", wtf); + } + + msn_auth_got_contact_list(soap_req->ic); + return MSN_SOAP_OK; } -static int msn_soap_addressbook_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_addressbook_free_data(struct msn_soap_req_data *soap_req) { return 0; } -int msn_soap_addressbook_request( struct im_connection *ic ) +int msn_soap_addressbook_request(struct im_connection *ic) { - return msn_soap_start( ic, NULL, msn_soap_addressbook_build_request, - msn_soap_addressbook_parser, - msn_soap_addressbook_handle_response, - msn_soap_addressbook_free_data ); + return msn_soap_start(ic, NULL, msn_soap_addressbook_build_request, + msn_soap_addressbook_parser, + msn_soap_addressbook_handle_response, + msn_soap_addressbook_free_data); } /* Variant: Change our display name. */ -static int msn_soap_ab_namechange_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_namechange_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - - soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); - soap_req->action = g_strdup( SOAP_AB_NAMECHANGE_ACTION ); - soap_req->payload = msn_soap_abservice_build( SOAP_AB_NAMECHANGE_PAYLOAD, - "Timer", md->tokens[1], (char *) soap_req->data ); - + + soap_req->url = g_strdup(SOAP_ADDRESSBOOK_URL); + soap_req->action = g_strdup(SOAP_AB_NAMECHANGE_ACTION); + soap_req->payload = msn_soap_abservice_build(SOAP_AB_NAMECHANGE_PAYLOAD, + "Timer", md->tokens[1], (char *) soap_req->data); + return 1; } -static int msn_soap_ab_namechange_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_namechange_handle_response(struct msn_soap_req_data *soap_req) { /* TODO: Ack the change? Not sure what the NAKs look like.. */ return MSN_SOAP_OK; } -static int msn_soap_ab_namechange_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_namechange_free_data(struct msn_soap_req_data *soap_req) { - g_free( soap_req->data ); + g_free(soap_req->data); return 0; } -int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ) +int msn_soap_addressbook_set_display_name(struct im_connection *ic, const char *new) { - return msn_soap_start( ic, g_strdup( new ), - msn_soap_ab_namechange_build_request, - NULL, - msn_soap_ab_namechange_handle_response, - msn_soap_ab_namechange_free_data ); + return msn_soap_start(ic, g_strdup(new), + msn_soap_ab_namechange_build_request, + NULL, + msn_soap_ab_namechange_handle_response, + msn_soap_ab_namechange_free_data); } /* Add a contact. */ -static int msn_soap_ab_contact_add_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_add_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; bee_user_t *bu = soap_req->data; - - soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); - soap_req->action = g_strdup( SOAP_AB_CONTACT_ADD_ACTION ); - soap_req->payload = msn_soap_abservice_build( SOAP_AB_CONTACT_ADD_PAYLOAD, - "ContactSave", md->tokens[1], bu->handle, bu->fullname ? bu->fullname : bu->handle ); - + + soap_req->url = g_strdup(SOAP_ADDRESSBOOK_URL); + soap_req->action = g_strdup(SOAP_AB_CONTACT_ADD_ACTION); + soap_req->payload = msn_soap_abservice_build(SOAP_AB_CONTACT_ADD_PAYLOAD, + "ContactSave", md->tokens[1], bu->handle, + bu->fullname ? bu->fullname : bu->handle); + return 1; } -static xt_status msn_soap_ab_contact_add_cid( struct xt_node *node, gpointer data ) +static xt_status msn_soap_ab_contact_add_cid(struct xt_node *node, gpointer data) { struct msn_soap_req_data *soap_req = data; bee_user_t *bu = soap_req->data; struct msn_buddy_data *bd = bu->data; - - g_free( bd->cid ); - bd->cid = g_strdup( node->text ); - + + g_free(bd->cid); + bd->cid = g_strdup(node->text); + return XT_HANDLED; } @@ -862,105 +859,104 @@ static const struct xt_handler_entry msn_soap_ab_contact_add_parser[] = { { NULL, NULL, NULL } }; -static int msn_soap_ab_contact_add_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_add_handle_response(struct msn_soap_req_data *soap_req) { /* TODO: Ack the change? Not sure what the NAKs look like.. */ return MSN_SOAP_OK; } -static int msn_soap_ab_contact_add_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_add_free_data(struct msn_soap_req_data *soap_req) { return 0; } -int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ) +int msn_soap_ab_contact_add(struct im_connection *ic, bee_user_t *bu) { - return msn_soap_start( ic, bu, - msn_soap_ab_contact_add_build_request, - msn_soap_ab_contact_add_parser, - msn_soap_ab_contact_add_handle_response, - msn_soap_ab_contact_add_free_data ); + return msn_soap_start(ic, bu, + msn_soap_ab_contact_add_build_request, + msn_soap_ab_contact_add_parser, + msn_soap_ab_contact_add_handle_response, + msn_soap_ab_contact_add_free_data); } /* Remove a contact. */ -static int msn_soap_ab_contact_del_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_del_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; const char *cid = soap_req->data; - - soap_req->url = g_strdup( SOAP_ADDRESSBOOK_URL ); - soap_req->action = g_strdup( SOAP_AB_CONTACT_DEL_ACTION ); - soap_req->payload = msn_soap_abservice_build( SOAP_AB_CONTACT_DEL_PAYLOAD, - "Timer", md->tokens[1], cid ); - + + soap_req->url = g_strdup(SOAP_ADDRESSBOOK_URL); + soap_req->action = g_strdup(SOAP_AB_CONTACT_DEL_ACTION); + soap_req->payload = msn_soap_abservice_build(SOAP_AB_CONTACT_DEL_PAYLOAD, + "Timer", md->tokens[1], cid); + return 1; } -static int msn_soap_ab_contact_del_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_del_handle_response(struct msn_soap_req_data *soap_req) { /* TODO: Ack the change? Not sure what the NAKs look like.. */ return MSN_SOAP_OK; } -static int msn_soap_ab_contact_del_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_ab_contact_del_free_data(struct msn_soap_req_data *soap_req) { - g_free( soap_req->data ); + g_free(soap_req->data); return 0; } -int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ) +int msn_soap_ab_contact_del(struct im_connection *ic, bee_user_t *bu) { struct msn_buddy_data *bd = bu->data; - - return msn_soap_start( ic, g_strdup( bd->cid ), - msn_soap_ab_contact_del_build_request, - NULL, - msn_soap_ab_contact_del_handle_response, - msn_soap_ab_contact_del_free_data ); + + return msn_soap_start(ic, g_strdup(bd->cid), + msn_soap_ab_contact_del_build_request, + NULL, + msn_soap_ab_contact_del_handle_response, + msn_soap_ab_contact_del_free_data); } /* Storage stuff: Fetch profile. */ -static int msn_soap_profile_get_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_get_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - - soap_req->url = g_strdup( SOAP_STORAGE_URL ); - soap_req->action = g_strdup( SOAP_PROFILE_GET_ACTION ); - soap_req->payload = g_markup_printf_escaped( SOAP_PROFILE_GET_PAYLOAD, - md->tokens[3], (char*) soap_req->data ); - + + soap_req->url = g_strdup(SOAP_STORAGE_URL); + soap_req->action = g_strdup(SOAP_PROFILE_GET_ACTION); + soap_req->payload = g_markup_printf_escaped(SOAP_PROFILE_GET_PAYLOAD, + md->tokens[3], (char *) soap_req->data); + return 1; } -static xt_status msn_soap_profile_get_result( struct xt_node *node, gpointer data ) +static xt_status msn_soap_profile_get_result(struct xt_node *node, gpointer data) { struct msn_soap_req_data *soap_req = data; struct im_connection *ic = soap_req->ic; struct msn_data *md = soap_req->ic->proto_data; struct xt_node *dn; - - if( ( dn = xt_find_node( node->children, "DisplayName" ) ) && dn->text ) - { - set_t *set = set_find( &ic->acc->set, "display_name" ); - g_free( set->value ); - set->value = g_strdup( dn->text ); - + + if ((dn = xt_find_node(node->children, "DisplayName")) && dn->text) { + set_t *set = set_find(&ic->acc->set, "display_name"); + g_free(set->value); + set->value = g_strdup(dn->text); + md->flags |= MSN_GOT_PROFILE_DN; } - + return XT_HANDLED; } -static xt_status msn_soap_profile_get_rid( struct xt_node *node, gpointer data ) +static xt_status msn_soap_profile_get_rid(struct xt_node *node, gpointer data) { struct msn_soap_req_data *soap_req = data; struct msn_data *md = soap_req->ic->proto_data; - - g_free( md->profile_rid ); - md->profile_rid = g_strdup( node->text ); - + + g_free(md->profile_rid); + md->profile_rid = g_strdup(node->text); + return XT_HANDLED; } @@ -970,41 +966,41 @@ static const struct xt_handler_entry msn_soap_profile_get_parser[] = { { NULL, NULL, NULL } }; -static int msn_soap_profile_get_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_get_handle_response(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - + md->flags |= MSN_GOT_PROFILE; - msn_ns_finish_login( soap_req->ic ); - + msn_ns_finish_login(soap_req->ic); + return MSN_SOAP_OK; } -static int msn_soap_profile_get_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_get_free_data(struct msn_soap_req_data *soap_req) { - g_free( soap_req->data ); + g_free(soap_req->data); return 0; } -int msn_soap_profile_get( struct im_connection *ic, const char *cid ) +int msn_soap_profile_get(struct im_connection *ic, const char *cid) { - return msn_soap_start( ic, g_strdup( cid ), - msn_soap_profile_get_build_request, - msn_soap_profile_get_parser, - msn_soap_profile_get_handle_response, - msn_soap_profile_get_free_data ); + return msn_soap_start(ic, g_strdup(cid), + msn_soap_profile_get_build_request, + msn_soap_profile_get_parser, + msn_soap_profile_get_handle_response, + msn_soap_profile_get_free_data); } /* Update profile (display name). */ -static int msn_soap_profile_set_dn_build_request( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_set_dn_build_request(struct msn_soap_req_data *soap_req) { struct msn_data *md = soap_req->ic->proto_data; - - soap_req->url = g_strdup( SOAP_STORAGE_URL ); - soap_req->action = g_strdup( SOAP_PROFILE_SET_DN_ACTION ); - soap_req->payload = g_markup_printf_escaped( SOAP_PROFILE_SET_DN_PAYLOAD, - md->tokens[3], md->profile_rid, (char*) soap_req->data ); - + + soap_req->url = g_strdup(SOAP_STORAGE_URL); + soap_req->action = g_strdup(SOAP_PROFILE_SET_DN_ACTION); + soap_req->payload = g_markup_printf_escaped(SOAP_PROFILE_SET_DN_PAYLOAD, + md->tokens[3], md->profile_rid, (char *) soap_req->data); + return 1; } @@ -1012,22 +1008,22 @@ static const struct xt_handler_entry msn_soap_profile_set_dn_parser[] = { { NULL, NULL, NULL } }; -static int msn_soap_profile_set_dn_handle_response( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_set_dn_handle_response(struct msn_soap_req_data *soap_req) { return MSN_SOAP_OK; } -static int msn_soap_profile_set_dn_free_data( struct msn_soap_req_data *soap_req ) +static int msn_soap_profile_set_dn_free_data(struct msn_soap_req_data *soap_req) { - g_free( soap_req->data ); + g_free(soap_req->data); return 0; } -int msn_soap_profile_set_dn( struct im_connection *ic, const char *dn ) +int msn_soap_profile_set_dn(struct im_connection *ic, const char *dn) { - return msn_soap_start( ic, g_strdup( dn ), - msn_soap_profile_set_dn_build_request, - msn_soap_profile_set_dn_parser, - msn_soap_profile_set_dn_handle_response, - msn_soap_profile_set_dn_free_data ); + return msn_soap_start(ic, g_strdup(dn), + msn_soap_profile_set_dn_build_request, + msn_soap_profile_set_dn_parser, + msn_soap_profile_set_dn_handle_response, + msn_soap_profile_set_dn_free_data); } diff --git a/protocols/msn/soap.h b/protocols/msn/soap.h index 73ef5f8a..44e27b2e 100644 --- a/protocols/msn/soap.h +++ b/protocols/msn/soap.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -42,20 +42,20 @@ #include "nogaim.h" -int msn_soapq_flush( struct im_connection *ic, gboolean resend ); +int msn_soapq_flush(struct im_connection *ic, gboolean resend); #define SOAP_HTTP_REQUEST \ -"POST %s HTTP/1.0\r\n" \ -"Host: %s\r\n" \ -"Accept: */*\r\n" \ -"User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ -"Content-Type: text/xml; charset=utf-8\r\n" \ -"%s" \ -"Content-Length: %zd\r\n" \ -"Cache-Control: no-cache\r\n" \ -"\r\n" \ -"%s" + "POST %s HTTP/1.0\r\n" \ + "Host: %s\r\n" \ + "Accept: */*\r\n" \ + "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ + "Content-Type: text/xml; charset=utf-8\r\n" \ + "%s" \ + "Content-Length: %zd\r\n" \ + "Cache-Control: no-cache\r\n" \ + "\r\n" \ + "%s" #define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf" @@ -63,205 +63,205 @@ int msn_soapq_flush( struct im_connection *ic, gboolean resend ); #define MAX_PASSPORT_PWLEN 16 #define SOAP_PASSPORT_SSO_PAYLOAD \ -"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" " \ - "xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" " \ - "xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" " \ - "xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" " \ - "xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" " \ - "xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" " \ - "xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" " \ - "xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \ - "<Header>" \ - "<ps:AuthInfo " \ - "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ - "Id=\"PPAuthInfo\">" \ - "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \ - "<ps:BinaryVersion>4</ps:BinaryVersion>" \ - "<ps:UIVersion>1</ps:UIVersion>" \ - "<ps:Cookies></ps:Cookies>" \ - "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>" \ - "</ps:AuthInfo>" \ - "<wsse:Security>" \ - "<wsse:UsernameToken Id=\"user\">" \ - "<wsse:Username>%s</wsse:Username>" \ - "<wsse:Password>%s</wsse:Password>" \ - "</wsse:UsernameToken>" \ - "</wsse:Security>" \ - "</Header>" \ - "<Body>" \ - "<ps:RequestMultipleSecurityTokens " \ - "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ - "Id=\"RSTS\">" \ - "<wst:RequestSecurityToken Id=\"RST0\">" \ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ - "<wsp:AppliesTo>" \ - "<wsa:EndpointReference>" \ - "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \ - "</wsa:EndpointReference>" \ - "</wsp:AppliesTo>" \ - "</wst:RequestSecurityToken>" \ - "<wst:RequestSecurityToken Id=\"RST1\">" \ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ - "<wsp:AppliesTo>" \ - "<wsa:EndpointReference>" \ - "<wsa:Address>messengerclear.live.com</wsa:Address>" \ - "</wsa:EndpointReference>" \ - "</wsp:AppliesTo>" \ - "<wsse:PolicyReference URI=\"%s\"></wsse:PolicyReference>" \ - "</wst:RequestSecurityToken>" \ - "<wst:RequestSecurityToken Id=\"RST2\">" \ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ - "<wsp:AppliesTo>" \ - "<wsa:EndpointReference>" \ - "<wsa:Address>contacts.msn.com</wsa:Address>" \ - "</wsa:EndpointReference>" \ - "</wsp:AppliesTo>" \ - "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI\"></wsse:PolicyReference>" \ - "</wst:RequestSecurityToken>" \ - "<wst:RequestSecurityToken Id=\"RST3\">" \ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ - "<wsp:AppliesTo>" \ - "<wsa:EndpointReference>" \ - "<wsa:Address>messengersecure.live.com</wsa:Address>" \ - "</wsa:EndpointReference>" \ - "</wsp:AppliesTo>" \ - "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \ - "</wst:RequestSecurityToken>" \ - "<wst:RequestSecurityToken Id=\"RST4\">" \ - "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ - "<wsp:AppliesTo>" \ - "<wsa:EndpointReference>" \ - "<wsa:Address>storage.msn.com</wsa:Address>" \ - "</wsa:EndpointReference>" \ - "</wsp:AppliesTo>" \ - "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \ - "</wst:RequestSecurityToken>" \ - "</ps:RequestMultipleSecurityTokens>" \ - "</Body>" \ -"</Envelope>" - -int msn_soap_passport_sso_request( struct im_connection *ic, const char *nonce ); + "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" " \ + "xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" " \ + "xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" " \ + "xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" " \ + "xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" " \ + "xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" " \ + "xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" " \ + "xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \ + "<Header>" \ + "<ps:AuthInfo " \ + "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ + "Id=\"PPAuthInfo\">" \ + "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \ + "<ps:BinaryVersion>4</ps:BinaryVersion>" \ + "<ps:UIVersion>1</ps:UIVersion>" \ + "<ps:Cookies></ps:Cookies>" \ + "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>" \ + "</ps:AuthInfo>" \ + "<wsse:Security>" \ + "<wsse:UsernameToken Id=\"user\">" \ + "<wsse:Username>%s</wsse:Username>" \ + "<wsse:Password>%s</wsse:Password>" \ + "</wsse:UsernameToken>" \ + "</wsse:Security>" \ + "</Header>" \ + "<Body>" \ + "<ps:RequestMultipleSecurityTokens " \ + "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ + "Id=\"RSTS\">" \ + "<wst:RequestSecurityToken Id=\"RST0\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "</wst:RequestSecurityToken>" \ + "<wst:RequestSecurityToken Id=\"RST1\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>messengerclear.live.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference URI=\"%s\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "<wst:RequestSecurityToken Id=\"RST2\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>contacts.msn.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "<wst:RequestSecurityToken Id=\"RST3\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>messengersecure.live.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "<wst:RequestSecurityToken Id=\"RST4\">" \ + "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ + "<wsp:AppliesTo>" \ + "<wsa:EndpointReference>" \ + "<wsa:Address>storage.msn.com</wsa:Address>" \ + "</wsa:EndpointReference>" \ + "</wsp:AppliesTo>" \ + "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI_SSL\"></wsse:PolicyReference>" \ + "</wst:RequestSecurityToken>" \ + "</ps:RequestMultipleSecurityTokens>" \ + "</Body>" \ + "</Envelope>" + +int msn_soap_passport_sso_request(struct im_connection *ic, const char *nonce); #define SOAP_ABSERVICE_PAYLOAD \ -"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">F6D2794D-501F-443A-ADBE-8F1490FF30FD</ApplicationId>" \ - "<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>" \ - "<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>" \ - "</ABApplicationHeader>" \ - "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>" \ - "<TicketToken>%s</TicketToken>" \ - "</ABAuthHeader>" \ - "</soap:Header>" \ - "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "%%s" \ - "</soap:Body>" \ -"</soap:Envelope>" + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">F6D2794D-501F-443A-ADBE-8F1490FF30FD</ApplicationId>" \ + "<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>" \ + "<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>" \ + "</ABApplicationHeader>" \ + "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>" \ + "<TicketToken>%s</TicketToken>" \ + "</ABAuthHeader>" \ + "</soap:Header>" \ + "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "%%s" \ + "</soap:Body>" \ + "</soap:Envelope>" #define SOAP_MEMLIST_URL "http://contacts.msn.com/abservice/SharingService.asmx" #define SOAP_MEMLIST_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership" #define SOAP_MEMLIST_PAYLOAD \ - "<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\"><serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\"><Types xmlns=\"http://www.msn.com/webservices/AddressBook\"><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType></Types></serviceFilter>" \ - "</FindMembership>" + "<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\"><serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\"><Types xmlns=\"http://www.msn.com/webservices/AddressBook\"><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType><ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType></Types></serviceFilter>" \ + "</FindMembership>" #define SOAP_MEMLIST_ADD_ACTION "http://www.msn.com/webservices/AddressBook/AddMember" #define SOAP_MEMLIST_DEL_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember" #define SOAP_MEMLIST_EDIT_PAYLOAD \ - "<%sMember xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<serviceHandle>" \ - "<Id>0</Id>" \ - "<Type>Messenger</Type>" \ - "<ForeignId></ForeignId>" \ - "</serviceHandle>" \ - "<memberships>" \ - "<Membership>" \ - "<MemberRole>%s</MemberRole>" \ - "<Members>" \ - "<Member xsi:type=\"PassportMember\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" \ - "<Type>Passport</Type>" \ - "<State>Accepted</State>" \ - "<PassportName>%s</PassportName>" \ - "</Member>" \ - "</Members>" \ - "</Membership>" \ - "</memberships>" \ - "</%sMember>" - -int msn_soap_memlist_request( struct im_connection *ic ); -int msn_soap_memlist_edit( struct im_connection *ic, const char *handle, gboolean add, int list ); + "<%sMember xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<serviceHandle>" \ + "<Id>0</Id>" \ + "<Type>Messenger</Type>" \ + "<ForeignId></ForeignId>" \ + "</serviceHandle>" \ + "<memberships>" \ + "<Membership>" \ + "<MemberRole>%s</MemberRole>" \ + "<Members>" \ + "<Member xsi:type=\"PassportMember\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" \ + "<Type>Passport</Type>" \ + "<State>Accepted</State>" \ + "<PassportName>%s</PassportName>" \ + "</Member>" \ + "</Members>" \ + "</Membership>" \ + "</memberships>" \ + "</%sMember>" + +int msn_soap_memlist_request(struct im_connection *ic); +int msn_soap_memlist_edit(struct im_connection *ic, const char *handle, gboolean add, int list); #define SOAP_ADDRESSBOOK_URL "http://contacts.msn.com/abservice/abservice.asmx" #define SOAP_ADDRESSBOOK_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" #define SOAP_ADDRESSBOOK_PAYLOAD \ - "<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<abId>00000000-0000-0000-0000-000000000000</abId>" \ - "<abView>Full</abView>" \ - "<deltasOnly>false</deltasOnly>" \ - "<lastChange>0001-01-01T00:00:00.0000000-08:00</lastChange>" \ - "</ABFindAll>" + "<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<abId>00000000-0000-0000-0000-000000000000</abId>" \ + "<abView>Full</abView>" \ + "<deltasOnly>false</deltasOnly>" \ + "<lastChange>0001-01-01T00:00:00.0000000-08:00</lastChange>" \ + "</ABFindAll>" #define SOAP_AB_NAMECHANGE_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" #define SOAP_AB_NAMECHANGE_PAYLOAD \ - "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<abId>00000000-0000-0000-0000-000000000000</abId>" \ - "<contacts>" \ - "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<contactInfo>" \ - "<contactType>Me</contactType>" \ - "<displayName>%s</displayName>" \ - "</contactInfo>" \ - "<propertiesChanged>DisplayName</propertiesChanged>" \ - "</Contact>" \ - "</contacts>" \ - "</ABContactUpdate>" + "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<abId>00000000-0000-0000-0000-000000000000</abId>" \ + "<contacts>" \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<contactInfo>" \ + "<contactType>Me</contactType>" \ + "<displayName>%s</displayName>" \ + "</contactInfo>" \ + "<propertiesChanged>DisplayName</propertiesChanged>" \ + "</Contact>" \ + "</contacts>" \ + "</ABContactUpdate>" #define SOAP_AB_CONTACT_ADD_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd" #define SOAP_AB_CONTACT_ADD_PAYLOAD \ - "<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<abId>00000000-0000-0000-0000-000000000000</abId>" \ - "<contacts>" \ - "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<contactInfo>" \ - "<contactType>LivePending</contactType>" \ - "<passportName>%s</passportName>" \ - "<isMessengerUser>true</isMessengerUser>" \ - "<MessengerMemberInfo>" \ - "<DisplayName>%s</DisplayName>" \ - "</MessengerMemberInfo>" \ - "</contactInfo>" \ - "</Contact>" \ - "</contacts>" \ - "<options>" \ - "<EnableAllowListManagement>true</EnableAllowListManagement>" \ - "</options>" \ - "</ABContactAdd>" + "<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<abId>00000000-0000-0000-0000-000000000000</abId>" \ + "<contacts>" \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<contactInfo>" \ + "<contactType>LivePending</contactType>" \ + "<passportName>%s</passportName>" \ + "<isMessengerUser>true</isMessengerUser>" \ + "<MessengerMemberInfo>" \ + "<DisplayName>%s</DisplayName>" \ + "</MessengerMemberInfo>" \ + "</contactInfo>" \ + "</Contact>" \ + "</contacts>" \ + "<options>" \ + "<EnableAllowListManagement>true</EnableAllowListManagement>" \ + "</options>" \ + "</ABContactAdd>" #define SOAP_AB_CONTACT_DEL_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete" #define SOAP_AB_CONTACT_DEL_PAYLOAD \ - "<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<abId>00000000-0000-0000-0000-000000000000</abId>" \ - "<contacts>" \ - "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ - "<contactId>%s</contactId>" \ - "</Contact>" \ - "</contacts>" \ - "</ABContactDelete>" + "<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<abId>00000000-0000-0000-0000-000000000000</abId>" \ + "<contacts>" \ + "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">" \ + "<contactId>%s</contactId>" \ + "</Contact>" \ + "</contacts>" \ + "</ABContactDelete>" -int msn_soap_addressbook_request( struct im_connection *ic ); -int msn_soap_addressbook_set_display_name( struct im_connection *ic, const char *new ); -int msn_soap_ab_contact_add( struct im_connection *ic, bee_user_t *bu ); -int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ); +int msn_soap_addressbook_request(struct im_connection *ic); +int msn_soap_addressbook_set_display_name(struct im_connection *ic, const char *new); +int msn_soap_ab_contact_add(struct im_connection *ic, bee_user_t *bu); +int msn_soap_ab_contact_del(struct im_connection *ic, bee_user_t *bu); #define SOAP_STORAGE_URL "https://storage.msn.com/storageservice/SchematizedStore.asmx" @@ -269,74 +269,74 @@ int msn_soap_ab_contact_del( struct im_connection *ic, bee_user_t *bu ); #define SOAP_PROFILE_SET_DN_ACTION "http://www.msn.com/webservices/storage/w10/UpdateProfile" #define SOAP_PROFILE_GET_PAYLOAD \ -"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<StorageApplicationHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<ApplicationID>Messenger Client 9.0</ApplicationID>" \ - "<Scenario>Initial</Scenario>" \ - "</StorageApplicationHeader>" \ - "<StorageUserHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<Puid>0</Puid>" \ - "<TicketToken>%s</TicketToken>" \ - "</StorageUserHeader>" \ - "</soap:Header>" \ - "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<GetProfile xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<profileHandle>" \ - "<Alias>" \ - "<Name>%s</Name>" \ - "<NameSpace>MyCidStuff</NameSpace>" \ - "</Alias>" \ - "<RelationshipName>MyProfile</RelationshipName>" \ - "</profileHandle>" \ - "<profileAttributes>" \ - "<ResourceID>true</ResourceID>" \ - "<DateModified>true</DateModified>" \ - "<ExpressionProfileAttributes>" \ - "<ResourceID>true</ResourceID>" \ - "<DateModified>true</DateModified>" \ - "<DisplayName>true</DisplayName>" \ - "<DisplayNameLastModified>true</DisplayNameLastModified>" \ - "<PersonalStatus>true</PersonalStatus>" \ - "<PersonalStatusLastModified>true</PersonalStatusLastModified>" \ - "<StaticUserTilePublicURL>true</StaticUserTilePublicURL>" \ - "<Photo>true</Photo>" \ - "<Flags>true</Flags>" \ - "</ExpressionProfileAttributes>" \ - "</profileAttributes>" \ - "</GetProfile>" \ - "</soap:Body>" \ -"</soap:Envelope>" + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<StorageApplicationHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<ApplicationID>Messenger Client 9.0</ApplicationID>" \ + "<Scenario>Initial</Scenario>" \ + "</StorageApplicationHeader>" \ + "<StorageUserHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<Puid>0</Puid>" \ + "<TicketToken>%s</TicketToken>" \ + "</StorageUserHeader>" \ + "</soap:Header>" \ + "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<GetProfile xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<profileHandle>" \ + "<Alias>" \ + "<Name>%s</Name>" \ + "<NameSpace>MyCidStuff</NameSpace>" \ + "</Alias>" \ + "<RelationshipName>MyProfile</RelationshipName>" \ + "</profileHandle>" \ + "<profileAttributes>" \ + "<ResourceID>true</ResourceID>" \ + "<DateModified>true</DateModified>" \ + "<ExpressionProfileAttributes>" \ + "<ResourceID>true</ResourceID>" \ + "<DateModified>true</DateModified>" \ + "<DisplayName>true</DisplayName>" \ + "<DisplayNameLastModified>true</DisplayNameLastModified>" \ + "<PersonalStatus>true</PersonalStatus>" \ + "<PersonalStatusLastModified>true</PersonalStatusLastModified>" \ + "<StaticUserTilePublicURL>true</StaticUserTilePublicURL>" \ + "<Photo>true</Photo>" \ + "<Flags>true</Flags>" \ + "</ExpressionProfileAttributes>" \ + "</profileAttributes>" \ + "</GetProfile>" \ + "</soap:Body>" \ + "</soap:Envelope>" #define SOAP_PROFILE_SET_DN_PAYLOAD \ -"<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ -"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<StorageApplicationHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<ApplicationID>Messenger Client 9.0</ApplicationID>" \ - "<Scenario>Initial</Scenario>" \ - "</StorageApplicationHeader>" \ - "<StorageUserHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<Puid>0</Puid>" \ - "<TicketToken>%s</TicketToken>" \ - "</StorageUserHeader>" \ - "</soap:Header>" \ - "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ - "<UpdateProfile xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ - "<profile>" \ - "<ResourceID>%s</ResourceID>" \ - "<ExpressionProfile>" \ - "<FreeText>Update</FreeText>" \ - "<DisplayName>%s</DisplayName>" \ - "<Flags>0</Flags>" \ - "</ExpressionProfile>" \ - "</profile>" \ - "</UpdateProfile>" \ - "</soap:Body>" \ -"</soap:Envelope>" - -int msn_soap_profile_get( struct im_connection *ic, const char *cid ); -int msn_soap_profile_set_dn( struct im_connection *ic, const char *dn ); + "<?xml version=\"1.0\" encoding=\"utf-8\"?>" \ + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<StorageApplicationHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<ApplicationID>Messenger Client 9.0</ApplicationID>" \ + "<Scenario>Initial</Scenario>" \ + "</StorageApplicationHeader>" \ + "<StorageUserHeader xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<Puid>0</Puid>" \ + "<TicketToken>%s</TicketToken>" \ + "</StorageUserHeader>" \ + "</soap:Header>" \ + "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \ + "<UpdateProfile xmlns=\"http://www.msn.com/webservices/storage/w10\">" \ + "<profile>" \ + "<ResourceID>%s</ResourceID>" \ + "<ExpressionProfile>" \ + "<FreeText>Update</FreeText>" \ + "<DisplayName>%s</DisplayName>" \ + "<Flags>0</Flags>" \ + "</ExpressionProfile>" \ + "</profile>" \ + "</UpdateProfile>" \ + "</soap:Body>" \ + "</soap:Envelope>" + +int msn_soap_profile_get(struct im_connection *ic, const char *cid); +int msn_soap_profile_set_dn(struct im_connection *ic, const char *dn); #endif /* __SOAP_H__ */ diff --git a/protocols/msn/tables.c b/protocols/msn/tables.c index c3e36eb5..c4dc895e 100644 --- a/protocols/msn/tables.c +++ b/protocols/msn/tables.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2010 Wilmer van der Gaast and others * @@ -39,25 +39,29 @@ const struct msn_away_state msn_away_state_list[] = { "", "" } }; -const struct msn_away_state *msn_away_state_by_code( char *code ) +const struct msn_away_state *msn_away_state_by_code(char *code) { int i; - - for( i = 0; *msn_away_state_list[i].code; i ++ ) - if( g_strcasecmp( msn_away_state_list[i].code, code ) == 0 ) - return( msn_away_state_list + i ); - + + for (i = 0; *msn_away_state_list[i].code; i++) { + if (g_strcasecmp(msn_away_state_list[i].code, code) == 0) { + return(msn_away_state_list + i); + } + } + return NULL; } -const struct msn_away_state *msn_away_state_by_name( char *name ) +const struct msn_away_state *msn_away_state_by_name(char *name) { int i; - - for( i = 0; *msn_away_state_list[i].code; i ++ ) - if( g_strcasecmp( msn_away_state_list[i].name, name ) == 0 ) - return( msn_away_state_list + i ); - + + for (i = 0; *msn_away_state_list[i].code; i++) { + if (g_strcasecmp(msn_away_state_list[i].name, name) == 0) { + return(msn_away_state_list + i); + } + } + return NULL; } @@ -86,24 +90,24 @@ const struct msn_status_code msn_status_code_list[] = { 241, "ADL/RML command with invalid modification", 0 }, { 280, "Switchboard failed", STATUS_SB_FATAL }, { 281, "Transfer to switchboard failed", 0 }, - + { 300, "Required field missing", 0 }, { 302, "Not logged in", 0 }, - + { 500, "Internal server error/Account banned", STATUS_FATAL }, { 501, "Database server error", STATUS_FATAL }, { 502, "Command disabled", 0 }, { 510, "File operation failed", STATUS_FATAL }, { 520, "Memory allocation failed", STATUS_FATAL }, { 540, "Challenge response invalid", STATUS_FATAL }, - + { 600, "Server is busy", STATUS_FATAL }, { 601, "Server is unavailable", STATUS_FATAL }, { 602, "Peer nameserver is down", STATUS_FATAL }, { 603, "Database connection failed", STATUS_FATAL }, { 604, "Server is going down", STATUS_FATAL }, { 605, "Server is unavailable", STATUS_FATAL }, - + { 700, "Could not create connection", STATUS_FATAL }, { 710, "Invalid CVR parameters", STATUS_FATAL }, { 711, "Write is blocking", STATUS_FATAL }, @@ -113,9 +117,9 @@ const struct msn_status_code msn_status_code_list[] = { 715, "Not expected/Invalid argument/action", 0 }, { 717, "Bad friend file", STATUS_FATAL }, { 731, "Not expected/Invalid argument", 0 }, - + { 800, "Changing too rapidly", 0 }, - + { 910, "Server is busy", STATUS_FATAL }, { 911, "Authentication failed", STATUS_SB_FATAL | STATUS_FATAL }, { 912, "Server is busy", STATUS_FATAL }, @@ -134,24 +138,25 @@ const struct msn_status_code msn_status_code_list[] = { -1, NULL, 0 } }; -const struct msn_status_code *msn_status_by_number( int number ) +const struct msn_status_code *msn_status_by_number(int number) { static struct msn_status_code *unknown = NULL; int i; - - for( i = 0; msn_status_code_list[i].number >= 0; i ++ ) - if( msn_status_code_list[i].number == number ) - return( msn_status_code_list + i ); - - if( unknown == NULL ) - { - unknown = g_new0( struct msn_status_code, 1 ); - unknown->text = g_new0( char, 128 ); + + for (i = 0; msn_status_code_list[i].number >= 0; i++) { + if (msn_status_code_list[i].number == number) { + return(msn_status_code_list + i); + } } - + + if (unknown == NULL) { + unknown = g_new0(struct msn_status_code, 1); + unknown->text = g_new0(char, 128); + } + unknown->number = number; unknown->flags = 0; - g_snprintf( unknown->text, 128, "Unknown error (%d)", number ); - - return( unknown ); + g_snprintf(unknown->text, 128, "Unknown error (%d)", number); + + return(unknown); } diff --git a/protocols/nogaim.c b/protocols/nogaim.c index 0a674b40..2de24af8 100644 --- a/protocols/nogaim.c +++ b/protocols/nogaim.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -42,15 +42,15 @@ GSList *connections; gboolean load_plugin(char *path) { void (*init_function) (void); - + GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY); - if(!mod) { + if (!mod) { log_message(LOGLVL_ERROR, "Can't find `%s', not loading (%s)\n", path, g_module_error()); return FALSE; } - if(!g_module_symbol(mod,"init_plugin",(gpointer *) &init_function)) { + if (!g_module_symbol(mod, "init_plugin", (gpointer *) &init_function)) { log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path); return FALSE; } @@ -73,7 +73,7 @@ void load_plugins(void) while ((entry = g_dir_read_name(dir))) { path = g_build_filename(global.conf->plugindir, entry, NULL); - if(!path) { + if (!path) { log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry); continue; } @@ -89,37 +89,38 @@ void load_plugins(void) #endif GList *protocols = NULL; - -void register_protocol (struct prpl *p) + +void register_protocol(struct prpl *p) { int i; gboolean refused = global.conf->protocols != NULL; - - for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++) - { - if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0) + + for (i = 0; global.conf->protocols && global.conf->protocols[i]; i++) { + if (g_strcasecmp(p->name, global.conf->protocols[i]) == 0) { refused = FALSE; - } + } + } - if (refused) + if (refused) { log_message(LOGLVL_WARNING, "Protocol %s disabled\n", p->name); - else + } else { protocols = g_list_append(protocols, p); + } } struct prpl *find_protocol(const char *name) { GList *gl; - - for( gl = protocols; gl; gl = gl->next ) - { - struct prpl *proto = gl->data; - - if( g_strcasecmp( proto->name, name ) == 0 ) + + for (gl = protocols; gl; gl = gl->next) { + struct prpl *proto = gl->data; + + if (g_strcasecmp(proto->name, name) == 0) { return proto; - } - - return NULL; + } + } + + return NULL; } void nogaim_init() @@ -138,11 +139,11 @@ void nogaim_init() #ifdef WITH_OSCAR oscar_initmodule(); #endif - + #ifdef WITH_YAHOO byahoo_initmodule(); #endif - + #ifdef WITH_JABBER jabber_initmodule(); #endif @@ -160,449 +161,464 @@ void nogaim_init() #endif } -GSList *get_connections() { return connections; } +GSList *get_connections() +{ + return connections; +} -struct im_connection *imcb_new( account_t *acc ) +struct im_connection *imcb_new(account_t *acc) { struct im_connection *ic; - - ic = g_new0( struct im_connection, 1 ); - + + ic = g_new0(struct im_connection, 1); + ic->bee = acc->bee; ic->acc = acc; acc->ic = ic; - - connections = g_slist_append( connections, ic ); - - return( ic ); + + connections = g_slist_append(connections, ic); + + return(ic); } -void imc_free( struct im_connection *ic ) +void imc_free(struct im_connection *ic) { account_t *a; - + /* Destroy the pointer to this connection from the account list */ - for( a = ic->bee->accounts; a; a = a->next ) - if( a->ic == ic ) - { + for (a = ic->bee->accounts; a; a = a->next) { + if (a->ic == ic) { a->ic = NULL; break; } - - connections = g_slist_remove( connections, ic ); - g_free( ic ); + } + + connections = g_slist_remove(connections, ic); + g_free(ic); } -static void serv_got_crap( struct im_connection *ic, char *format, ... ) +static void serv_got_crap(struct im_connection *ic, char *format, ...) { va_list params; char *text; account_t *a; - - va_start( params, format ); - text = g_strdup_vprintf( format, params ); - va_end( params ); - - if( ( g_strcasecmp( set_getstr( &ic->bee->set, "strip_html" ), "always" ) == 0 ) || - ( ( ic->flags & OPT_DOES_HTML ) && set_getbool( &ic->bee->set, "strip_html" ) ) ) - strip_html( text ); - + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + if ((g_strcasecmp(set_getstr(&ic->bee->set, "strip_html"), "always") == 0) || + ((ic->flags & OPT_DOES_HTML) && set_getbool(&ic->bee->set, "strip_html"))) { + strip_html(text); + } + /* Try to find a different connection on the same protocol. */ - for( a = ic->bee->accounts; a; a = a->next ) - if( a->prpl == ic->acc->prpl && a->ic != ic ) + for (a = ic->bee->accounts; a; a = a->next) { + if (a->prpl == ic->acc->prpl && a->ic != ic) { break; - + } + } + /* If we found one, include the screenname in the message. */ - if( a ) + if (a) { /* FIXME(wilmer): ui_log callback or so */ - irc_rootmsg( ic->bee->ui_data, "%s - %s", ic->acc->tag, text ); - else - irc_rootmsg( ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text ); - - g_free( text ); + irc_rootmsg(ic->bee->ui_data, "%s - %s", ic->acc->tag, text); + } else { + irc_rootmsg(ic->bee->ui_data, "%s - %s", ic->acc->prpl->name, text); + } + + g_free(text); } -void imcb_log( struct im_connection *ic, char *format, ... ) +void imcb_log(struct im_connection *ic, char *format, ...) { va_list params; char *text; - - va_start( params, format ); - text = g_strdup_vprintf( format, params ); - va_end( params ); - - if( ic->flags & OPT_LOGGED_IN ) - serv_got_crap( ic, "%s", text ); - else - serv_got_crap( ic, "Logging in: %s", text ); - - g_free( text ); + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + if (ic->flags & OPT_LOGGED_IN) { + serv_got_crap(ic, "%s", text); + } else { + serv_got_crap(ic, "Logging in: %s", text); + } + + g_free(text); } -void imcb_error( struct im_connection *ic, char *format, ... ) +void imcb_error(struct im_connection *ic, char *format, ...) { va_list params; char *text; - - va_start( params, format ); - text = g_strdup_vprintf( format, params ); - va_end( params ); - - if( ic->flags & OPT_LOGGED_IN ) - serv_got_crap( ic, "Error: %s", text ); - else - serv_got_crap( ic, "Login error: %s", text ); - - g_free( text ); + + va_start(params, format); + text = g_strdup_vprintf(format, params); + va_end(params); + + if (ic->flags & OPT_LOGGED_IN) { + serv_got_crap(ic, "Error: %s", text); + } else { + serv_got_crap(ic, "Login error: %s", text); + } + + g_free(text); } -static gboolean send_keepalive( gpointer d, gint fd, b_input_condition cond ) +static gboolean send_keepalive(gpointer d, gint fd, b_input_condition cond) { struct im_connection *ic = d; - - if( ( ic->flags & OPT_PONGS ) && !( ic->flags & OPT_PONGED ) ) - { + + if ((ic->flags & OPT_PONGS) && !(ic->flags & OPT_PONGED)) { /* This protocol is expected to ack keepalives and hasn't since the last time we were here. */ - imcb_error( ic, "Connection timeout" ); - imc_logout( ic, TRUE ); + imcb_error(ic, "Connection timeout"); + imc_logout(ic, TRUE); return FALSE; } ic->flags &= ~OPT_PONGED; - - if( ic->acc->prpl->keepalive ) - ic->acc->prpl->keepalive( ic ); - + + if (ic->acc->prpl->keepalive) { + ic->acc->prpl->keepalive(ic); + } + return TRUE; } -void start_keepalives( struct im_connection *ic, int interval ) +void start_keepalives(struct im_connection *ic, int interval) { - b_event_remove( ic->keepalive ); - ic->keepalive = b_timeout_add( interval, send_keepalive, ic ); - + b_event_remove(ic->keepalive); + ic->keepalive = b_timeout_add(interval, send_keepalive, ic); + /* Connecting successfully counts as a first successful pong. */ - if( ic->flags & OPT_PONGS ) + if (ic->flags & OPT_PONGS) { ic->flags |= OPT_PONGED; + } } -void imcb_connected( struct im_connection *ic ) +void imcb_connected(struct im_connection *ic) { /* MSN servers sometimes redirect you to a different server and do the whole login sequence again, so these "late" calls to this function should be handled correctly. (IOW, ignored) */ - if( ic->flags & OPT_LOGGED_IN ) + if (ic->flags & OPT_LOGGED_IN) { return; + } - if( ic->acc->flags & ACC_FLAG_LOCAL ) - { + if (ic->acc->flags & ACC_FLAG_LOCAL) { GHashTableIter nicks; gpointer k, v; - g_hash_table_iter_init( &nicks, ic->acc->nicks ); - while( g_hash_table_iter_next( &nicks, &k, &v ) ) - { - ic->acc->prpl->add_buddy( ic, (char*) k, NULL ); + g_hash_table_iter_init(&nicks, ic->acc->nicks); + while (g_hash_table_iter_next(&nicks, &k, &v)) { + ic->acc->prpl->add_buddy(ic, (char *) k, NULL); } } - - imcb_log( ic, "Logged in" ); - + + imcb_log(ic, "Logged in"); + ic->flags |= OPT_LOGGED_IN; - start_keepalives( ic, 60000 ); - + start_keepalives(ic, 60000); + /* Necessary to send initial presence status, even if we're not away. */ - imc_away_send_update( ic ); - + imc_away_send_update(ic); + /* Apparently we're connected successfully, so reset the exponential backoff timer. */ ic->acc->auto_reconnect_delay = 0; - - if( ic->bee->ui->imc_connected ) - ic->bee->ui->imc_connected( ic ); + + if (ic->bee->ui->imc_connected) { + ic->bee->ui->imc_connected(ic); + } } -gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ) +gboolean auto_reconnect(gpointer data, gint fd, b_input_condition cond) { account_t *a = data; - + a->reconnect = 0; - account_on( a->bee, a ); - - return( FALSE ); /* Only have to run the timeout once */ + account_on(a->bee, a); + + return(FALSE); /* Only have to run the timeout once */ } -void cancel_auto_reconnect( account_t *a ) +void cancel_auto_reconnect(account_t *a) { - b_event_remove( a->reconnect ); + b_event_remove(a->reconnect); a->reconnect = 0; } -void imc_logout( struct im_connection *ic, int allow_reconnect ) +void imc_logout(struct im_connection *ic, int allow_reconnect) { bee_t *bee = ic->bee; account_t *a; GSList *l; int delay; - + /* Nested calls might happen sometimes, this is probably the best place to catch them. */ - if( ic->flags & OPT_LOGGING_OUT ) + if (ic->flags & OPT_LOGGING_OUT) { return; - else + } else { ic->flags |= OPT_LOGGING_OUT; - - if( ic->bee->ui->imc_disconnected ) - ic->bee->ui->imc_disconnected( ic ); - - imcb_log( ic, "Signing off.." ); - + } + + if (ic->bee->ui->imc_disconnected) { + ic->bee->ui->imc_disconnected(ic); + } + + imcb_log(ic, "Signing off.."); + /* TBH I don't remember anymore why I didn't just use ic->acc... */ - for( a = bee->accounts; a; a = a->next ) - if( a->ic == ic ) + for (a = bee->accounts; a; a = a->next) { + if (a->ic == ic) { break; - - if( a && !allow_reconnect && !( ic->flags & OPT_LOGGED_IN ) && - set_getbool( &a->set, "oauth" ) ) - { + } + } + + if (a && !allow_reconnect && !(ic->flags & OPT_LOGGED_IN) && + set_getbool(&a->set, "oauth")) { /* If this account supports OAuth, we're not logged in yet and not allowed to retry, assume there were auth issues. Give a helpful message on what might be necessary to fix this. */ - imcb_log( ic, "If you're having problems logging in, try re-requesting " - "an OAuth token: account %s set password \"\"", a->tag ); + imcb_log(ic, "If you're having problems logging in, try re-requesting " + "an OAuth token: account %s set password \"\"", a->tag); } - - for( l = bee->users; l; ) - { + + for (l = bee->users; l; ) { bee_user_t *bu = l->data; GSList *next = l->next; - - if( bu->ic == ic ) - bee_user_free( bee, bu ); - + + if (bu->ic == ic) { + bee_user_free(bee, bu); + } + l = next; } - - b_event_remove( ic->keepalive ); + + b_event_remove(ic->keepalive); ic->keepalive = 0; - ic->acc->prpl->logout( ic ); - b_event_remove( ic->inpa ); - - g_free( ic->away ); + ic->acc->prpl->logout(ic); + b_event_remove(ic->inpa); + + g_free(ic->away); ic->away = NULL; - - query_del_by_conn( (irc_t*) ic->bee->ui_data, ic ); - - if( !a ) - { + + query_del_by_conn((irc_t *) ic->bee->ui_data, ic); + + if (!a) { /* Uhm... This is very sick. */ + } else if (allow_reconnect && set_getbool(&bee->set, "auto_reconnect") && + set_getbool(&a->set, "auto_reconnect") && + (delay = account_reconnect_delay(a)) > 0) { + imcb_log(ic, "Reconnecting in %d seconds..", delay); + a->reconnect = b_timeout_add(delay * 1000, auto_reconnect, a); } - else if( allow_reconnect && set_getbool( &bee->set, "auto_reconnect" ) && - set_getbool( &a->set, "auto_reconnect" ) && - ( delay = account_reconnect_delay( a ) ) > 0 ) - { - imcb_log( ic, "Reconnecting in %d seconds..", delay ); - a->reconnect = b_timeout_add( delay * 1000, auto_reconnect, a ); - } - - imc_free( ic ); + + imc_free(ic); } -void imcb_ask( struct im_connection *ic, char *msg, void *data, - query_callback doit, query_callback dont ) +void imcb_ask(struct im_connection *ic, char *msg, void *data, + query_callback doit, query_callback dont) { - query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, g_free, data ); + query_add((irc_t *) ic->bee->ui_data, ic, msg, doit, dont, g_free, data); } -void imcb_ask_with_free( struct im_connection *ic, char *msg, void *data, - query_callback doit, query_callback dont, query_callback myfree ) +void imcb_ask_with_free(struct im_connection *ic, char *msg, void *data, + query_callback doit, query_callback dont, query_callback myfree) { - query_add( (irc_t *) ic->bee->ui_data, ic, msg, doit, dont, myfree, data ); + query_add((irc_t *) ic->bee->ui_data, ic, msg, doit, dont, myfree, data); } -void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ) +void imcb_add_buddy(struct im_connection *ic, const char *handle, const char *group) { bee_user_t *bu; bee_t *bee = ic->bee; bee_group_t *oldg; - - if( !( bu = bee_user_by_handle( bee, ic, handle ) ) ) - bu = bee_user_new( bee, ic, handle, 0 ); - + + if (!(bu = bee_user_by_handle(bee, ic, handle))) { + bu = bee_user_new(bee, ic, handle, 0); + } + oldg = bu->group; - bu->group = bee_group_by_name( bee, group, TRUE ); - - if( bee->ui->user_group && bu->group != oldg ) - bee->ui->user_group( bee, bu ); + bu->group = bee_group_by_name(bee, group, TRUE); + + if (bee->ui->user_group && bu->group != oldg) { + bee->ui->user_group(bee, bu); + } } -void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *fullname ) +void imcb_rename_buddy(struct im_connection *ic, const char *handle, const char *fullname) { bee_t *bee = ic->bee; - bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); - - if( !bu || !fullname ) return; - - if( !bu->fullname || strcmp( bu->fullname, fullname ) != 0 ) - { - g_free( bu->fullname ); - bu->fullname = g_strdup( fullname ); - - if( bee->ui->user_fullname ) - bee->ui->user_fullname( bee, bu ); + bee_user_t *bu = bee_user_by_handle(bee, ic, handle); + + if (!bu || !fullname) { + return; + } + + if (!bu->fullname || strcmp(bu->fullname, fullname) != 0) { + g_free(bu->fullname); + bu->fullname = g_strdup(fullname); + + if (bee->ui->user_fullname) { + bee->ui->user_fullname(bee, bu); + } } } -void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ) +void imcb_remove_buddy(struct im_connection *ic, const char *handle, char *group) { - bee_user_free( ic->bee, bee_user_by_handle( ic->bee, ic, handle ) ); + bee_user_free(ic->bee, bee_user_by_handle(ic->bee, ic, handle)); } /* Mainly meant for ICQ (and now also for Jabber conferences) to allow IM modules to suggest a nickname for a handle. */ -void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ) +void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick) { bee_t *bee = ic->bee; - bee_user_t *bu = bee_user_by_handle( bee, ic, handle ); - - if( !bu || !nick ) return; - - g_free( bu->nick ); - bu->nick = g_strdup( nick ); - - if( bee->ui->user_nick_hint ) - bee->ui->user_nick_hint( bee, bu, nick ); + bee_user_t *bu = bee_user_by_handle(bee, ic, handle); + + if (!bu || !nick) { + return; + } + + g_free(bu->nick); + bu->nick = g_strdup(nick); + + if (bee->ui->user_nick_hint) { + bee->ui->user_nick_hint(bee, bu, nick); + } } -struct imcb_ask_cb_data -{ +struct imcb_ask_cb_data { struct im_connection *ic; char *handle; }; -static void imcb_ask_auth_cb_no( void *data ) +static void imcb_ask_auth_cb_no(void *data) { struct imcb_ask_cb_data *cbd = data; - - cbd->ic->acc->prpl->auth_deny( cbd->ic, cbd->handle ); - - g_free( cbd->handle ); - g_free( cbd ); + + cbd->ic->acc->prpl->auth_deny(cbd->ic, cbd->handle); + + g_free(cbd->handle); + g_free(cbd); } -static void imcb_ask_auth_cb_yes( void *data ) +static void imcb_ask_auth_cb_yes(void *data) { struct imcb_ask_cb_data *cbd = data; - - cbd->ic->acc->prpl->auth_allow( cbd->ic, cbd->handle ); - - g_free( cbd->handle ); - g_free( cbd ); + + cbd->ic->acc->prpl->auth_allow(cbd->ic, cbd->handle); + + g_free(cbd->handle); + g_free(cbd); } -void imcb_ask_auth( struct im_connection *ic, const char *handle, const char *realname ) +void imcb_ask_auth(struct im_connection *ic, const char *handle, const char *realname) { - struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 ); + struct imcb_ask_cb_data *data = g_new0(struct imcb_ask_cb_data, 1); char *s, *realname_ = NULL; - - if( realname != NULL ) - realname_ = g_strdup_printf( " (%s)", realname ); - - s = g_strdup_printf( "The user %s%s wants to add you to his/her buddy list.", - handle, realname_ ? realname_ : "" ); - - g_free( realname_ ); - + + if (realname != NULL) { + realname_ = g_strdup_printf(" (%s)", realname); + } + + s = g_strdup_printf("The user %s%s wants to add you to his/her buddy list.", + handle, realname_ ? realname_ : ""); + + g_free(realname_); + data->ic = ic; - data->handle = g_strdup( handle ); - query_add( (irc_t *) ic->bee->ui_data, ic, s, - imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, g_free, data ); + data->handle = g_strdup(handle); + query_add((irc_t *) ic->bee->ui_data, ic, s, + imcb_ask_auth_cb_yes, imcb_ask_auth_cb_no, g_free, data); } -static void imcb_ask_add_cb_no( void *data ) +static void imcb_ask_add_cb_no(void *data) { - g_free( ((struct imcb_ask_cb_data*)data)->handle ); - g_free( data ); + g_free(((struct imcb_ask_cb_data*) data)->handle); + g_free(data); } -static void imcb_ask_add_cb_yes( void *data ) +static void imcb_ask_add_cb_yes(void *data) { struct imcb_ask_cb_data *cbd = data; - - cbd->ic->acc->prpl->add_buddy( cbd->ic, cbd->handle, NULL ); - - imcb_ask_add_cb_no( data ); + + cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); + + imcb_ask_add_cb_no(data); } -void imcb_ask_add( struct im_connection *ic, const char *handle, const char *realname ) +void imcb_ask_add(struct im_connection *ic, const char *handle, const char *realname) { - struct imcb_ask_cb_data *data = g_new0( struct imcb_ask_cb_data, 1 ); + struct imcb_ask_cb_data *data = g_new0(struct imcb_ask_cb_data, 1); char *s; - + /* TODO: Make a setting for this! */ - if( bee_user_by_handle( ic->bee, ic, handle ) != NULL ) + if (bee_user_by_handle(ic->bee, ic, handle) != NULL) { return; - - s = g_strdup_printf( "The user %s is not in your buddy list yet. Do you want to add him/her now?", handle ); - + } + + s = g_strdup_printf("The user %s is not in your buddy list yet. Do you want to add him/her now?", handle); + data->ic = ic; - data->handle = g_strdup( handle ); - query_add( (irc_t *) ic->bee->ui_data, ic, s, - imcb_ask_add_cb_yes, imcb_ask_add_cb_no, g_free, data ); + data->handle = g_strdup(handle); + query_add((irc_t *) ic->bee->ui_data, ic, s, + imcb_ask_add_cb_yes, imcb_ask_add_cb_no, g_free, data); } -struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ) +struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle) { - return bee_user_by_handle( ic->bee, ic, handle ); + return bee_user_by_handle(ic->bee, ic, handle); } /* The plan is to not allow straight calls to prpl functions anymore, but do them all from some wrappers. We'll start to define some down here: */ -int imc_chat_msg( struct groupchat *c, char *msg, int flags ) +int imc_chat_msg(struct groupchat *c, char *msg, int flags) { char *buf = NULL; - - if( ( c->ic->flags & OPT_DOES_HTML ) && ( g_strncasecmp( msg, "<html>", 6 ) != 0 ) ) - { - buf = escape_html( msg ); + + if ((c->ic->flags & OPT_DOES_HTML) && (g_strncasecmp(msg, "<html>", 6) != 0)) { + buf = escape_html(msg); msg = buf; } - - c->ic->acc->prpl->chat_msg( c, msg, flags ); - g_free( buf ); - + + c->ic->acc->prpl->chat_msg(c, msg, flags); + g_free(buf); + return 1; } -static char *imc_away_state_find( GList *gcm, char *away, char **message ); +static char *imc_away_state_find(GList *gcm, char *away, char **message); -int imc_away_send_update( struct im_connection *ic ) +int imc_away_send_update(struct im_connection *ic) { char *away, *msg = NULL; - - if( ic->acc->prpl->away_states == NULL || - ic->acc->prpl->set_away == NULL ) + + if (ic->acc->prpl->away_states == NULL || + ic->acc->prpl->set_away == NULL) { return 0; - - away = set_getstr( &ic->acc->set, "away" ) ? - : set_getstr( &ic->bee->set, "away" ); - if( away && *away ) - { - GList *m = ic->acc->prpl->away_states( ic ); - msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL; - away = imc_away_state_find( m, away, &msg ) ? : m->data; } - else if( ic->acc->flags & ACC_FLAG_STATUS_MESSAGE ) - { + + away = set_getstr(&ic->acc->set, "away") ? + : set_getstr(&ic->bee->set, "away"); + if (away && *away) { + GList *m = ic->acc->prpl->away_states(ic); + msg = ic->acc->flags & ACC_FLAG_AWAY_MESSAGE ? away : NULL; + away = imc_away_state_find(m, away, &msg) ? : m->data; + } else if (ic->acc->flags & ACC_FLAG_STATUS_MESSAGE) { away = NULL; - msg = set_getstr( &ic->acc->set, "status" ) ? - : set_getstr( &ic->bee->set, "status" ); + msg = set_getstr(&ic->acc->set, "status") ? + : set_getstr(&ic->bee->set, "status"); } - - ic->acc->prpl->set_away( ic, away, msg ); - + + ic->acc->prpl->set_away(ic, away, msg); + return 1; } @@ -618,132 +634,127 @@ static char *imc_away_alias_list[8][5] = { NULL } }; -static char *imc_away_state_find( GList *gcm, char *away, char **message ) +static char *imc_away_state_find(GList *gcm, char *away, char **message) { GList *m; int i, j; - - for( m = gcm; m; m = m->next ) - if( g_strncasecmp( m->data, away, strlen( m->data ) ) == 0 ) - { + + for (m = gcm; m; m = m->next) { + if (g_strncasecmp(m->data, away, strlen(m->data)) == 0) { /* At least the Yahoo! module works better if message contains no data unless it adds something to what we have in state already. */ - if( strlen( m->data ) == strlen( away ) ) + if (strlen(m->data) == strlen(away)) { *message = NULL; - + } + return m->data; } - - for( i = 0; *imc_away_alias_list[i]; i ++ ) - { + } + + for (i = 0; *imc_away_alias_list[i]; i++) { int keep_message; - - for( j = 0; imc_away_alias_list[i][j]; j ++ ) - if( g_strncasecmp( away, imc_away_alias_list[i][j], strlen( imc_away_alias_list[i][j] ) ) == 0 ) - { - keep_message = strlen( away ) != strlen( imc_away_alias_list[i][j] ); + + for (j = 0; imc_away_alias_list[i][j]; j++) { + if (g_strncasecmp(away, imc_away_alias_list[i][j], strlen(imc_away_alias_list[i][j])) == 0) { + keep_message = strlen(away) != strlen(imc_away_alias_list[i][j]); break; } - - if( !imc_away_alias_list[i][j] ) /* If we reach the end, this row */ - continue; /* is not what we want. Next! */ - + } + + if (!imc_away_alias_list[i][j]) { /* If we reach the end, this row */ + continue; /* is not what we want. Next! */ + + } /* Now find an entry in this row which exists in gcm */ - for( j = 0; imc_away_alias_list[i][j]; j ++ ) - { - for( m = gcm; m; m = m->next ) - if( g_strcasecmp( imc_away_alias_list[i][j], m->data ) == 0 ) - { - if( !keep_message ) + for (j = 0; imc_away_alias_list[i][j]; j++) { + for (m = gcm; m; m = m->next) { + if (g_strcasecmp(imc_away_alias_list[i][j], m->data) == 0) { + if (!keep_message) { *message = NULL; - + } + return imc_away_alias_list[i][j]; } + } } - + /* No need to look further, apparently this state doesn't have any good alias for this protocol. */ break; } - + return NULL; } -void imc_add_allow( struct im_connection *ic, char *handle ) +void imc_add_allow(struct im_connection *ic, char *handle) { - if( g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) - { - ic->permit = g_slist_prepend( ic->permit, g_strdup( handle ) ); + if (g_slist_find_custom(ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp) == NULL) { + ic->permit = g_slist_prepend(ic->permit, g_strdup(handle)); } - - ic->acc->prpl->add_permit( ic, handle ); + + ic->acc->prpl->add_permit(ic, handle); } -void imc_rem_allow( struct im_connection *ic, char *handle ) +void imc_rem_allow(struct im_connection *ic, char *handle) { GSList *l; - - if( ( l = g_slist_find_custom( ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) ) - { - g_free( l->data ); - ic->permit = g_slist_delete_link( ic->permit, l ); + + if ((l = g_slist_find_custom(ic->permit, handle, (GCompareFunc) ic->acc->prpl->handle_cmp))) { + g_free(l->data); + ic->permit = g_slist_delete_link(ic->permit, l); } - - ic->acc->prpl->rem_permit( ic, handle ); + + ic->acc->prpl->rem_permit(ic, handle); } -void imc_add_block( struct im_connection *ic, char *handle ) +void imc_add_block(struct im_connection *ic, char *handle) { - if( g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) == NULL ) - { - ic->deny = g_slist_prepend( ic->deny, g_strdup( handle ) ); + if (g_slist_find_custom(ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp) == NULL) { + ic->deny = g_slist_prepend(ic->deny, g_strdup(handle)); } - - ic->acc->prpl->add_deny( ic, handle ); + + ic->acc->prpl->add_deny(ic, handle); } -void imc_rem_block( struct im_connection *ic, char *handle ) +void imc_rem_block(struct im_connection *ic, char *handle) { GSList *l; - - if( ( l = g_slist_find_custom( ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) ) - { - g_free( l->data ); - ic->deny = g_slist_delete_link( ic->deny, l ); + + if ((l = g_slist_find_custom(ic->deny, handle, (GCompareFunc) ic->acc->prpl->handle_cmp))) { + g_free(l->data); + ic->deny = g_slist_delete_link(ic->deny, l); } - - ic->acc->prpl->rem_deny( ic, handle ); + + ic->acc->prpl->rem_deny(ic, handle); } -void imcb_clean_handle( struct im_connection *ic, char *handle ) +void imcb_clean_handle(struct im_connection *ic, char *handle) { /* Accepts a handle and does whatever is necessary to make it BitlBee-friendly. Currently this means removing everything outside 33-127 (ASCII printable excl spaces), @ (only one is allowed) and ! and : */ - char out[strlen(handle)+1]; + char out[strlen(handle) + 1]; int s, d; - + s = d = 0; - while( handle[s] ) - { - if( handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' && - ( handle[s] & 0x80 ) == 0 ) - { - if( handle[s] == '@' ) - { + while (handle[s]) { + if (handle[s] > ' ' && handle[s] != '!' && handle[s] != ':' && + (handle[s] & 0x80) == 0) { + if (handle[s] == '@') { /* See if we got an @ already? */ out[d] = 0; - if( strchr( out, '@' ) ) + if (strchr(out, '@')) { continue; + } } - + out[d++] = handle[s]; } - s ++; + s++; } out[d] = handle[s]; - - strcpy( handle, out ); + + strcpy(handle, out); } diff --git a/protocols/nogaim.h b/protocols/nogaim.h index a726b174..96bddb66 100644 --- a/protocols/nogaim.h +++ b/protocols/nogaim.h @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -38,7 +38,7 @@ #ifndef _NOGAIM_H #define _NOGAIM_H -#if(__sun) +#if (__sun) #include <inttypes.h> #else #include <stdint.h> @@ -71,29 +71,28 @@ #define OPT_PONGED 0x00020000 /* Received a keep-alive during last interval */ /* ok. now the fun begins. first we create a connection structure */ -struct im_connection -{ +struct im_connection { account_t *acc; uint32_t flags; - + /* each connection then can have its own protocol-specific data */ void *proto_data; - + /* all connections need an input watcher */ int inpa; guint keepalive; - + /* buddy list stuff. there is still a global groups for the buddy list, but * we need to maintain our own set of buddies, and our own permit/deny lists */ GSList *permit; GSList *deny; int permdeny; - + char *away; - + /* BitlBee */ bee_t *bee; - + GSList *groupchats; }; @@ -106,7 +105,7 @@ struct groupchat { * already, for example to avoid adding somebody two times. */ GList *in_room; //GList *ignored; - + //struct groupchat *next; /* The title variable contains the ID you gave when you created the * chat using imcb_chat_new(). */ @@ -152,121 +151,121 @@ struct prpl { /* 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 * set_add() function to add new settings. */ - void (* init) (account_t *); + void (* init) (account_t *); /* The typical usage of the login() function: * - Create an im_connection using imcb_new() from the account_t parameter. * - Initialize your myproto_data struct - you should store all your protocol-specific data there. * - Save your custom structure to im_connection->proto_data. * - Use proxy_connect() to connect to the server. */ - void (* login) (account_t *); + void (* login) (account_t *); /* Implementing this function is optional. */ - void (* keepalive) (struct im_connection *); + void (* keepalive) (struct im_connection *); /* In this function you should: * - Tell the server about you are logging out. * - g_free() your myproto_data struct as BitlBee does not know how to * properly do so. */ - void (* logout) (struct im_connection *); - + void (* logout) (struct im_connection *); + /* This function is called when the user wants to send a message to a handle. * - 'to' is a handle, not a nick * - 'flags' may be ignored */ - int (* buddy_msg) (struct im_connection *, char *to, char *message, int flags); + int (* buddy_msg) (struct im_connection *, char *to, char *message, int flags); /* This function is called then the user uses the /away IRC command. * - 'state' contains the away reason. * - 'message' may be ignored if your protocol does not support it. */ - void (* set_away) (struct im_connection *, char *state, char *message); + void (* set_away) (struct im_connection *, char *state, char *message); /* Implementing this function is optional. */ void (* get_away) (struct im_connection *, char *who); /* Implementing this function is optional. */ - int (* send_typing) (struct im_connection *, char *who, int flags); - + int (* send_typing) (struct im_connection *, char *who, int flags); + /* 'name' is a handle to add/remove. For now BitlBee doesn't really * handle groups, just set it to NULL, so you can ignore that * parameter. */ - void (* add_buddy) (struct im_connection *, char *name, char *group); - void (* remove_buddy) (struct im_connection *, char *name, char *group); - + void (* add_buddy) (struct im_connection *, char *name, char *group); + void (* remove_buddy) (struct im_connection *, char *name, char *group); + /* Block list stuff. Implementing these are optional. */ - void (* add_permit) (struct im_connection *, char *who); - void (* add_deny) (struct im_connection *, char *who); - void (* rem_permit) (struct im_connection *, char *who); - void (* rem_deny) (struct im_connection *, char *who); + void (* add_permit) (struct im_connection *, char *who); + void (* add_deny) (struct im_connection *, char *who); + void (* rem_permit) (struct im_connection *, char *who); + void (* rem_deny) (struct im_connection *, char *who); /* Doesn't actually have UI hooks. Not used at all, can be removed. */ void (* set_permit_deny)(struct im_connection *); - + /* Request profile info. Free-formatted stuff, the IM module gives back this info via imcb_log(). Implementing these are optional. */ - void (* get_info) (struct im_connection *, char *who); + void (* get_info) (struct im_connection *, char *who); /* set_my_name is *DEPRECATED*, not used by the UI anymore. Use the display_name setting instead. */ - void (* set_my_name) (struct im_connection *, char *name); - void (* set_name) (struct im_connection *, char *who, char *name); - + void (* set_my_name) (struct im_connection *, char *name); + void (* set_name) (struct im_connection *, char *who, char *name); + /* Group chat stuff. */ /* This is called when the user uses the /invite IRC command. * - 'who' may be ignored * - 'message' is a handle to invite */ - void (* chat_invite) (struct groupchat *, char *who, char *message); + void (* chat_invite) (struct groupchat *, char *who, char *message); /* This is called when the user uses the /kick IRC command. * - 'who' is a handle to kick * - 'message' is a kick message or NULL */ - void (* chat_kick) (struct groupchat *, char *who, const char *message); + void (* chat_kick) (struct groupchat *, char *who, const char *message); /* This is called when the user uses the /part IRC command in a group * chat. You just should tell the user about it, nothing more. */ - void (* chat_leave) (struct groupchat *); + void (* chat_leave) (struct groupchat *); /* This is called when the user sends a message to the groupchat. * 'flags' may be ignored. */ - void (* chat_msg) (struct groupchat *, char *message, int flags); + void (* chat_msg) (struct groupchat *, char *message, int flags); /* This is called when the user uses the /join #nick IRC command. * - 'who' is the handle of the nick */ struct groupchat * - (* chat_with) (struct im_connection *, char *who); + (* chat_with) (struct im_connection *, char *who); /* This is used when the user uses the /join #channel IRC command. If * your protocol does not support publicly named group chats, then do * not implement this. */ struct groupchat * - (* chat_join) (struct im_connection *, const char *room, - const char *nick, const char *password, set_t **sets); + (* chat_join) (struct im_connection *, const char *room, + const char *nick, const char *password, set_t **sets); /* Change the topic, if supported. Note that BitlBee expects the IM server to confirm the topic change with a regular topic change event. If it doesn't do that, you have to fake it to make it visible to the user. */ - void (* chat_topic) (struct groupchat *, char *topic); - + void (* chat_topic) (struct groupchat *, char *topic); + /* If your protocol module needs any special info for joining chatrooms other than a roomname + nickname, add them here. */ - void (* chat_add_settings) (account_t *acc, set_t **head); - void (* chat_free_settings) (account_t *acc, set_t **head); - + void (* chat_add_settings) (account_t *acc, set_t **head); + void (* chat_free_settings) (account_t *acc, set_t **head); + /* You can tell what away states your protocol supports, so that * BitlBee will try to map the IRC away reasons to them. If your * protocol doesn't have any, just return one generic "Away". */ GList *(* away_states)(struct im_connection *ic); - + /* Mainly for AOL, since they think "Bung hole" == "Bu ngho le". *sigh* * - Most protocols will just want to set this to g_strcasecmp().*/ int (* handle_cmp) (const char *who1, const char *who2); /* Implement these callbacks if you want to use imcb_ask_auth() */ - void (* auth_allow) (struct im_connection *, const char *who); - void (* auth_deny) (struct im_connection *, const char *who); + void (* auth_allow) (struct im_connection *, const char *who); + void (* auth_deny) (struct im_connection *, const char *who); /* Incoming transfer request */ - void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle ); - + void (* transfer_request) (struct im_connection *, file_transfer_t *ft, char *handle); + void (* buddy_data_add) (struct bee_user *bu); void (* buddy_data_free) (struct bee_user *bu); - + GList *(* buddy_action_list) (struct bee_user *bu); void *(* buddy_action) (struct bee_user *bu, const char *action, char * const args[], void *data); - + /* If null, equivalent to handle_cmp( ic->acc->user, who ) */ gboolean (* handle_is_self) (struct im_connection *, const char *who); @@ -281,72 +280,74 @@ struct prpl { /* im_api core stuff. */ void nogaim_init(); G_MODULE_EXPORT GSList *get_connections(); -G_MODULE_EXPORT struct prpl *find_protocol( const char *name ); +G_MODULE_EXPORT struct prpl *find_protocol(const char *name); /* When registering a new protocol, you should allocate space for a new prpl * struct, initialize it (set the function pointers to point to your * functions), finally call this function. */ -G_MODULE_EXPORT void register_protocol( struct prpl * ); +G_MODULE_EXPORT void register_protocol(struct prpl *); /* Connection management. */ /* You will need this function in prpl->login() to get an im_connection from * the account_t parameter. */ -G_MODULE_EXPORT struct im_connection *imcb_new( account_t *acc ); -G_MODULE_EXPORT void imc_free( struct im_connection *ic ); +G_MODULE_EXPORT struct im_connection *imcb_new(account_t *acc); +G_MODULE_EXPORT void imc_free(struct im_connection *ic); /* Once you're connected, you should call this function, so that the user will * see the success. */ -G_MODULE_EXPORT void imcb_connected( struct im_connection *ic ); +G_MODULE_EXPORT void imcb_connected(struct im_connection *ic); /* This can be used to disconnect when something went wrong (ie. read error * from the server). You probably want to set the second parameter to TRUE. */ -G_MODULE_EXPORT void imc_logout( struct im_connection *ic, int allow_reconnect ); +G_MODULE_EXPORT void imc_logout(struct im_connection *ic, int allow_reconnect); /* Communicating with the user. */ /* A printf()-like function to tell the user anything you want. */ -G_MODULE_EXPORT void imcb_log( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +G_MODULE_EXPORT void imcb_log(struct im_connection *ic, char *format, ...) G_GNUC_PRINTF(2, 3); /* To tell the user an error, ie. before logging out when an error occurs. */ -G_MODULE_EXPORT void imcb_error( struct im_connection *ic, char *format, ... ) G_GNUC_PRINTF( 2, 3 ); +G_MODULE_EXPORT void imcb_error(struct im_connection *ic, char *format, ...) G_GNUC_PRINTF(2, 3); /* To ask a your about something. * - 'msg' is the question. * - 'data' can be your custom struct - it will be passed to the callbacks. * - 'doit' or 'dont' will be called depending of the answer of the user. */ -G_MODULE_EXPORT void imcb_ask( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont ); -G_MODULE_EXPORT void imcb_ask_with_free( struct im_connection *ic, char *msg, void *data, query_callback doit, query_callback dont, query_callback myfree ); +G_MODULE_EXPORT void imcb_ask(struct im_connection *ic, char *msg, void *data, query_callback doit, + query_callback dont); +G_MODULE_EXPORT void imcb_ask_with_free(struct im_connection *ic, char *msg, void *data, query_callback doit, + query_callback dont, query_callback myfree); /* Two common questions you may want to ask: * - X added you to his contact list, allow? * - X is not in your contact list, want to add? */ -G_MODULE_EXPORT void imcb_ask_auth( struct im_connection *ic, const char *handle, const char *realname ); -G_MODULE_EXPORT void imcb_ask_add( struct im_connection *ic, const char *handle, const char *realname ); +G_MODULE_EXPORT void imcb_ask_auth(struct im_connection *ic, const char *handle, const char *realname); +G_MODULE_EXPORT void imcb_ask_add(struct im_connection *ic, const char *handle, const char *realname); /* Buddy management */ /* This function should be called for each handle which are visible to the * user, usually after a login, or if the user added a buddy and the IM * server confirms that the add was successful. Don't forget to do this! */ -G_MODULE_EXPORT void imcb_add_buddy( struct im_connection *ic, const char *handle, const char *group ); -G_MODULE_EXPORT void imcb_remove_buddy( struct im_connection *ic, const char *handle, char *group ); -G_MODULE_EXPORT struct buddy *imcb_find_buddy( struct im_connection *ic, char *handle ); -G_MODULE_EXPORT void imcb_rename_buddy( struct im_connection *ic, const char *handle, const char *realname ); -G_MODULE_EXPORT void imcb_buddy_nick_hint( struct im_connection *ic, const char *handle, const char *nick ); -G_MODULE_EXPORT void imcb_buddy_action_response( bee_user_t *bu, const char *action, char * const args[], void *data ); +G_MODULE_EXPORT void imcb_add_buddy(struct im_connection *ic, const char *handle, const char *group); +G_MODULE_EXPORT void imcb_remove_buddy(struct im_connection *ic, const char *handle, char *group); +G_MODULE_EXPORT struct buddy *imcb_find_buddy(struct im_connection *ic, char *handle); +G_MODULE_EXPORT void imcb_rename_buddy(struct im_connection *ic, const char *handle, const char *realname); +G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick); +G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data); -G_MODULE_EXPORT void imcb_buddy_typing( struct im_connection *ic, const char *handle, uint32_t flags ); -G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle( struct im_connection *ic, const char *handle ); -G_MODULE_EXPORT void imcb_clean_handle( struct im_connection *ic, char *handle ); +G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags); +G_MODULE_EXPORT struct bee_user *imcb_buddy_by_handle(struct im_connection *ic, const char *handle); +G_MODULE_EXPORT void imcb_clean_handle(struct im_connection *ic, char *handle); /* Actions, or whatever. */ -int imc_away_send_update( struct im_connection *ic ); -int imc_chat_msg( struct groupchat *c, char *msg, int flags ); +int imc_away_send_update(struct im_connection *ic); +int imc_chat_msg(struct groupchat *c, char *msg, int flags); -void imc_add_allow( struct im_connection *ic, char *handle ); -void imc_rem_allow( struct im_connection *ic, char *handle ); -void imc_add_block( struct im_connection *ic, char *handle ); -void imc_rem_block( struct im_connection *ic, char *handle ); +void imc_add_allow(struct im_connection *ic, char *handle); +void imc_rem_allow(struct im_connection *ic, char *handle); +void imc_add_block(struct im_connection *ic, char *handle); +void imc_rem_block(struct im_connection *ic, char *handle); /* Misc. stuff */ -char *set_eval_timezone( set_t *set, char *value ); -gboolean auto_reconnect( gpointer data, gint fd, b_input_condition cond ); -void cancel_auto_reconnect( struct account *a ); +char *set_eval_timezone(set_t *set, char *value); +gboolean auto_reconnect(gpointer data, gint fd, b_input_condition cond); +void cancel_auto_reconnect(struct account *a); #endif diff --git a/protocols/oscar/admin.c b/protocols/oscar/admin.c index 09082c5b..b317529b 100644 --- a/protocols/oscar/admin.c +++ b/protocols/oscar/admin.c @@ -27,17 +27,20 @@ static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a type = aimbs_get16(bs); len = aimbs_get16(bs); - if ((type == 0x0011) || (type == 0x0004)) + if ((type == 0x0011) || (type == 0x0004)) { str = 1; + } - if (str) - val = (guint8 *)aimbs_getstr(bs, len); - else + if (str) { + val = (guint8 *) aimbs_getstr(bs, len); + } else { val = aimbs_getraw(bs, len); + } /* XXX fix so its only called once for the entire packet */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, type, len, val, str); + } g_free(val); @@ -48,15 +51,17 @@ static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a return 1; } -static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs) { aim_rxcallback_t userfunc; guint16 status; status = aimbs_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, status); + } return 0; } @@ -64,10 +69,11 @@ static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) + if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) { return infochange(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0007) + } else if (snac->subtype == 0x0007) { return accountconfirm(sess, mod, rx, snac, bs); + } return 0; } @@ -78,7 +84,7 @@ int admin_modfirst(aim_session_t *sess, aim_module_t *mod) mod->family = AIM_CB_FAM_ADM; mod->version = 0x0001; mod->toolid = AIM_TOOL_NEWWIN; - mod->toolversion = 0x0629; + mod->toolversion = 0x0629; mod->flags = 0; strncpy(mod->name, "admin", sizeof(mod->name)); mod->snachandler = snachandler; @@ -92,17 +98,18 @@ int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *ne aim_tlvlist_t *tl = NULL; aim_snacid_t snacid; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+strlen(curpw)+4+strlen(newpw)))) + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + strlen(curpw) + 4 + strlen(newpw)))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid); /* new password TLV t(0002) */ - aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), (guint8 *)newpw); + aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), (guint8 *) newpw); /* current password TLV t(0012) */ - aim_addtlvtochain_raw(&tl, 0x0012, strlen(curpw), (guint8 *)curpw); + aim_addtlvtochain_raw(&tl, 0x0012, strlen(curpw), (guint8 *) curpw); aim_writetlvchain(&tx->data, &tl); aim_freetlvchain(&tl); @@ -113,7 +120,7 @@ int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *ne } /* - * Request account confirmation. + * Request account confirmation. * * This will cause an email to be sent to the address associated with * the account. By following the instructions in the mail, you can @@ -130,14 +137,15 @@ int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn) * * The only known valid tag is 0x0011 (email address). * - */ + */ int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, guint16 info) { aim_frame_t *tx; aim_snacid_t snacid; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14))) + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0002, 0x0002, 0x0000, NULL, 0); aim_putsnac(&tx->data, 0x0007, 0x0002, 0x0000, snacid); @@ -156,17 +164,18 @@ int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newema aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newemail)))) + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(newemail)))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid); - aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), (guint8 *)newemail); - + aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), (guint8 *) newemail); + aim_writetlvchain(&tx->data, &tl); aim_freetlvchain(&tl); - + aim_tx_enqueue(sess, tx); return 0; @@ -178,17 +187,18 @@ int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(newnick)))) + if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(newnick)))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0); aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid); - aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), (guint8 *)newnick); - + aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), (guint8 *) newnick); + aim_writetlvchain(&tx->data, &tl); aim_freetlvchain(&tl); - + aim_tx_enqueue(sess, tx); diff --git a/protocols/oscar/admin.h b/protocols/oscar/admin.h index f9d74cae..38a362bb 100644 --- a/protocols/oscar/admin.h +++ b/protocols/oscar/admin.h @@ -5,7 +5,7 @@ /* * SNAC Family: Administrative Services. - */ + */ #define AIM_CB_ADM_ERROR 0x0001 #define AIM_CB_ADM_INFOCHANGE_REPLY 0x0005 #define AIM_CB_ADM_DEFAULT 0xffff diff --git a/protocols/oscar/aim.h b/protocols/oscar/aim.h index 3f26b392..265cd19b 100644 --- a/protocols/oscar/aim.h +++ b/protocols/oscar/aim.h @@ -1,4 +1,4 @@ -/* +/* * Main libfaim header. Must be included in client for prototypes/macros. * * "come on, i turned a chick lesbian; i think this is the hackish equivalent" @@ -28,11 +28,11 @@ typedef guint16 flap_seqnum_t; /* Portability stuff (DMP) */ #if defined(mach) && defined(__APPLE__) -#define gethostbyname(x) gethostbyname2(x, AF_INET) +#define gethostbyname(x) gethostbyname2(x, AF_INET) #endif -/* - * Current Maximum Length for Screen Names (not including NULL) +/* + * Current Maximum Length for Screen Names (not including NULL) * * Currently only names up to 16 characters can be registered * however it is aparently legal for them to be larger. @@ -52,7 +52,7 @@ typedef guint16 flap_seqnum_t; * with utterly oversized instant messages! * * XXX: the real limit is the total SNAC size at 8192. Fix this. - * + * */ #define MAXMSGLEN 7987 @@ -66,7 +66,7 @@ typedef guint16 flap_seqnum_t; * Current Maximum Length for Chat Room Messages * * This is actually defined by the protocol to be - * dynamic, but I have yet to see due cause to + * dynamic, but I have yet to see due cause to * define it dynamically here. Maybe later. * */ @@ -80,10 +80,10 @@ typedef guint16 flap_seqnum_t; #define AIM_MD5_STRING "AOL Instant Messenger (SM)" /* - * Default Authorizer server name and TCP port for the OSCAR farm. + * Default Authorizer server name and TCP port for the OSCAR farm. * * You shouldn't need to change this unless you're writing - * your own server. + * your own server. * * Note that only one server is needed to start the whole * AIM process. The later server addresses come from @@ -106,7 +106,7 @@ typedef guint16 flap_seqnum_t; #define AIM_SNAC_HASH_SIZE 16 /* - * Client info. Filled in by the client and passed in to + * Client info. Filled in by the client and passed in to * aim_send_login(). The information ends up getting passed to OSCAR * through the initial login command. * @@ -123,44 +123,44 @@ struct client_info_s { }; #define AIM_CLIENTINFO_KNOWNGOOD_3_5_1670 { \ - "AOL Instant Messenger (SM), version 3.5.1670/WIN32", \ - 0x0004, \ - 0x0003, \ - 0x0005, \ - 0x0000, \ - 0x0686, \ - "us", \ - "en", \ + "AOL Instant Messenger (SM), version 3.5.1670/WIN32", \ + 0x0004, \ + 0x0003, \ + 0x0005, \ + 0x0000, \ + 0x0686, \ + "us", \ + "en", \ } #define AIM_CLIENTINFO_KNOWNGOOD_4_1_2010 { \ - "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ - 0x0004, \ - 0x0004, \ - 0x0001, \ - 0x0000, \ - 0x07da, \ - "us", \ - "en", \ + "AOL Instant Messenger (SM), version 4.1.2010/WIN32", \ + 0x0004, \ + 0x0004, \ + 0x0001, \ + 0x0000, \ + 0x07da, \ + "us", \ + "en", \ } #define AIM_CLIENTINFO_KNOWNGOOD_5_1_3036 { \ - "AOL Instant Messenger, version 5.1.3036/WIN32", \ - 0x0109, \ - 0x0005, \ - 0x0001, \ - 0x0000, \ - 0x0bdc, \ - "us", \ - "en", \ + "AOL Instant Messenger, version 5.1.3036/WIN32", \ + 0x0109, \ + 0x0005, \ + 0x0001, \ + 0x0000, \ + 0x0bdc, \ + "us", \ + "en", \ } /* * I would make 4.1.2010 the default, but they seem to have found - * an alternate way of breaking that one. + * an alternate way of breaking that one. * * 3.5.1670 should work fine, however, you will be subjected to the - * memory test, which may require you to have a WinAIM binary laying + * memory test, which may require you to have a WinAIM binary laying * around. (see login.c::memrequest()) */ #define AIM_CLIENTINFO_KNOWNGOOD AIM_CLIENTINFO_KNOWNGOOD_5_1_3036 @@ -170,8 +170,8 @@ struct client_info_s { #define FALSE 0 #endif -/* - * These could be arbitrary, but its easier to use the actual AIM values +/* + * These could be arbitrary, but its easier to use the actual AIM values */ #define AIM_CONN_TYPE_AUTH 0x0007 #define AIM_CONN_TYPE_ADS 0x0005 @@ -206,11 +206,11 @@ struct client_info_s { #define AIM_MTYPE_EEXPRESS 0x0E #define AIM_MTYPE_CONTACTS 0x13 #define AIM_MTYPE_PLUGIN 0x1A -#define AIM_MTYPE_AUTOAWAY 0xE8 -#define AIM_MTYPE_AUTOBUSY 0xE9 -#define AIM_MTYPE_AUTONA 0xEA -#define AIM_MTYPE_AUTODND 0xEB -#define AIM_MTYPE_AUTOFFC 0xEC +#define AIM_MTYPE_AUTOAWAY 0xE8 +#define AIM_MTYPE_AUTOBUSY 0xE9 +#define AIM_MTYPE_AUTONA 0xEA +#define AIM_MTYPE_AUTODND 0xEB +#define AIM_MTYPE_AUTOFFC 0xEC typedef struct aim_conn_s { int fd; @@ -221,7 +221,7 @@ typedef struct aim_conn_s { void *priv; /* misc data the client may want to store */ void *internal; /* internal conn-specific libfaim data */ time_t lastactivity; /* time of last transmit */ - int forcedlatency; + int forcedlatency; void *handlerlist; void *sessv; /* pointer to parent session */ void *inside; /* only accessible from inside libfaim */ @@ -251,14 +251,14 @@ typedef struct aim_bstream_s { typedef struct aim_frame_s { guint8 hdrtype; /* defines which piece of the union to use */ union { - struct { + struct { guint8 type; - flap_seqnum_t seqnum; + flap_seqnum_t seqnum; } flap; } hdr; - aim_bstream_t data; /* payload stream */ - guint8 handled; /* 0 = new, !0 = been handled */ - guint8 nofree; /* 0 = free data on purge, 1 = only unlink */ + aim_bstream_t data; /* payload stream */ + guint8 handled; /* 0 = new, !0 = been handled */ + guint8 nofree; /* 0 = free data on purge, 1 = only unlink */ aim_conn_t *conn; /* the connection it came in on... */ struct aim_frame_s *next; } aim_frame_t; @@ -272,7 +272,7 @@ typedef struct aim_msgcookie_s { } aim_msgcookie_t; /* - * AIM Session: The main client-data interface. + * AIM Session: The main client-data interface. * */ typedef struct aim_session_s { @@ -280,10 +280,10 @@ typedef struct aim_session_s { /* ---- Client Accessible ------------------------ */ /* Our screen name. */ - char sn[MAXSNLEN+1]; + char sn[MAXSNLEN + 1]; /* - * Pointer to anything the client wants to + * Pointer to anything the client wants to * explicitly associate with this session. * * This is for use in the callbacks mainly. In any @@ -313,10 +313,10 @@ typedef struct aim_session_s { * These are only used when you don't use your own lowlevel * I/O. I don't suggest that you use libfaim's internal I/O. * Its really bad and the API/event model is quirky at best. - * + * */ - aim_frame_t *queue_outgoing; - aim_frame_t *queue_incoming; + aim_frame_t *queue_outgoing; + aim_frame_t *queue_incoming; /* * Tx Enqueuing function. @@ -329,7 +329,7 @@ typedef struct aim_session_s { int (*tx_enqueue)(struct aim_session_s *, aim_frame_t *); /* - * Outstanding snac handling + * Outstanding snac handling * * XXX: Should these be per-connection? -mid */ @@ -383,13 +383,13 @@ typedef struct aim_session_s { * AIM User Info, Standard Form. */ typedef struct { - char sn[MAXSNLEN+1]; + char sn[MAXSNLEN + 1]; guint16 warnlevel; guint16 idletime; guint16 flags; guint32 membersince; guint32 onlinesince; - guint32 sessionlen; + guint32 sessionlen; guint32 capabilities; struct { guint32 status; @@ -409,21 +409,21 @@ typedef struct { #define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 #define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 -#define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ -#define AIM_FLAG_ADMINISTRATOR 0x0002 -#define AIM_FLAG_AOL 0x0004 -#define AIM_FLAG_OSCAR_PAY 0x0008 -#define AIM_FLAG_FREE 0x0010 -#define AIM_FLAG_AWAY 0x0020 -#define AIM_FLAG_ICQ 0x0040 -#define AIM_FLAG_WIRELESS 0x0080 -#define AIM_FLAG_UNKNOWN100 0x0100 -#define AIM_FLAG_UNKNOWN200 0x0200 +#define AIM_FLAG_UNCONFIRMED 0x0001 /* "damned transients" */ +#define AIM_FLAG_ADMINISTRATOR 0x0002 +#define AIM_FLAG_AOL 0x0004 +#define AIM_FLAG_OSCAR_PAY 0x0008 +#define AIM_FLAG_FREE 0x0010 +#define AIM_FLAG_AWAY 0x0020 +#define AIM_FLAG_ICQ 0x0040 +#define AIM_FLAG_WIRELESS 0x0080 +#define AIM_FLAG_UNKNOWN100 0x0100 +#define AIM_FLAG_UNKNOWN200 0x0200 #define AIM_FLAG_ACTIVEBUDDY 0x0400 -#define AIM_FLAG_UNKNOWN800 0x0800 +#define AIM_FLAG_UNKNOWN800 0x0800 #define AIM_FLAG_ABINTERNAL 0x1000 -#define AIM_FLAG_ALLUSERS 0x001f +#define AIM_FLAG_ALLUSERS 0x001f /* * TLV handling @@ -467,7 +467,8 @@ int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 type, const guint32 int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l, const guint8 *v); int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 caps); int aim_addtlvtochain_noval(aim_tlvlist_t **list, const guint16 type); -int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance); +int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, + guint16 instance); int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *ui); int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl); int aim_counttlvchain(aim_tlvlist_t **list); @@ -542,7 +543,8 @@ int aim_conn_setlatency(aim_conn_t *conn, int newval); void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn); -int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, u_short family, u_short type, aim_rxcallback_t newhandler, u_short flags); +int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, u_short family, u_short type, aim_rxcallback_t newhandler, + u_short flags); int aim_clearhandlers(aim_conn_t *conn); aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, guint16 group); @@ -557,7 +559,7 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn); int aim_conn_isconnecting(aim_conn_t *conn); typedef void (*faim_debugging_callback_t)(aim_session_t *sess, int level, const char *format, va_list va); -int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t); +int aim_setdebuggingcb(aim_session_t * sess, faim_debugging_callback_t); void aim_session_init(aim_session_t *, guint32 flags, int debuglevel); void aim_session_kill(aim_session_t *); void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password); @@ -617,7 +619,8 @@ int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn); /* aim_im.c */ -aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, guint16 numfiles, guint32 totsize); +aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, guint16 numfiles, + guint32 totsize); aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn); int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size); @@ -652,29 +655,31 @@ int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur); #define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000 #define AIM_TRANSFER_DENY_DECLINE 0x0001 #define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002 -aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const guint8 *cookie, const guint8 *ip, guint16 listingfiles, guint16 listingtotsize, guint16 listingsize, guint32 listingchecksum, guint16 rendid); +aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const guint8 *cookie, + const guint8 *ip, guint16 listingfiles, guint16 listingtotsize, guint16 listingsize, + guint32 listingchecksum, guint16 rendid); int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, unsigned short); -#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 -#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 +#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED 0x00000001 +#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED 0x00000002 /* This is what the server will give you if you don't set them yourself. */ #define AIM_IMPARAM_DEFAULTS { \ - 0, \ - AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ - 512, /* !! Note how small this is. */ \ - (99.9)*10, (99.9)*10, \ - 1000 /* !! And how large this is. */ \ + 0, \ + AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ + 512, /* !! Note how small this is. */ \ + (99.9) * 10, (99.9) * 10, \ + 1000 /* !! And how large this is. */ \ } /* This is what most AIM versions use. */ #define AIM_IMPARAM_REASONABLE { \ - 0, \ - AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ - 8000, \ - (99.9)*10, (99.9)*10, \ - 0 \ + 0, \ + AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \ + 8000, \ + (99.9) * 10, (99.9) * 10, \ + 0 \ } @@ -715,17 +720,18 @@ struct aim_chat_exchangeinfo { char *lang2; }; -#define AIM_CHATFLAGS_NOREFLECT 0x0001 -#define AIM_CHATFLAGS_AWAY 0x0002 -#define AIM_CHATFLAGS_UNICODE 0x0004 -#define AIM_CHATFLAGS_ISO_8859_1 0x0008 +#define AIM_CHATFLAGS_NOREFLECT 0x0001 +#define AIM_CHATFLAGS_AWAY 0x0002 +#define AIM_CHATFLAGS_UNICODE 0x0004 +#define AIM_CHATFLAGS_ISO_8859_1 0x0008 int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen); int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance); int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn); -int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance); +int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange, + const char *roomname, guint16 instance); int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, guint16 exchange); @@ -737,50 +743,50 @@ int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *na * their use. * */ -#define aimutil_put8(buf, data) ((*(buf) = (u_char)(data)&0xff),1) -#define aimutil_get8(buf) ((*(buf))&0xff) +#define aimutil_put8(buf, data) ((*(buf) = (u_char) (data) & 0xff), 1) +#define aimutil_get8(buf) ((*(buf)) & 0xff) #define aimutil_put16(buf, data) ( \ - (*(buf) = (u_char)((data)>>8)&0xff), \ - (*((buf)+1) = (u_char)(data)&0xff), \ - 2) -#define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff)) + (*(buf) = (u_char) ((data) >> 8) & 0xff), \ + (*((buf) + 1) = (u_char) (data) & 0xff), \ + 2) +#define aimutil_get16(buf) ((((*(buf)) << 8) & 0xff00) + ((*((buf) + 1)) & 0xff)) #define aimutil_put32(buf, data) ( \ - (*((buf)) = (u_char)((data)>>24)&0xff), \ - (*((buf)+1) = (u_char)((data)>>16)&0xff), \ - (*((buf)+2) = (u_char)((data)>>8)&0xff), \ - (*((buf)+3) = (u_char)(data)&0xff), \ - 4) -#define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \ - (((*((buf)+1))<<16)&0x00ff0000) + \ - (((*((buf)+2))<< 8)&0x0000ff00) + \ - (((*((buf)+3) )&0x000000ff))) + (*((buf)) = (u_char) ((data) >> 24) & 0xff), \ + (*((buf) + 1) = (u_char) ((data) >> 16) & 0xff), \ + (*((buf) + 2) = (u_char) ((data) >> 8) & 0xff), \ + (*((buf) + 3) = (u_char) (data) & 0xff), \ + 4) +#define aimutil_get32(buf) ((((*(buf)) << 24) & 0xff000000) + \ + (((*((buf) + 1)) << 16) & 0x00ff0000) + \ + (((*((buf) + 2)) << 8) & 0x0000ff00) + \ + (((*((buf) + 3)) & 0x000000ff))) /* Little-endian versions (damn ICQ) */ #define aimutil_putle8(buf, data) ( \ - (*(buf) = (unsigned char)(data) & 0xff), \ - 1) + (*(buf) = (unsigned char) (data) & 0xff), \ + 1) #define aimutil_getle8(buf) ( \ - (*(buf)) & 0xff \ - ) + (*(buf)) & 0xff \ + ) #define aimutil_putle16(buf, data) ( \ - (*((buf)+0) = (unsigned char)((data) >> 0) & 0xff), \ - (*((buf)+1) = (unsigned char)((data) >> 8) & 0xff), \ - 2) + (*((buf) + 0) = (unsigned char) ((data) >> 0) & 0xff), \ + (*((buf) + 1) = (unsigned char) ((data) >> 8) & 0xff), \ + 2) #define aimutil_getle16(buf) ( \ - (((*((buf)+0)) << 0) & 0x00ff) + \ - (((*((buf)+1)) << 8) & 0xff00) \ - ) + (((*((buf) + 0)) << 0) & 0x00ff) + \ + (((*((buf) + 1)) << 8) & 0xff00) \ + ) #define aimutil_putle32(buf, data) ( \ - (*((buf)+0) = (unsigned char)((data) >> 0) & 0xff), \ - (*((buf)+1) = (unsigned char)((data) >> 8) & 0xff), \ - (*((buf)+2) = (unsigned char)((data) >> 16) & 0xff), \ - (*((buf)+3) = (unsigned char)((data) >> 24) & 0xff), \ - 4) + (*((buf) + 0) = (unsigned char) ((data) >> 0) & 0xff), \ + (*((buf) + 1) = (unsigned char) ((data) >> 8) & 0xff), \ + (*((buf) + 2) = (unsigned char) ((data) >> 16) & 0xff), \ + (*((buf) + 3) = (unsigned char) ((data) >> 24) & 0xff), \ + 4) #define aimutil_getle32(buf) ( \ - (((*((buf)+0)) << 0) & 0x000000ff) + \ - (((*((buf)+1)) << 8) & 0x0000ff00) + \ - (((*((buf)+2)) << 16) & 0x00ff0000) + \ - (((*((buf)+3)) << 24) & 0xff000000)) + (((*((buf) + 0)) << 0) & 0x000000ff) + \ + (((*((buf) + 1)) << 8) & 0x0000ff00) + \ + (((*((buf) + 2)) << 16) & 0x00ff0000) + \ + (((*((buf) + 3)) << 24) & 0xff000000)) int aim_sncmp(const char *a, const char *b); @@ -796,7 +802,7 @@ int aim_sncmp(const char *a, const char *b); /* * SNAC Family: Ack. - * + * * Not really a family, but treating it as one really * helps it fit into the libfaim callback structure better. * @@ -805,7 +811,7 @@ int aim_sncmp(const char *a, const char *b); /* * SNAC Family: General. - */ + */ #define AIM_CB_GEN_ERROR 0x0001 #define AIM_CB_GEN_CLIENTREADY 0x0002 #define AIM_CB_GEN_SERVERREADY 0x0003 @@ -830,7 +836,7 @@ int aim_sncmp(const char *a, const char *b); /* * SNAC Family: Advertisement Services - */ + */ #define AIM_CB_ADS_ERROR 0x0001 #define AIM_CB_ADS_DEFAULT 0xffff @@ -839,7 +845,7 @@ int aim_sncmp(const char *a, const char *b); * * See non-SNAC note below. */ -#define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001/* connect request -- actually an OSCAR CAP*/ +#define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001 /* connect request -- actually an OSCAR CAP*/ #define AIM_CB_OFT_DIRECTIMINCOMING 0x0002 #define AIM_CB_OFT_DIRECTIMDISCONNECT 0x0003 #define AIM_CB_OFT_DIRECTIMTYPING 0x0004 @@ -868,7 +874,7 @@ int aim_sncmp(const char *a, const char *b); * these, we can integrated non-SNAC services into * the SNAC-centered libfaim callback structure. * - */ + */ #define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001 #define AIM_CB_SPECIAL_AUTHOTHER 0x0002 #define AIM_CB_SPECIAL_CONNERR 0x0003 diff --git a/protocols/oscar/aim_internal.h b/protocols/oscar/aim_internal.h index e4cdd0a2..4c1be740 100644 --- a/protocols/oscar/aim_internal.h +++ b/protocols/oscar/aim_internal.h @@ -21,8 +21,9 @@ typedef struct aim_module_s { guint16 toolid; guint16 toolversion; guint16 flags; - char name[AIM_MODULENAME_MAXLEN+1]; - int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs); + char name[AIM_MODULENAME_MAXLEN + 1]; + int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs); void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod); void *priv; struct aim_module_s *next; @@ -106,12 +107,13 @@ typedef struct aim_snac_s { } aim_snac_t; void aim_initsnachash(aim_session_t *sess); -aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen); +aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags, + const void *data, const int datalen); aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id); void aim_cleansnacs(aim_session_t *, int maxage); int aim_putsnac(aim_bstream_t *, guint16 family, guint16 type, guint16 flags, aim_snacid_t id); -int aim_oft_buildheader(unsigned char *,struct aim_fileheader_t *); +int aim_oft_buildheader(unsigned char *, struct aim_fileheader_t *); int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...); @@ -137,7 +139,7 @@ struct aim_tool_version { guint16 toolversion; }; -/* +/* * In SNACland, the terms 'family' and 'group' are synonymous -- the former * is my term, the latter is AOL's. */ @@ -169,9 +171,9 @@ struct rateclass { /* * This is inside every connection. But it is a void * to anything * outside of libfaim. It should remain that way. It's called data - * abstraction. Maybe you've heard of it. (Probably not if you're a + * abstraction. Maybe you've heard of it. (Probably not if you're a * libfaim user.) - * + * */ typedef struct aim_conn_inside_s { struct snacgroup *groups; diff --git a/protocols/oscar/auth.c b/protocols/oscar/auth.c index 7a6b05d4..5e1dc4ec 100644 --- a/protocols/oscar/auth.c +++ b/protocols/oscar/auth.c @@ -3,13 +3,13 @@ * */ -#include <aim.h> +#include <aim.h> #include "md5.h" static int aim_encode_password(const char *password, unsigned char *encoded); -/* +/* * This just pushes the passed cookie onto the passed connection, without * the SNAC header or any of that. * @@ -22,11 +22,12 @@ int aim_sendcookie(aim_session_t *sess, aim_conn_t *conn, const guint8 *chipsaho aim_frame_t *fr; aim_tlvlist_t *tl = NULL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4+2+2+AIM_COOKIELEN))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4 + 2 + 2 + AIM_COOKIELEN))) { return -ENOMEM; + } aimbs_put32(&fr->data, 0x00000001); - aim_addtlvtochain_raw(&tl, 0x0006, AIM_COOKIELEN, chipsahoy); + aim_addtlvtochain_raw(&tl, 0x0006, AIM_COOKIELEN, chipsahoy); aim_writetlvchain(&fr->data, &tl); aim_freetlvchain(&tl); @@ -47,8 +48,9 @@ int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn) { aim_frame_t *fr; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4))) { return -ENOMEM; + } aimbs_put32(&fr->data, 0x00000001); @@ -94,24 +96,25 @@ static int goddamnicq(aim_session_t *sess, aim_conn_t *conn, const char *sn) { aim_frame_t fr; aim_rxcallback_t userfunc; - + sess->flags &= ~AIM_SESS_FLAGS_SNACLOGIN; sess->flags |= AIM_SESS_FLAGS_XORLOGIN; fr.conn = conn; - - if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007))) + + if ((userfunc = aim_callhandler(sess, conn, 0x0017, 0x0007))) { userfunc(sess, &fr, ""); + } return 0; } /* - * In AIM 3.5 protocol, the first stage of login is to request login from the - * Authorizer, passing it the screen name for verification. If the name is - * invalid, a 0017/0003 is spit back, with the standard error contents. If - * valid, a 0017/0007 comes back, which is the signal to send it the main - * login command (0017/0002). + * In AIM 3.5 protocol, the first stage of login is to request login from the + * Authorizer, passing it the screen name for verification. If the name is + * invalid, a 0017/0003 is spit back, with the standard error contents. If + * valid, a 0017/0007 comes back, which is the signal to send it the main + * login command (0017/0002). * */ int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) @@ -120,24 +123,27 @@ int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; struct im_connection *ic = sess->aux_data; - - if (!sess || !conn || !sn) + + if (!sess || !conn || !sn) { return -EINVAL; + } - if (g_ascii_isdigit(sn[0]) && set_getbool(&ic->acc->set, "old_icq_auth")) + if (g_ascii_isdigit(sn[0]) && set_getbool(&ic->acc->set, "old_icq_auth")) { return goddamnicq(sess, conn, sn); + } sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; aim_sendflapver(sess, conn); - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2+2+strlen(sn)))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(sn)))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid); - aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *)sn); + aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn); aim_writetlvchain(&fr->data, &tl); aim_freetlvchain(&tl); @@ -151,15 +157,16 @@ int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) */ static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password) { - static const char clientstr[] = {"ICQ Inc. - Product of ICQ (TM) 2001b.5.17.1.3642.85"}; - static const char lang[] = {"en"}; - static const char country[] = {"us"}; + static const char clientstr[] = { "ICQ Inc. - Product of ICQ (TM) 2001b.5.17.1.3642.85" }; + static const char lang[] = { "en" }; + static const char country[] = { "us" }; aim_frame_t *fr; aim_tlvlist_t *tl = NULL; guint8 *password_encoded; - if (!(password_encoded = (guint8 *) g_malloc(strlen(password)))) + if (!(password_encoded = (guint8 *) g_malloc(strlen(password)))) { return -ENOMEM; + } if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 1152))) { g_free(password_encoded); @@ -169,17 +176,17 @@ static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, co aim_encode_password(password, password_encoded); aimbs_put32(&fr->data, 0x00000001); - aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *)sn); + aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn); aim_addtlvtochain_raw(&tl, 0x0002, strlen(password), password_encoded); - aim_addtlvtochain_raw(&tl, 0x0003, strlen(clientstr), (guint8 *)clientstr); + aim_addtlvtochain_raw(&tl, 0x0003, strlen(clientstr), (guint8 *) clientstr); aim_addtlvtochain16(&tl, 0x0016, 0x010a); /* cliend ID */ aim_addtlvtochain16(&tl, 0x0017, 0x0005); /* major version */ aim_addtlvtochain16(&tl, 0x0018, 0x0011); /* minor version */ aim_addtlvtochain16(&tl, 0x0019, 0x0001); /* point version */ aim_addtlvtochain16(&tl, 0x001a, 0x0e3a); /* build */ aim_addtlvtochain32(&tl, 0x0014, 0x00000055); /* distribution chan */ - aim_addtlvtochain_raw(&tl, 0x000f, strlen(lang), (guint8 *)lang); - aim_addtlvtochain_raw(&tl, 0x000e, strlen(country), (guint8 *)country); + aim_addtlvtochain_raw(&tl, 0x000f, strlen(lang), (guint8 *) lang); + aim_addtlvtochain_raw(&tl, 0x000e, strlen(country), (guint8 *) country); aim_writetlvchain(&fr->data, &tl); @@ -193,7 +200,7 @@ static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, co /* * send_login(int socket, char *sn, char *password) - * + * * This is the initial login request packet. * * NOTE!! If you want/need to make use of the aim_sendmemblock() function, @@ -248,7 +255,7 @@ static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, co * point = (not sent) * build = 0x0013 * unknown= (not sent) - * + * * AIM for Linux 1.1.112: * clientstring = "AOL Instant Messenger (SM)" * clientid = 0x1d09 @@ -260,32 +267,36 @@ static int goddamnicq2(aim_session_t *sess, aim_conn_t *conn, const char *sn, co * serverstore = 0x01 * */ -int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, struct client_info_s *ci, const char *key) +int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password, + struct client_info_s *ci, const char *key) { aim_frame_t *fr; aim_tlvlist_t *tl = NULL; guint8 digest[16]; aim_snacid_t snacid; - if (!ci || !sn || !password) + if (!ci || !sn || !password) { return -EINVAL; + } /* * What the XORLOGIN flag _really_ means is that its an ICQ login, * which is really stupid and painful, so its not done here. * */ - if (sess->flags & AIM_SESS_FLAGS_XORLOGIN) + if (sess->flags & AIM_SESS_FLAGS_XORLOGIN) { return goddamnicq2(sess, conn, sn, password); + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0017, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid); - aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *)sn); + aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn); aim_encode_password_md5(password, key, digest); aim_addtlvtochain_raw(&tl, 0x0025, 16, digest); @@ -294,15 +305,16 @@ int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const * Newer versions of winaim have an empty type x004c TLV here. */ - if (ci->clientstring) - aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), (guint8 *)ci->clientstring); - aim_addtlvtochain16(&tl, 0x0016, (guint16)ci->clientid); - aim_addtlvtochain16(&tl, 0x0017, (guint16)ci->major); - aim_addtlvtochain16(&tl, 0x0018, (guint16)ci->minor); - aim_addtlvtochain16(&tl, 0x0019, (guint16)ci->point); - aim_addtlvtochain16(&tl, 0x001a, (guint16)ci->build); - aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), (guint8 *)ci->country); - aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), (guint8 *)ci->lang); + if (ci->clientstring) { + aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), (guint8 *) ci->clientstring); + } + aim_addtlvtochain16(&tl, 0x0016, (guint16) ci->clientid); + aim_addtlvtochain16(&tl, 0x0017, (guint16) ci->major); + aim_addtlvtochain16(&tl, 0x0018, (guint16) ci->minor); + aim_addtlvtochain16(&tl, 0x0019, (guint16) ci->point); + aim_addtlvtochain16(&tl, 0x001a, (guint16) ci->build); + aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), (guint8 *) ci->country); + aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), (guint8 *) ci->lang); /* * If set, old-fashioned buddy lists will not work. You will need @@ -313,7 +325,7 @@ int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const aim_writetlvchain(&fr->data, &tl); aim_freetlvchain(&tl); - + aim_tx_enqueue(sess, fr); return 0; @@ -323,11 +335,11 @@ int aim_encode_password_md5(const char *password, const char *key, guint8 *diges { md5_state_t state; - md5_init(&state); - md5_append(&state, (const md5_byte_t *)key, strlen(key)); - md5_append(&state, (const md5_byte_t *)password, strlen(password)); - md5_append(&state, (const md5_byte_t *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - md5_finish(&state, (md5_byte_t *)digest); + md5_init(&state); + md5_append(&state, (const md5_byte_t *) key, strlen(key)); + md5_append(&state, (const md5_byte_t *) password, strlen(password)); + md5_append(&state, (const md5_byte_t *) AIM_MD5_STRING, strlen(AIM_MD5_STRING)); + md5_finish(&state, (md5_byte_t *) digest); return 0; } @@ -344,7 +356,7 @@ int aim_encode_password_md5(const char *password, const char *key, guint8 *diges * the null. The encoded password buffer /is not %NULL terminated/. * * The encoding_table seems to be a fixed set of values. We'll - * hope it doesn't change over time! + * hope it doesn't change over time! * * This is only used for the XOR method, not the better MD5 method. * @@ -352,7 +364,7 @@ int aim_encode_password_md5(const char *password, const char *key, guint8 *diges static int aim_encode_password(const char *password, guint8 *encoded) { guint8 encoding_table[] = { - /* v2.1 table, also works for ICQ */ + /* v2.1 table, also works for ICQ */ 0xf3, 0x26, 0x81, 0xc4, 0x39, 0x86, 0xdb, 0x92, 0x71, 0xa3, 0xb9, 0xe6, @@ -360,8 +372,9 @@ static int aim_encode_password(const char *password, guint8 *encoded) }; int i; - for (i = 0; i < strlen(password); i++) + for (i = 0; i < strlen(password); i++) { encoded[i] = (password[i] ^ encoding_table[i]); + } return 0; } @@ -369,7 +382,7 @@ static int aim_encode_password(const char *password, guint8 *encoded) /* * This is sent back as a general response to the login command. * It can be either an error or a success, depending on the - * precense of certain TLVs. + * precense of certain TLVs. * * The client should check the value passed as errorcode. If * its nonzero, there was an error. @@ -403,16 +416,19 @@ static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo * Check for an error code. If so, we should also * have an error url. */ - if (aim_gettlv(tlvlist, 0x0008, 1)) + if (aim_gettlv(tlvlist, 0x0008, 1)) { info.errorcode = aim_gettlv16(tlvlist, 0x0008, 1); - if (aim_gettlv(tlvlist, 0x0004, 1)) + } + if (aim_gettlv(tlvlist, 0x0004, 1)) { info.errorurl = aim_gettlv_str(tlvlist, 0x0004, 1); + } /* * BOS server address. */ - if (aim_gettlv(tlvlist, 0x0005, 1)) + if (aim_gettlv(tlvlist, 0x0005, 1)) { info.bosip = aim_gettlv_str(tlvlist, 0x0005, 1); + } /* * Authorization cookie. @@ -429,8 +445,9 @@ static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo * The email address attached to this account * Not available for ICQ logins. */ - if (aim_gettlv(tlvlist, 0x0011, 1)) + if (aim_gettlv(tlvlist, 0x0011, 1)) { info.email = aim_gettlv_str(tlvlist, 0x0011, 1); + } /* * The registration status. (Not real sure what it means.) @@ -444,34 +461,46 @@ static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo * to other users or not. AFAIK, this feature is no longer used. * */ - if (aim_gettlv(tlvlist, 0x0013, 1)) + if (aim_gettlv(tlvlist, 0x0013, 1)) { info.regstatus = aim_gettlv16(tlvlist, 0x0013, 1); + } - if (aim_gettlv(tlvlist, 0x0040, 1)) + if (aim_gettlv(tlvlist, 0x0040, 1)) { info.latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1); - if (aim_gettlv(tlvlist, 0x0041, 1)) + } + if (aim_gettlv(tlvlist, 0x0041, 1)) { info.latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1); - if (aim_gettlv(tlvlist, 0x0042, 1)) + } + if (aim_gettlv(tlvlist, 0x0042, 1)) { info.latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1); - if (aim_gettlv(tlvlist, 0x0043, 1)) + } + if (aim_gettlv(tlvlist, 0x0043, 1)) { info.latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1); - if (aim_gettlv(tlvlist, 0x0048, 1)) + } + if (aim_gettlv(tlvlist, 0x0048, 1)) { ; /* no idea what this is */ - if (aim_gettlv(tlvlist, 0x0044, 1)) + } + if (aim_gettlv(tlvlist, 0x0044, 1)) { info.latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1); - if (aim_gettlv(tlvlist, 0x0045, 1)) + } + if (aim_gettlv(tlvlist, 0x0045, 1)) { info.latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1); - if (aim_gettlv(tlvlist, 0x0046, 1)) + } + if (aim_gettlv(tlvlist, 0x0046, 1)) { info.latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1); - if (aim_gettlv(tlvlist, 0x0047, 1)) + } + if (aim_gettlv(tlvlist, 0x0047, 1)) { info.latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1); - if (aim_gettlv(tlvlist, 0x0049, 1)) + } + if (aim_gettlv(tlvlist, 0x0049, 1)) { ; /* no idea what this is */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) + } + if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) { ret = userfunc(sess, rx, &info); + } g_free(info.sn); g_free(info.bosip); @@ -505,10 +534,11 @@ static int keyparse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim keylen = aimbs_get16(bs); keystr = aimbs_getstr(bs, keylen); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, keystr); + } - g_free(keystr); + g_free(keystr); return ret; } @@ -516,10 +546,11 @@ static int keyparse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return parse(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0007) + } else if (snac->subtype == 0x0007) { return keyparse(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/bos.c b/protocols/oscar/bos.c index 4a1c5036..8d5fc12a 100644 --- a/protocols/oscar/bos.c +++ b/protocols/oscar/bos.c @@ -15,32 +15,35 @@ static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m guint16 maxpermits = 0, maxdenies = 0; int ret = 0; - /* - * TLVs follow + /* + * TLVs follow */ tlvlist = aim_readtlvchain(bs); /* * TLV type 0x0001: Maximum number of buddies on permit list. */ - if (aim_gettlv(tlvlist, 0x0001, 1)) + if (aim_gettlv(tlvlist, 0x0001, 1)) { maxpermits = aim_gettlv16(tlvlist, 0x0001, 1); + } /* * TLV type 0x0002: Maximum number of buddies on deny list. */ - if (aim_gettlv(tlvlist, 0x0002, 1)) + if (aim_gettlv(tlvlist, 0x0002, 1)) { maxdenies = aim_gettlv16(tlvlist, 0x0002, 1); + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, maxpermits, maxdenies); + } aim_freetlvchain(&tlvlist); - return ret; + return ret; } -/* +/* * Set group permisson mask (group 9, type 4) * * Normally 0x1f (all classes). @@ -58,8 +61,9 @@ int aim_bos_setgroupperm(aim_session_t *sess, aim_conn_t *conn, guint32 mask) static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return rights(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/bos.h b/protocols/oscar/bos.h index e7c2cbcd..a8cabf8b 100644 --- a/protocols/oscar/bos.h +++ b/protocols/oscar/bos.h @@ -5,7 +5,7 @@ /* * SNAC Family: Misc BOS Services. - */ + */ #define AIM_CB_BOS_ERROR 0x0001 #define AIM_CB_BOS_RIGHTSQUERY 0x0002 #define AIM_CB_BOS_RIGHTS 0x0003 diff --git a/protocols/oscar/buddylist.c b/protocols/oscar/buddylist.c index 3335c5ab..8fa7ac01 100644 --- a/protocols/oscar/buddylist.c +++ b/protocols/oscar/buddylist.c @@ -17,8 +17,9 @@ static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_extractuserinfo(sess, bs, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, &userinfo); + } return 0; } @@ -30,16 +31,17 @@ static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m guint16 maxbuddies = 0, maxwatchers = 0; int ret = 0; - /* - * TLVs follow + /* + * TLVs follow */ tlvlist = aim_readtlvchain(bs); /* * TLV type 0x0001: Maximum number of buddies. */ - if (aim_gettlv(tlvlist, 0x0001, 1)) + if (aim_gettlv(tlvlist, 0x0001, 1)) { maxbuddies = aim_gettlv16(tlvlist, 0x0001, 1); + } /* * TLV type 0x0002: Maximum number of watchers. @@ -47,10 +49,11 @@ static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m * Watchers are other users who have you on their buddy * list. (This is called the "reverse list" by a certain * other IM protocol.) - * + * */ - if (aim_gettlv(tlvlist, 0x0002, 1)) + if (aim_gettlv(tlvlist, 0x0002, 1)) { maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1); + } /* * TLV type 0x0003: Unknown. @@ -58,21 +61,23 @@ static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m * ICQ only? */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, maxbuddies, maxwatchers); + } aim_freetlvchain(&tlvlist); - return ret; + return ret; } static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return rights(sess, mod, rx, snac, bs); - else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c)) + } else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c)) { return buddychange(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/buddylist.h b/protocols/oscar/buddylist.h index 55189581..268bc81a 100644 --- a/protocols/oscar/buddylist.h +++ b/protocols/oscar/buddylist.h @@ -5,7 +5,7 @@ /* * SNAC Family: Buddy List Management Services. - */ + */ #define AIM_CB_BUD_ERROR 0x0001 #define AIM_CB_BUD_REQRIGHTS 0x0002 #define AIM_CB_BUD_RIGHTSINFO 0x0003 diff --git a/protocols/oscar/chat.c b/protocols/oscar/chat.c index 6c8d8998..a902ce64 100644 --- a/protocols/oscar/chat.c +++ b/protocols/oscar/chat.c @@ -5,7 +5,7 @@ * */ -#include <aim.h> +#include <aim.h> #include <glib.h> #include "info.h" @@ -18,10 +18,11 @@ struct chatconnpriv { void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn) { - struct chatconnpriv *ccp = (struct chatconnpriv *)conn->priv; + struct chatconnpriv *ccp = (struct chatconnpriv *) conn->priv; - if (ccp) + if (ccp) { g_free(ccp->name); + } g_free(ccp); return; @@ -37,10 +38,10 @@ void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn) * (Note that WinAIM does not honor this, * and displays the message as normal.) * - * XXX convert this to use tlvchains + * XXX convert this to use tlvchains */ int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen) -{ +{ int i; aim_frame_t *fr; aim_msgcookie_t *cookie; @@ -48,38 +49,42 @@ int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const guint8 ckstr[8]; aim_tlvlist_t *otl = NULL, *itl = NULL; - if (!sess || !conn || !msg || (msglen <= 0)) + if (!sess || !conn || !msg || (msglen <= 0)) { return 0; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x000e, 0x0005, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x000e, 0x0005, 0x0000, snacid); - /* + /* * Generate a random message cookie. * * XXX mkcookie should generate the cookie and cache it in one * operation to preserve uniqueness. * */ - for (i = 0; i < sizeof(ckstr); i++) - (void) aimutil_put8(ckstr+i, (guint8) rand()); - + for (i = 0; i < sizeof(ckstr); i++) { + (void) aimutil_put8(ckstr + i, (guint8) rand()); + } + cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL); cookie->data = NULL; /* XXX store something useful here */ aim_cachecookie(sess, cookie); - for (i = 0; i < sizeof(ckstr); i++) + for (i = 0; i < sizeof(ckstr); i++) { aimbs_put8(&fr->data, ckstr[i]); + } /* - * Channel ID. + * Channel ID. */ aimbs_put16(&fr->data, 0x0003); @@ -92,57 +97,59 @@ int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const /* * Type 6: Reflect */ - if (!(flags & AIM_CHATFLAGS_NOREFLECT)) + if (!(flags & AIM_CHATFLAGS_NOREFLECT)) { aim_addtlvtochain_noval(&otl, 0x0006); + } /* * Type 7: Autoresponse */ - if (flags & AIM_CHATFLAGS_AWAY) + if (flags & AIM_CHATFLAGS_AWAY) { aim_addtlvtochain_noval(&otl, 0x0007); - + } + /* [WvG] This wasn't there originally, but we really should send the right charset flags, as we also do with normal messages. Hope this will work. :-) */ /* if (flags & AIM_CHATFLAGS_UNICODE) - aimbs_put16(&fr->data, 0x0002); + aimbs_put16(&fr->data, 0x0002); else if (flags & AIM_CHATFLAGS_ISO_8859_1) - aimbs_put16(&fr->data, 0x0003); + aimbs_put16(&fr->data, 0x0003); else - aimbs_put16(&fr->data, 0x0000); - + aimbs_put16(&fr->data, 0x0000); + aimbs_put16(&fr->data, 0x0000); */ - + /* * SubTLV: Type 1: Message */ - aim_addtlvtochain_raw(&itl, 0x0001, strlen(msg), (guint8 *)msg); + aim_addtlvtochain_raw(&itl, 0x0001, strlen(msg), (guint8 *) msg); /* * Type 5: Message block. Contains more TLVs. * * This could include other information... We just - * put in a message TLV however. - * + * put in a message TLV however. + * */ aim_addtlvtochain_frozentlvlist(&otl, 0x0005, &itl); aim_writetlvchain(&fr->data, &otl); - + aim_freetlvchain(&itl); aim_freetlvchain(&otl); - + aim_tx_enqueue(sess, fr); return 0; } /* - * Join a room of name roomname. This is the first step to joining an - * already created room. It's basically a Service Request for - * family 0x000e, with a little added on to specify the exchange and room + * Join a room of name roomname. This is the first step to joining an + * already created room. It's basically a Service Request for + * family 0x000e, with a little added on to specify the exchange and room * name. */ int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance) @@ -151,12 +158,14 @@ int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; struct chatsnacinfo csi; - - if (!sess || !conn || !roomname || !strlen(roomname)) + + if (!sess || !conn || !roomname || !strlen(roomname)) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) { return -ENOMEM; + } memset(&csi, 0, sizeof(csi)); csi.exchange = exchange; @@ -177,15 +186,16 @@ int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const aim_tx_enqueue(sess, fr); - return 0; + return 0; } int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) { int namelen; - if (!bs || !outinfo) + if (!bs || !outinfo) { return 0; + } outinfo->exchange = aimbs_get16(bs); namelen = aimbs_get8(bs); @@ -198,7 +208,8 @@ int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo) /* * conn must be a BOS connection! */ -int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange, const char *roomname, guint16 instance) +int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange, + const char *roomname, guint16 instance) { int i; aim_frame_t *fr; @@ -210,25 +221,31 @@ int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const guint8 *hdr; int hdrlen; aim_bstream_t hdrbs; - - if (!sess || !conn || !sn || !msg || !roomname) + + if (!sess || !conn || !sn || !msg || !roomname) { return -EINVAL; + } - if (conn->type != AIM_CONN_TYPE_BOS) + if (conn->type != AIM_CONN_TYPE_BOS) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152+strlen(sn)+strlen(roomname)+strlen(msg)))) + if (!(fr = + aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152 + strlen(sn) + strlen(roomname) + + strlen(msg)))) { return -ENOMEM; + } - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn)+1); + snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn) + 1); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* * Cookie */ - for (i = 0; i < sizeof(ckstr); i++) + for (i = 0; i < sizeof(ckstr); i++) { (void) aimutil_put8(ckstr, (guint8) rand()); + } /* XXX should be uncached by an unwritten 'invite accept' handler */ if ((priv = g_malloc(sizeof(struct aim_invite_priv)))) { @@ -238,13 +255,15 @@ int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const priv->instance = instance; } - if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv))) + if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv))) { aim_cachecookie(sess, cookie); - else + } else { g_free(priv); + } - for (i = 0; i < sizeof(ckstr); i++) + for (i = 0; i < sizeof(ckstr); i++) { aimbs_put8(&fr->data, ckstr[i]); + } /* @@ -256,7 +275,7 @@ int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const * Dest sn */ aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); + aimbs_putraw(&fr->data, (guint8 *) sn, strlen(sn)); /* * TLV t(0005) @@ -265,23 +284,23 @@ int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const * * Sigh. AOL was rather inconsistent right here. So we have * to play some minor tricks. Right inside the type 5 is some - * raw data, followed by a series of TLVs. + * raw data, followed by a series of TLVs. * */ - hdrlen = 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2; + hdrlen = 2 + 8 + 16 + 6 + 4 + 4 + strlen(msg) + 4 + 2 + 1 + strlen(roomname) + 2; hdr = g_malloc(hdrlen); aim_bstream_init(&hdrbs, hdr, hdrlen); - + aimbs_put16(&hdrbs, 0x0000); /* Unknown! */ aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */ aim_putcap(&hdrbs, AIM_CAPS_CHAT); aim_addtlvtochain16(&itl, 0x000a, 0x0001); aim_addtlvtochain_noval(&itl, 0x000f); - aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), (guint8 *)msg); + aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), (guint8 *) msg); aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance); aim_writetlvchain(&hdrbs, &itl); - + aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr); aim_writetlvchain(&fr->data, &otl); @@ -289,7 +308,7 @@ int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const g_free(hdr); aim_freetlvchain(&itl); aim_freetlvchain(&otl); - + aim_tx_enqueue(sess, fr); return 0; @@ -333,25 +352,27 @@ static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a /* * Everything else are TLVs. - */ + */ tlvlist = aim_readtlvchain(bs); /* * TLV type 0x006a is the room name in Human Readable Form. */ - if (aim_gettlv(tlvlist, 0x006a, 1)) + if (aim_gettlv(tlvlist, 0x006a, 1)) { roomname = aim_gettlv_str(tlvlist, 0x006a, 1); + } /* * Type 0x006f: Number of occupants. */ - if (aim_gettlv(tlvlist, 0x006f, 1)) + if (aim_gettlv(tlvlist, 0x006f, 1)) { usercount = aim_gettlv16(tlvlist, 0x006f, 1); + } /* * Type 0x0073: Occupant list. */ - if (aim_gettlv(tlvlist, 0x0073, 1)) { + if (aim_gettlv(tlvlist, 0x0073, 1)) { int curoccupant = 0; aim_tlv_t *tmptlv; aim_bstream_t occbs; @@ -363,97 +384,110 @@ static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a aim_bstream_init(&occbs, tmptlv->value, tmptlv->length); - while (curoccupant < usercount) + while (curoccupant < usercount) { aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]); + } } - /* + /* * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG) */ - if (aim_gettlv(tlvlist, 0x00c9, 1)) + if (aim_gettlv(tlvlist, 0x00c9, 1)) { flags = aim_gettlv16(tlvlist, 0x00c9, 1); + } - /* + /* * Type 0x00ca: Creation time (4 bytes) */ - if (aim_gettlv(tlvlist, 0x00ca, 1)) + if (aim_gettlv(tlvlist, 0x00ca, 1)) { creationtime = aim_gettlv32(tlvlist, 0x00ca, 1); + } - /* + /* * Type 0x00d1: Maximum Message Length */ - if (aim_gettlv(tlvlist, 0x00d1, 1)) + if (aim_gettlv(tlvlist, 0x00d1, 1)) { maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1); + } - /* + /* * Type 0x00d2: Unknown. (2 bytes) */ - if (aim_gettlv(tlvlist, 0x00d2, 1)) + if (aim_gettlv(tlvlist, 0x00d2, 1)) { unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1); + } - /* + /* * Type 0x00d3: Room Description */ - if (aim_gettlv(tlvlist, 0x00d3, 1)) + if (aim_gettlv(tlvlist, 0x00d3, 1)) { roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1); + } /* * Type 0x000d4: Unknown (flag only) */ - if (aim_gettlv(tlvlist, 0x000d4, 1)) + if (aim_gettlv(tlvlist, 0x000d4, 1)) { ; + } - /* + /* * Type 0x00d5: Unknown. (1 byte) */ - if (aim_gettlv(tlvlist, 0x00d5, 1)) + if (aim_gettlv(tlvlist, 0x00d5, 1)) { unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1); + } /* * Type 0x00d6: Encoding 1 ("us-ascii") */ - if (aim_gettlv(tlvlist, 0x000d6, 1)) + if (aim_gettlv(tlvlist, 0x000d6, 1)) { ; - + } + /* * Type 0x00d7: Language 1 ("en") */ - if (aim_gettlv(tlvlist, 0x000d7, 1)) + if (aim_gettlv(tlvlist, 0x000d7, 1)) { ; + } /* * Type 0x00d8: Encoding 2 ("us-ascii") */ - if (aim_gettlv(tlvlist, 0x000d8, 1)) + if (aim_gettlv(tlvlist, 0x000d8, 1)) { ; - + } + /* * Type 0x00d9: Language 2 ("en") */ - if (aim_gettlv(tlvlist, 0x000d9, 1)) + if (aim_gettlv(tlvlist, 0x000d9, 1)) { ; + } /* * Type 0x00da: Maximum visible message length */ - if (aim_gettlv(tlvlist, 0x000da, 1)) + if (aim_gettlv(tlvlist, 0x000da, 1)) { maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1); + } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, - rx, - &roominfo, - roomname, - usercount, - userinfo, - roomdesc, - flags, - creationtime, - maxmsglen, - unknown_d2, - unknown_d5, - maxvisiblemsglen); + rx, + &roominfo, + roomname, + usercount, + userinfo, + roomdesc, + flags, + creationtime, + maxmsglen, + unknown_d2, + unknown_d5, + maxvisiblemsglen); } g_free(roominfo.name); @@ -465,7 +499,8 @@ static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a return ret; } -static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs) { aim_userinfo_t *userinfo = NULL; aim_rxcallback_t userfunc; @@ -474,11 +509,12 @@ static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r while (aim_bstream_empty(bs)) { curcount++; userinfo = g_realloc(userinfo, curcount * sizeof(aim_userinfo_t)); - aim_extractuserinfo(sess, bs, &userinfo[curcount-1]); + aim_extractuserinfo(sess, bs, &userinfo[curcount - 1]); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, curcount, userinfo); + } g_free(userinfo); @@ -486,7 +522,7 @@ static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r } /* - * We could probably include this in the normal ICBM parsing + * We could probably include this in the normal ICBM parsing * code as channel 0x0003, however, since only the start * would be the same, we might as well do it here. * @@ -506,12 +542,12 @@ static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r * message tlv * message string * possibly others - * + * */ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { aim_userinfo_t userinfo; - aim_rxcallback_t userfunc; + aim_rxcallback_t userfunc; int ret = 0; guint8 *cookie; guint16 channel; @@ -548,7 +584,7 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, } /* - * Start parsing TLVs right away. + * Start parsing TLVs right away. */ otl = aim_readtlvchain(bs); @@ -566,11 +602,12 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, } /* - * Type 0x0001: If present, it means it was a message to the + * Type 0x0001: If present, it means it was a message to the * room (as opposed to a whisper). */ - if (aim_gettlv(otl, 0x0001, 1)) + if (aim_gettlv(otl, 0x0001, 1)) { ; + } /* * Type 0x0005: Message Block. Conains more TLVs. @@ -584,17 +621,19 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_bstream_init(&tbs, msgblock->value, msgblock->length); itl = aim_readtlvchain(&tbs); - /* + /* * Type 0x0001: Message. - */ - if (aim_gettlv(itl, 0x0001, 1)) + */ + if (aim_gettlv(itl, 0x0001, 1)) { msg = aim_gettlv_str(itl, 0x0001, 1); + } - aim_freetlvchain(&itl); + aim_freetlvchain(&itl); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, &userinfo, msg); + } g_free(cookie); g_free(msg); @@ -606,12 +645,13 @@ static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0002) + if (snac->subtype == 0x0002) { return infoupdate(sess, mod, rx, snac, bs); - else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) + } else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) { return userlistchange(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0006) + } else if (snac->subtype == 0x0006) { return incomingmsg(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/chat.h b/protocols/oscar/chat.h index 6b360326..714f6b74 100644 --- a/protocols/oscar/chat.h +++ b/protocols/oscar/chat.h @@ -5,7 +5,7 @@ /* * SNAC Family: Chat Services - */ + */ #define AIM_CB_CHT_ERROR 0x0001 #define AIM_CB_CHT_ROOMINFOUPDATE 0x0002 #define AIM_CB_CHT_USERJOIN 0x0003 diff --git a/protocols/oscar/chatnav.c b/protocols/oscar/chatnav.c index 1aefd6e7..56d7ef73 100644 --- a/protocols/oscar/chatnav.c +++ b/protocols/oscar/chatnav.c @@ -2,7 +2,7 @@ * Handle ChatNav. * * [The ChatNav(igation) service does various things to keep chat - * alive. It provides room information, room searching and creating, + * alive. It provides room information, room searching and creating, * as well as giving users the right ("permission") to use chat.] * */ @@ -20,15 +20,16 @@ int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn) int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, guint16 exchange) { - static const char ck[] = {"create"}; - static const char lang[] = {"en"}; - static const char charset[] = {"us-ascii"}; + static const char ck[] = { "create" }; + static const char lang[] = { "en" }; + static const char charset[] = { "us-ascii" }; aim_frame_t *fr; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x000d, 0x0008, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x000d, 0x0008, 0x0000, snacid); @@ -39,7 +40,7 @@ int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *na /* * This looks to be a big hack. You'll note that this entire * SNAC is just a room info structure, but the hard room name, - * here, is set to "create". + * here, is set to "create". * * Either this goes on the "list of questions concerning * why-the-hell-did-you-do-that", or this value is completly @@ -48,11 +49,11 @@ int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *na * the value of the room name in create requests is ignored. */ aimbs_put8(&fr->data, strlen(ck)); - aimbs_putraw(&fr->data, (guint8 *)ck, strlen(ck)); + aimbs_putraw(&fr->data, (guint8 *) ck, strlen(ck)); - /* + /* * instance - * + * * Setting this to 0xffff apparently assigns the last instance. * */ @@ -61,9 +62,9 @@ int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *na /* detail level */ aimbs_put8(&fr->data, 0x01); - aim_addtlvtochain_raw(&tl, 0x00d3, strlen(name), (guint8 *)name); - aim_addtlvtochain_raw(&tl, 0x00d6, strlen(charset), (guint8 *)charset); - aim_addtlvtochain_raw(&tl, 0x00d7, strlen(lang), (guint8 *)lang); + aim_addtlvtochain_raw(&tl, 0x00d3, strlen(name), (guint8 *) name); + aim_addtlvtochain_raw(&tl, 0x00d6, strlen(charset), (guint8 *) charset); + aim_addtlvtochain_raw(&tl, 0x00d7, strlen(lang), (guint8 *) lang); /* tlvcount */ aimbs_put16(&fr->data, aim_counttlvchain(&tl)); @@ -76,7 +77,8 @@ int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *na return 0; } -static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs, aim_snac_t *snac2) +static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs, aim_snac_t *snac2) { aim_rxcallback_t userfunc; int ret = 0; @@ -88,20 +90,21 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * tlvlist = aim_readtlvchain(bs); - /* + /* * Type 0x0002: Maximum concurrent rooms. - */ - if (aim_gettlv(tlvlist, 0x0002, 1)) + */ + if (aim_gettlv(tlvlist, 0x0002, 1)) { maxrooms = aim_gettlv8(tlvlist, 0x0002, 1); + } - /* + /* * Type 0x0003: Exchange information * * There can be any number of these, each one - * representing another exchange. - * + * representing another exchange. + * */ - for (curexchange = 0; ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange+1))); ) { + for (curexchange = 0; ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange + 1))); ) { aim_bstream_t tbs; aim_bstream_init(&tbs, exchangetlv->value, exchangetlv->length); @@ -111,35 +114,39 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * exchanges = g_realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo)); /* exchange number */ - exchanges[curexchange-1].number = aimbs_get16(&tbs); + exchanges[curexchange - 1].number = aimbs_get16(&tbs); innerlist = aim_readtlvchain(&tbs); - /* + /* * Type 0x000a: Unknown. * * Usually three bytes: 0x0114 (exchange 1) or 0x010f (others). * */ - if (aim_gettlv(innerlist, 0x000a, 1)) + if (aim_gettlv(innerlist, 0x000a, 1)) { ; + } - /* + /* * Type 0x000d: Unknown. */ - if (aim_gettlv(innerlist, 0x000d, 1)) + if (aim_gettlv(innerlist, 0x000d, 1)) { ; + } - /* + /* * Type 0x0004: Unknown */ - if (aim_gettlv(innerlist, 0x0004, 1)) + if (aim_gettlv(innerlist, 0x0004, 1)) { ; + } - /* + /* * Type 0x0002: Unknown */ - if (aim_gettlv(innerlist, 0x0002, 1)) + if (aim_gettlv(innerlist, 0x0002, 1)) { ; + } /* * Type 0x00c9: Flags @@ -149,47 +156,54 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * * 4 Instancing Allowed * 8 Occupant Peek Allowed * - */ - if (aim_gettlv(innerlist, 0x00c9, 1)) - exchanges[curexchange-1].flags = aim_gettlv16(innerlist, 0x00c9, 1); - + */ + if (aim_gettlv(innerlist, 0x00c9, 1)) { + exchanges[curexchange - 1].flags = aim_gettlv16(innerlist, 0x00c9, 1); + } + /* - * Type 0x00ca: Creation Date + * Type 0x00ca: Creation Date */ - if (aim_gettlv(innerlist, 0x00ca, 1)) + if (aim_gettlv(innerlist, 0x00ca, 1)) { ; - + } + /* * Type 0x00d0: Mandatory Channels? */ - if (aim_gettlv(innerlist, 0x00d0, 1)) + if (aim_gettlv(innerlist, 0x00d0, 1)) { ; + } /* * Type 0x00d1: Maximum Message length */ - if (aim_gettlv(innerlist, 0x00d1, 1)) + if (aim_gettlv(innerlist, 0x00d1, 1)) { ; + } /* * Type 0x00d2: Maximum Occupancy? */ - if (aim_gettlv(innerlist, 0x00d2, 1)) + if (aim_gettlv(innerlist, 0x00d2, 1)) { ; + } /* * Type 0x00d3: Exchange Description */ - if (aim_gettlv(innerlist, 0x00d3, 1)) - exchanges[curexchange-1].name = aim_gettlv_str(innerlist, 0x00d3, 1); - else - exchanges[curexchange-1].name = NULL; + if (aim_gettlv(innerlist, 0x00d3, 1)) { + exchanges[curexchange - 1].name = aim_gettlv_str(innerlist, 0x00d3, 1); + } else { + exchanges[curexchange - 1].name = NULL; + } /* * Type 0x00d4: Exchange Description URL */ - if (aim_gettlv(innerlist, 0x00d4, 1)) + if (aim_gettlv(innerlist, 0x00d4, 1)) { ; + } /* * Type 0x00d5: Creation Permissions @@ -197,7 +211,7 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * * 0 Creation not allowed * 1 Room creation allowed * 2 Exchange creation allowed - * + * */ if (aim_gettlv(innerlist, 0x00d5, 1)) { aim_gettlv8(innerlist, 0x00d5, 1); /* createperms */ @@ -205,41 +219,46 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * /* * Type 0x00d6: Character Set (First Time) - */ - if (aim_gettlv(innerlist, 0x00d6, 1)) - exchanges[curexchange-1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1); - else - exchanges[curexchange-1].charset1 = NULL; - + */ + if (aim_gettlv(innerlist, 0x00d6, 1)) { + exchanges[curexchange - 1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1); + } else { + exchanges[curexchange - 1].charset1 = NULL; + } + /* * Type 0x00d7: Language (First Time) - */ - if (aim_gettlv(innerlist, 0x00d7, 1)) - exchanges[curexchange-1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1); - else - exchanges[curexchange-1].lang1 = NULL; + */ + if (aim_gettlv(innerlist, 0x00d7, 1)) { + exchanges[curexchange - 1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1); + } else { + exchanges[curexchange - 1].lang1 = NULL; + } /* * Type 0x00d8: Character Set (Second Time) - */ - if (aim_gettlv(innerlist, 0x00d8, 1)) - exchanges[curexchange-1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1); - else - exchanges[curexchange-1].charset2 = NULL; + */ + if (aim_gettlv(innerlist, 0x00d8, 1)) { + exchanges[curexchange - 1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1); + } else { + exchanges[curexchange - 1].charset2 = NULL; + } /* * Type 0x00d9: Language (Second Time) - */ - if (aim_gettlv(innerlist, 0x00d9, 1)) - exchanges[curexchange-1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1); - else - exchanges[curexchange-1].lang2 = NULL; - + */ + if (aim_gettlv(innerlist, 0x00d9, 1)) { + exchanges[curexchange - 1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1); + } else { + exchanges[curexchange - 1].lang2 = NULL; + } + /* * Type 0x00da: Unknown */ - if (aim_gettlv(innerlist, 0x00da, 1)) + if (aim_gettlv(innerlist, 0x00da, 1)) { ; + } aim_freetlvchain(&innerlist); } @@ -247,8 +266,9 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * /* * Call client. */ - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, snac2->type, maxrooms, curexchange, exchanges); + } for (curexchange--; curexchange >= 0; curexchange--) { g_free(exchanges[curexchange].name); @@ -263,7 +283,8 @@ static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t * return ret; } -static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs, aim_snac_t *snac2) +static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs, aim_snac_t *snac2) { aim_rxcallback_t userfunc; aim_tlvlist_t *tlvlist, *innerlist; @@ -280,7 +301,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) { imcb_error(sess->aux_data, "no bigblock in top tlv in create room response"); - + aim_freetlvchain(&tlvlist); return 0; } @@ -304,29 +325,37 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t innerlist = aim_readtlvchain(&bbbs); - if (aim_gettlv(innerlist, 0x006a, 1)) + if (aim_gettlv(innerlist, 0x006a, 1)) { fqcn = aim_gettlv_str(innerlist, 0x006a, 1); + } - if (aim_gettlv(innerlist, 0x00c9, 1)) + if (aim_gettlv(innerlist, 0x00c9, 1)) { flags = aim_gettlv16(innerlist, 0x00c9, 1); + } - if (aim_gettlv(innerlist, 0x00ca, 1)) + if (aim_gettlv(innerlist, 0x00ca, 1)) { createtime = aim_gettlv32(innerlist, 0x00ca, 1); + } - if (aim_gettlv(innerlist, 0x00d1, 1)) + if (aim_gettlv(innerlist, 0x00d1, 1)) { maxmsglen = aim_gettlv16(innerlist, 0x00d1, 1); + } - if (aim_gettlv(innerlist, 0x00d2, 1)) + if (aim_gettlv(innerlist, 0x00d2, 1)) { maxoccupancy = aim_gettlv16(innerlist, 0x00d2, 1); + } - if (aim_gettlv(innerlist, 0x00d3, 1)) + if (aim_gettlv(innerlist, 0x00d3, 1)) { name = aim_gettlv_str(innerlist, 0x00d3, 1); + } - if (aim_gettlv(innerlist, 0x00d5, 1)) + if (aim_gettlv(innerlist, 0x00d5, 1)) { createperms = aim_gettlv8(innerlist, 0x00d5, 1); + } if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { - ret = userfunc(sess, rx, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck); + ret = userfunc(sess, rx, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, + maxoccupancy, createperms, unknown, name, ck); } g_free(ck); @@ -339,7 +368,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t } /* - * Since multiple things can trigger this callback, we must lookup the + * Since multiple things can trigger this callback, we must lookup the * snacid to determine the original snac subtype that was called. * * XXX This isn't really how this works. But this is: Every d/9 response @@ -349,7 +378,7 @@ static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t * Instance Info = 4 * Nav Short Desc = 8 * Nav Instance Info = 16 - * And then everything is really asynchronous. There is no specific + * And then everything is really asynchronous. There is no specific * attachment of a response to a create room request, for example. Creating * the room yields no different a response than requesting the room's info. * @@ -372,20 +401,27 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai /* * We now know what the original SNAC subtype was. */ - if (snac2->type == 0x0002) /* request chat rights */ + if (snac2->type == 0x0002) { /* request chat rights */ ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2); - else if (snac2->type == 0x0003) {} /* request exchange info */ - else if (snac2->type == 0x0004) {} /* request room info */ - else if (snac2->type == 0x0005) {} /* request more room info */ - else if (snac2->type == 0x0006) {} /* request occupant list */ - else if (snac2->type == 0x0007) {} /* search for a room */ - else if (snac2->type == 0x0008) /* create room */ + } else if (snac2->type == 0x0003) { + } /* request exchange info */ + else if (snac2->type == 0x0004) { + } /* request room info */ + else if (snac2->type == 0x0005) { + } /* request more room info */ + else if (snac2->type == 0x0006) { + } /* request occupant list */ + else if (snac2->type == 0x0007) { + } /* search for a room */ + else if (snac2->type == 0x0008) { /* create room */ ret = parseinfo_create(sess, mod, rx, snac, bs, snac2); - else + } else { imcb_error(sess->aux_data, "unknown request subtype"); + } - if (snac2) + if (snac2) { g_free(snac2->data); + } g_free(snac2); return ret; @@ -394,8 +430,9 @@ static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0009) + if (snac->subtype == 0x0009) { return parseinfo(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/chatnav.h b/protocols/oscar/chatnav.h index 285decad..a37a6e31 100644 --- a/protocols/oscar/chatnav.h +++ b/protocols/oscar/chatnav.h @@ -5,7 +5,7 @@ /* * SNAC Family: Chat Navigation Services - */ + */ #define AIM_CB_CTN_ERROR 0x0001 #define AIM_CB_CTN_CREATE 0x0008 #define AIM_CB_CTN_INFO 0x0009 diff --git a/protocols/oscar/conn.c b/protocols/oscar/conn.c index 16b6ac07..3cfc38e9 100644 --- a/protocols/oscar/conn.c +++ b/protocols/oscar/conn.c @@ -6,7 +6,7 @@ * */ -#include <aim.h> +#include <aim.h> #include "sock.h" static int aim_logoff(aim_session_t *sess); @@ -14,17 +14,17 @@ static int aim_logoff(aim_session_t *sess); /* * In OSCAR, every connection has a set of SNAC groups associated * with it. These are the groups that you can send over this connection - * without being guarenteed a "Not supported" SNAC error. + * without being guarenteed a "Not supported" SNAC error. * - * The grand theory of things says that these associations transcend + * The grand theory of things says that these associations transcend * what libfaim calls "connection types" (conn->type). You can probably - * see the elegance here, but since I want to revel in it for a bit, you + * see the elegance here, but since I want to revel in it for a bit, you * get to hear it all spelled out. * * So let us say that you have your core BOS connection running. One * of your modules has just given you a SNAC of the group 0x0004 to send * you. Maybe an IM destined for some twit in Greenland. So you start - * at the top of your connection list, looking for a connection that + * at the top of your connection list, looking for a connection that * claims to support group 0x0004. You find one. Why, that neat BOS * connection of yours can do that. So you send it on its way. * @@ -42,8 +42,8 @@ static int aim_logoff(aim_session_t *sess); * it. Great, you say. Now I have something to do. Off you go, making * that connection. One of the first things you get from this new server * is a message saying that indeed it does support the group you were looking - * for. So you continue and send rate confirmation and all that. - * + * for. So you continue and send rate confirmation and all that. + * * Then you remember you had that SNAC to send, and now you have a means to * do it, and you do, and everyone is happy. Except the Greenlander, who is * still stuck in the bitter cold. @@ -56,7 +56,7 @@ static int aim_logoff(aim_session_t *sess); * scheme for quite some time now. But I still haven't convinced myself * to make libfaim work that way. It would take a fair amount of effort, * and probably some client API changes as well. (Whenever I don't want - * to do something, I just say it would change the client API. Then I + * to do something, I just say it would change the client API. Then I * instantly have a couple of supporters of not doing it.) * * Generally, addgroup is only called by the internal handling of the @@ -68,11 +68,12 @@ static int aim_logoff(aim_session_t *sess); */ void aim_conn_addgroup(aim_conn_t *conn, guint16 group) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside; struct snacgroup *sg; - if (!(sg = g_malloc(sizeof(struct snacgroup)))) + if (!(sg = g_malloc(sizeof(struct snacgroup)))) { return; + } sg->group = group; @@ -87,12 +88,13 @@ aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, guint16 group) aim_conn_t *cur; for (cur = sess->connlist; cur; cur = cur->next) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)cur->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *) cur->inside; struct snacgroup *sg; for (sg = ins->groups; sg; sg = sg->next) { - if (sg->group == group) + if (sg->group == group) { return cur; + } } } @@ -149,25 +151,28 @@ static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn) aim_rxqueue_cleanbyconn(sess, *deadconn); aim_tx_cleanqueue(sess, *deadconn); - if ((*deadconn)->fd != -1) + if ((*deadconn)->fd != -1) { aim_conn_close(*deadconn); + } /* * XXX ->priv should never be touched by the library. I know * it used to be, but I'm getting rid of all that. Use * ->internal instead. */ - if ((*deadconn)->priv) + if ((*deadconn)->priv) { g_free((*deadconn)->priv); + } /* * This will free ->internal if it necessary... */ - if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) + if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) { aim_conn_kill_chat(sess, *deadconn); + } if ((*deadconn)->inside) { - aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside; + aim_conn_inside_t *inside = (aim_conn_inside_t *) (*deadconn)->inside; connkill_snacgroups(&inside->groups); connkill_rates(&inside->rates); @@ -217,8 +222,9 @@ static void aim_connrst(aim_session_t *sess) static void aim_conn_init(aim_conn_t *deadconn) { - if (!deadconn) + if (!deadconn) { return; + } deadconn->fd = -1; deadconn->subtype = -1; @@ -244,10 +250,11 @@ static aim_conn_t *aim_conn_getnext(aim_session_t *sess) { aim_conn_t *newconn; - if (!(newconn = g_new0(aim_conn_t,1))) + if (!(newconn = g_new0(aim_conn_t, 1))) { return NULL; + } - if (!(newconn->inside = g_new0(aim_conn_inside_t,1))) { + if (!(newconn->inside = g_new0(aim_conn_inside_t, 1))) { g_free(newconn); return NULL; } @@ -273,8 +280,9 @@ void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn) { aim_conn_t *cur, **prev; - if (!deadconn || !*deadconn) + if (!deadconn || !*deadconn) { return; + } for (prev = &sess->connlist; (cur = *prev); ) { if (cur == *deadconn) { @@ -284,9 +292,10 @@ void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn) prev = &cur->next; } - if (!cur) + if (!cur) { return; /* oops */ + } connkill_real(sess, &cur); return; @@ -298,7 +307,7 @@ void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn) * * Close (but not free) a connection. * - * This leaves everything untouched except for clearing the + * This leaves everything untouched except for clearing the * handler list and setting the fd to -1 (used to recognize * dead connections). It will also remove cookies if necessary. * @@ -306,11 +315,13 @@ void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn) void aim_conn_close(aim_conn_t *deadconn) { - if (deadconn->fd >= 3) + if (deadconn->fd >= 3) { closesocket(deadconn->fd); + } deadconn->fd = -1; - if (deadconn->handlerlist) + if (deadconn->handlerlist) { aim_clearhandlers(deadconn); + } return; } @@ -320,7 +331,7 @@ void aim_conn_close(aim_conn_t *deadconn) * @sess: Session to search * @type: Type of connection to look for * - * Searches for a connection of the specified type in the + * Searches for a connection of the specified type in the * specified session. Returns the first connection of that * type found. * @@ -332,9 +343,10 @@ aim_conn_t *aim_getconn_type(aim_session_t *sess, int type) aim_conn_t *cur; for (cur = sess->connlist; cur; cur = cur->next) { - if ((cur->type == type) && - !(cur->status & AIM_CONN_STATUS_INPROGRESS)) + if ((cur->type == type) && + !(cur->status & AIM_CONN_STATUS_INPROGRESS)) { break; + } } return cur; @@ -345,8 +357,9 @@ aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type) aim_conn_t *cur; for (cur = sess->connlist; cur; cur = cur->next) { - if (cur->type == type) + if (cur->type == type) { break; + } } return cur; @@ -360,7 +373,7 @@ aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type) * * Opens a new connection to the specified dest host of specified * type, using the proxy settings if available. If @host is %NULL, - * the connection is allocated and returned, but no connection + * the connection is allocated and returned, but no connection * is made. * * FIXME: Return errors in a more sane way. @@ -373,10 +386,11 @@ aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest) char *host; int i; - if (!(connstruct = aim_conn_getnext(sess))) + if (!(connstruct = aim_conn_getnext(sess))) { return NULL; + } - connstruct->sessv = (void *)sess; + connstruct->sessv = (void *) sess; connstruct->type = type; if (!dest) { /* just allocate a struct */ @@ -385,23 +399,23 @@ aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest) return connstruct; } - /* - * As of 23 Jul 1999, AOL now sends the port number, preceded by a - * colon, in the BOS redirect. This fatally breaks all previous + /* + * As of 23 Jul 1999, AOL now sends the port number, preceded by a + * colon, in the BOS redirect. This fatally breaks all previous * libfaims. Bad, bad AOL. * - * We put this here to catch every case. + * We put this here to catch every case. * */ - for(i = 0; i < (int)strlen(dest); i++) { + for (i = 0; i < (int) strlen(dest); i++) { if (dest[i] == ':') { - port = atoi(&(dest[i+1])); + port = atoi(&(dest[i + 1])); break; } } - host = (char *)g_malloc(i+1); + host = (char *) g_malloc(i + 1); strncpy(host, dest, i); host[i] = '\0'; @@ -420,7 +434,7 @@ aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest) * Causes @newval seconds to be spent between transmits on a connection. * * This is my lame attempt at overcoming not understanding the rate - * limiting. + * limiting. * * XXX: This should really be replaced with something that scales and * backs off like the real rate limiting does. @@ -429,8 +443,9 @@ aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest) int aim_conn_setlatency(aim_conn_t *conn, int newval) { - if (!conn) + if (!conn) { return -1; + } conn->forcedlatency = newval; conn->lastactivity = 0; /* reset this just to make sure */ @@ -450,8 +465,9 @@ int aim_conn_setlatency(aim_conn_t *conn, int newval) void aim_session_init(aim_session_t *sess, guint32 flags, int debuglevel) { - if (!sess) + if (!sess) { return; + } memset(sess, 0, sizeof(aim_session_t)); aim_connrst(sess); @@ -470,7 +486,7 @@ void aim_session_init(aim_session_t *sess, guint32 flags, int debuglevel) sess->ssi.holding_queue = NULL; sess->ssi.revision = 0; sess->ssi.items = NULL; - sess->ssi.timestamp = (time_t)0; + sess->ssi.timestamp = (time_t) 0; sess->locate.userinfo = NULL; sess->locate.torequest = NULL; @@ -486,13 +502,14 @@ void aim_session_init(aim_session_t *sess, guint32 flags, int debuglevel) /* * Default to SNAC login unless XORLOGIN is explicitly set. */ - if (!(flags & AIM_SESS_FLAGS_XORLOGIN)) + if (!(flags & AIM_SESS_FLAGS_XORLOGIN)) { sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; + } sess->flags |= flags; /* * This must always be set. Default to the queue-based - * version for back-compatibility. + * version for back-compatibility. */ aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL); @@ -547,11 +564,13 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) int res, error = ETIMEDOUT; aim_rxcallback_t userfunc; - if (!conn || (conn->fd == -1)) + if (!conn || (conn->fd == -1)) { return -1; + } - if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) + if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) { return -1; + } FD_ZERO(&fds); FD_SET(conn->fd, &fds); @@ -560,20 +579,21 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) tv.tv_sec = 0; tv.tv_usec = 0; - if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { + if ((res = select(conn->fd + 1, &fds, &wfds, NULL, &tv)) == -1) { error = errno; aim_conn_close(conn); errno = error; return -1; } else if (res == 0) { return 0; /* hasn't really completed yet... */ - } + } if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { socklen_t len = sizeof(error); - if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { error = errno; + } } if (error) { @@ -586,8 +606,9 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) conn->status &= ~AIM_CONN_STATUS_INPROGRESS; - if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) + if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) { userfunc(sess, NULL, conn); + } /* Flush out the queues if there was something waiting for this conn */ aim_tx_flushqueue(sess); @@ -598,10 +619,11 @@ int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) aim_session_t *aim_conn_getsess(aim_conn_t *conn) { - if (!conn) + if (!conn) { return NULL; + } - return (aim_session_t *)conn->sessv; + return (aim_session_t *) conn->sessv; } /* @@ -623,14 +645,15 @@ static int aim_logoff(aim_session_t *sess) * aim_flap_nop() * * No-op. WinAIM 4.x sends these _every minute_ to keep - * the connection alive. + * the connection alive. */ int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn) { aim_frame_t *fr; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0))) { return -ENOMEM; + } aim_tx_enqueue(sess, fr); diff --git a/protocols/oscar/icq.c b/protocols/oscar/icq.c index bd1ba1d1..0f3933f5 100644 --- a/protocols/oscar/icq.c +++ b/protocols/oscar/icq.c @@ -13,13 +13,15 @@ int aim_icq_reqofflinemsgs(aim_session_t *sess) aim_snacid_t snacid; int bslen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) { return -EINVAL; + } bslen = 2 + 4 + 2 + 2; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); @@ -45,13 +47,15 @@ int aim_icq_ackofflinemsgs(aim_session_t *sess) aim_snacid_t snacid; int bslen; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) { return -EINVAL; + } bslen = 2 + 4 + 2 + 2; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); @@ -72,82 +76,89 @@ int aim_icq_ackofflinemsgs(aim_session_t *sess) int aim_icq_getallinfo(aim_session_t *sess, const char *uin) { - aim_conn_t *conn; - aim_frame_t *fr; - aim_snacid_t snacid; - int bslen; - struct aim_icq_info *info; + aim_conn_t *conn; + aim_frame_t *fr; + aim_snacid_t snacid; + int bslen; + struct aim_icq_info *info; - if (!uin || uin[0] < '0' || uin[0] > '9') - return -EINVAL; + if (!uin || uin[0] < '0' || uin[0] > '9') { + return -EINVAL; + } - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) - return -EINVAL; + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) { + return -EINVAL; + } - bslen = 2 + 4 + 2 + 2 + 2 + 4; + bslen = 2 + 4 + 2 + 2 + 2 + 4; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) - return -ENOMEM; + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) { + return -ENOMEM; + } - snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); + snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid); - /* For simplicity, don't bother using a tlvlist */ - aimbs_put16(&fr->data, 0x0001); - aimbs_put16(&fr->data, bslen); + /* For simplicity, don't bother using a tlvlist */ + aimbs_put16(&fr->data, 0x0001); + aimbs_put16(&fr->data, bslen); - aimbs_putle16(&fr->data, bslen - 2); - aimbs_putle32(&fr->data, atoi(sess->sn)); - aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ - aimbs_putle16(&fr->data, snacid); /* eh. */ - aimbs_putle16(&fr->data, 0x04b2); /* shrug. */ - aimbs_putle32(&fr->data, atoi(uin)); + aimbs_putle16(&fr->data, bslen - 2); + aimbs_putle32(&fr->data, atoi(sess->sn)); + aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */ + aimbs_putle16(&fr->data, snacid); /* eh. */ + aimbs_putle16(&fr->data, 0x04b2); /* shrug. */ + aimbs_putle32(&fr->data, atoi(uin)); - aim_tx_enqueue(sess, fr); + aim_tx_enqueue(sess, fr); - /* Keep track of this request and the ICQ number and request ID */ - info = g_new0(struct aim_icq_info, 1); - info->reqid = snacid; - info->uin = atoi(uin); - info->next = sess->icq_info; - sess->icq_info = info; + /* Keep track of this request and the ICQ number and request ID */ + info = g_new0(struct aim_icq_info, 1); + info->reqid = snacid; + info->uin = atoi(uin); + info->next = sess->icq_info; + sess->icq_info = info; - return 0; + return 0; } -static void aim_icq_freeinfo(struct aim_icq_info *info) { - int i; - - if (!info) - return; - g_free(info->nick); - g_free(info->first); - g_free(info->last); - g_free(info->email); - g_free(info->homecity); - g_free(info->homestate); - g_free(info->homephone); - g_free(info->homefax); - g_free(info->homeaddr); - g_free(info->mobile); - g_free(info->homezip); - g_free(info->personalwebpage); - if (info->email2) - for (i = 0; i < info->numaddresses; i++) - g_free(info->email2[i]); - g_free(info->email2); - g_free(info->workcity); - g_free(info->workstate); - g_free(info->workphone); - g_free(info->workfax); - g_free(info->workaddr); - g_free(info->workzip); - g_free(info->workcompany); - g_free(info->workdivision); - g_free(info->workposition); - g_free(info->workwebpage); - g_free(info->info); - g_free(info); +static void aim_icq_freeinfo(struct aim_icq_info *info) +{ + int i; + + if (!info) { + return; + } + g_free(info->nick); + g_free(info->first); + g_free(info->last); + g_free(info->email); + g_free(info->homecity); + g_free(info->homestate); + g_free(info->homephone); + g_free(info->homefax); + g_free(info->homeaddr); + g_free(info->mobile); + g_free(info->homezip); + g_free(info->personalwebpage); + if (info->email2) { + for (i = 0; i < info->numaddresses; i++) { + g_free(info->email2[i]); + } + } + g_free(info->email2); + g_free(info->workcity); + g_free(info->workstate); + g_free(info->workphone); + g_free(info->workfax); + g_free(info->workaddr); + g_free(info->workzip); + g_free(info->workcompany); + g_free(info->workdivision); + g_free(info->workposition); + g_free(info->workwebpage); + g_free(info->info); + g_free(info); } /** @@ -191,16 +202,18 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, msglen = aimbs_getle16(&qbs); msg.msg = aimbs_getstr(&qbs, msglen); - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG))) + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG))) { ret = userfunc(sess, rx, &msg); + } g_free(msg.msg); } else if (cmd == 0x0042) { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE))) + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE))) { ret = userfunc(sess, rx); + } } else if (cmd == 0x07da) { /* information */ guint16 subtype; struct aim_icq_info *info; @@ -210,7 +223,9 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_bstream_advance(&qbs, 1); /* 0x0a */ /* find another data from the same request */ - for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next); + for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next) { + ; + } if (!info) { info = g_new0(struct aim_icq_info, 1); @@ -220,115 +235,121 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, } switch (subtype) { - case 0x00a0: { /* hide ip status */ - /* nothing */ - } break; - case 0x00aa: { /* password change status */ - /* nothing */ - } break; - case 0x00c8: { /* general and "home" information */ - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->homecountry = aimbs_getle16(&qbs); - /* 0x0a 00 02 00 */ - /* 1 byte timezone? */ - /* 1 byte hide email flag? */ - } break; - case 0x00dc: { /* personal information */ - info->age = aimbs_getle8(&qbs); - info->unknown = aimbs_getle8(&qbs); - info->gender = aimbs_getle8(&qbs); - info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->birthyear = aimbs_getle16(&qbs); - info->birthmonth = aimbs_getle8(&qbs); - info->birthday = aimbs_getle8(&qbs); - info->language1 = aimbs_getle8(&qbs); - info->language2 = aimbs_getle8(&qbs); - info->language3 = aimbs_getle8(&qbs); - /* 0x00 00 01 00 00 01 00 00 00 00 00 */ - } break; - case 0x00d2: { /* work information */ - info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workcountry = aimbs_getle16(&qbs); - info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - aim_bstream_advance(&qbs, 2); /* 0x01 00 */ - info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - } break; - case 0x00e6: { /* additional personal information */ - info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs)-1); - } break; - case 0x00eb: { /* email address(es) */ - int i; - info->numaddresses = aimbs_getle16(&qbs); - info->email2 = g_new0(char *, info->numaddresses); - for (i = 0; i < info->numaddresses; i++) { - info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - if (i+1 != info->numaddresses) - aim_bstream_advance(&qbs, 1); /* 0x00 */ - } - } break; - case 0x00f0: { /* personal interests */ - } break; - case 0x00fa: { /* past background and current organizations */ - } break; - case 0x0104: { /* alias info */ - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); - /* email address? */ - /* Then 0x00 02 00 */ - } break; - case 0x010e: { /* unknown */ - /* 0x00 00 */ - } break; - - case 0x019a: { /* simple info */ - aim_bstream_advance(&qbs, 2); - info->uin = aimbs_getle32(&qbs); - info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); - /* Then 0x00 02 00 00 00 00 00 */ - } break; + case 0x00a0: { /* hide ip status */ + /* nothing */ + } break; + case 0x00aa: { /* password change status */ + /* nothing */ + } break; + case 0x00c8: { /* general and "home" information */ + info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->homecountry = aimbs_getle16(&qbs); + /* 0x0a 00 02 00 */ + /* 1 byte timezone? */ + /* 1 byte hide email flag? */ + } break; + case 0x00dc: { /* personal information */ + info->age = aimbs_getle8(&qbs); + info->unknown = aimbs_getle8(&qbs); + info->gender = aimbs_getle8(&qbs); + info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->birthyear = aimbs_getle16(&qbs); + info->birthmonth = aimbs_getle8(&qbs); + info->birthday = aimbs_getle8(&qbs); + info->language1 = aimbs_getle8(&qbs); + info->language2 = aimbs_getle8(&qbs); + info->language3 = aimbs_getle8(&qbs); + /* 0x00 00 01 00 00 01 00 00 00 00 00 */ + } break; + case 0x00d2: { /* work information */ + info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workcountry = aimbs_getle16(&qbs); + info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, 2); /* 0x01 00 */ + info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + } break; + case 0x00e6: { /* additional personal information */ + info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs) - 1); + } break; + case 0x00eb: { /* email address(es) */ + int i; + info->numaddresses = aimbs_getle16(&qbs); + info->email2 = g_new0(char *, info->numaddresses); + for (i = 0; i < info->numaddresses; i++) { + info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + if (i + 1 != info->numaddresses) { + aim_bstream_advance(&qbs, 1); /* 0x00 */ + } + } + } break; + case 0x00f0: { /* personal interests */ + } break; + case 0x00fa: { /* past background and current organizations */ + } break; + case 0x0104: { /* alias info */ + info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + aim_bstream_advance(&qbs, aimbs_getle16(&qbs)); + /* email address? */ + /* Then 0x00 02 00 */ + } break; + case 0x010e: { /* unknown */ + /* 0x00 00 */ + } break; + + case 0x019a: { /* simple info */ + aim_bstream_advance(&qbs, 2); + info->uin = aimbs_getle32(&qbs); + info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs)); + /* Then 0x00 02 00 00 00 00 00 */ + } break; } /* End switch statement */ if (!(snac->flags & 0x0001)) { - if (subtype != 0x0104) - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO))) + if (subtype != 0x0104) { + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO))) { ret = userfunc(sess, rx, info); + } + } - /* Bitlbee - not supported, yet + /* Bitlbee - not supported, yet if (info->uin && info->nick) - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS))) - ret = userfunc(sess, rx, info); + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS))) + ret = userfunc(sess, rx, info); */ if (sess->icq_info == info) { sess->icq_info = info->next; } else { struct aim_icq_info *cur; - for (cur=sess->icq_info; (cur->next && (cur->next!=info)); cur=cur->next); - if (cur->next) + for (cur = sess->icq_info; (cur->next && (cur->next != info)); cur = cur->next) { + ; + } + if (cur->next) { cur->next = cur->next->next; + } } aim_icq_freeinfo(info); } @@ -342,8 +363,9 @@ static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return icqresponse(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/icq.h b/protocols/oscar/icq.h index 41b3efb9..009f5913 100644 --- a/protocols/oscar/icq.h +++ b/protocols/oscar/icq.h @@ -7,7 +7,7 @@ * SNAC Family: ICQ * * Most of these are actually special. - */ + */ #define AIM_CB_ICQ_ERROR 0x0001 #define AIM_CB_ICQ_OFFLINEMSG 0x00f0 #define AIM_CB_ICQ_OFFLINEMSGCOMPLETE 0x00f1 @@ -32,61 +32,61 @@ struct aim_icq_simpleinfo { }; struct aim_icq_info { - gushort reqid; + gushort reqid; - /* simple */ - guint32 uin; + /* simple */ + guint32 uin; - /* general and "home" information (0x00c8) */ - char *nick; - char *first; - char *last; - char *email; - char *homecity; - char *homestate; - char *homephone; - char *homefax; - char *homeaddr; - char *mobile; - char *homezip; - gushort homecountry; + /* general and "home" information (0x00c8) */ + char *nick; + char *first; + char *last; + char *email; + char *homecity; + char *homestate; + char *homephone; + char *homefax; + char *homeaddr; + char *mobile; + char *homezip; + gushort homecountry; /* guchar timezone; guchar hideemail; */ - /* personal (0x00dc) */ - guchar age; - guchar unknown; - guchar gender; - char *personalwebpage; - gushort birthyear; - guchar birthmonth; - guchar birthday; - guchar language1; - guchar language2; - guchar language3; + /* personal (0x00dc) */ + guchar age; + guchar unknown; + guchar gender; + char *personalwebpage; + gushort birthyear; + guchar birthmonth; + guchar birthday; + guchar language1; + guchar language2; + guchar language3; - /* work (0x00d2) */ - char *workcity; - char *workstate; - char *workphone; - char *workfax; - char *workaddr; - char *workzip; - gushort workcountry; - char *workcompany; - char *workdivision; - char *workposition; - char *workwebpage; + /* work (0x00d2) */ + char *workcity; + char *workstate; + char *workphone; + char *workfax; + char *workaddr; + char *workzip; + gushort workcountry; + char *workcompany; + char *workdivision; + char *workposition; + char *workwebpage; - /* additional personal information (0x00e6) */ - char *info; + /* additional personal information (0x00e6) */ + char *info; - /* email (0x00eb) */ - gushort numaddresses; - char **email2; + /* email (0x00eb) */ + gushort numaddresses; + char **email2; - /* we keep track of these in a linked list because we're 1337 */ - struct aim_icq_info *next; + /* we keep track of these in a linked list because we're 1337 */ + struct aim_icq_info *next; }; diff --git a/protocols/oscar/im.c b/protocols/oscar/im.c index 05e06e91..2ddf35ed 100644 --- a/protocols/oscar/im.c +++ b/protocols/oscar/im.c @@ -24,7 +24,7 @@ #include "info.h" /* - * Send an ICBM (instant message). + * Send an ICBM (instant message). * * * Possible flags: @@ -38,12 +38,12 @@ * this, you'd better be damn sure you know * what you're doing. * AIM_IMFLAGS_ISO_8859_1 -- The message contains the ASCII8 subset - * known as ISO-8859-1. + * known as ISO-8859-1. * * Generally, you should use the lowest encoding possible to send * your message. If you only use basic punctuation and the generic * Latin alphabet, use ASCII7 (no flags). If you happen to use non-ASCII7 - * characters, but they are all clearly defined in ISO-8859-1, then + * characters, but they are all clearly defined in ISO-8859-1, then * use that. Keep in mind that not all characters in the PC ASCII8 * character set are defined in the ISO standard. For those cases (most * notably when the (r) symbol is used), you must use the full UNICODE @@ -55,16 +55,16 @@ * I strongly discourage the use of UNICODE mode, mainly because none * of the clients I use can parse those messages (and besides that, * wchars are difficult and non-portable to handle in most UNIX environments). - * If you really need to include special characters, use the HTML UNICODE - * entities. These are of the form ߪ where 2026 is the hex - * representation of the UNICODE index (in this case, UNICODE + * If you really need to include special characters, use the HTML UNICODE + * entities. These are of the form ߪ where 2026 is the hex + * representation of the UNICODE index (in this case, UNICODE * "Horizontal Ellipsis", or 133 in in ASCII8). * * Implementation note: Since this is one of the most-used functions * in all of libfaim, it is written with performance in mind. As such, * it is not as clear as it could be in respect to how this message is - * supposed to be layed out. Most obviously, tlvlists should be used - * instead of writing out the bytes manually. + * supposed to be layed out. Most obviously, tlvlists should be used + * instead of writing out the bytes manually. * * XXX more precise verification that we never send SNACs larger than 8192 * XXX check SNAC size for multipart @@ -80,30 +80,36 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) { return -EINVAL; + } - if (!args) + if (!args) { return -EINVAL; + } if (args->flags & AIM_IMFLAGS_MULTIPART) { - if (args->mpmsg->numparts <= 0) + if (args->mpmsg->numparts <= 0) { return -EINVAL; + } } else { - if (!args->msg || (args->msglen <= 0)) + if (!args->msg || (args->msglen <= 0)) { return -EINVAL; + } - if (args->msglen >= MAXMSGLEN) + if (args->msglen >= MAXMSGLEN) { return -E2BIG; + } } /* Painfully calculate the size of the message TLV */ msgtlvlen = 1 + 1; /* 0501 */ - if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) + if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) { msgtlvlen += 2 + args->featureslen; - else + } else { msgtlvlen += 2 + sizeof(deffeatures); + } if (args->flags & AIM_IMFLAGS_MULTIPART) { aim_mpmsg_section_t *sec; @@ -119,24 +125,26 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen+128))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen + 128))) { return -ENOMEM; + } - /* XXX should be optional */ - snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn)+1); + /* XXX should be optional */ + snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn) + 1); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); - /* - * Generate a random message cookie + /* + * Generate a random message cookie * - * We could cache these like we do SNAC IDs. (In fact, it - * might be a good idea.) In the message error functions, - * the 8byte message cookie is returned as well as the + * We could cache these like we do SNAC IDs. (In fact, it + * might be a good idea.) In the message error functions, + * the 8byte message cookie is returned as well as the * SNAC ID. * */ - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { aimbs_put8(&fr->data, (guint8) rand()); + } /* * Channel ID @@ -147,7 +155,7 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) * Destination SN (prepended with byte length) */ aimbs_put8(&fr->data, strlen(args->destsn)); - aimbs_putraw(&fr->data, (guint8 *)args->destsn, strlen(args->destsn)); + aimbs_putraw(&fr->data, (guint8 *) args->destsn, strlen(args->destsn)); /* * Message TLV (type 2). @@ -156,7 +164,7 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) aimbs_put16(&fr->data, msgtlvlen); /* - * Features + * Features * */ aimbs_put8(&fr->data, 0x05); @@ -185,7 +193,7 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) aimbs_put16(&fr->data, 0x0101); - /* + /* * Message block length. */ aimbs_put16(&fr->data, args->msglen + 0x04); @@ -199,12 +207,13 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) aimbs_put16(&fr->data, args->charsubset); } else { - if (args->flags & AIM_IMFLAGS_UNICODE) + if (args->flags & AIM_IMFLAGS_UNICODE) { aimbs_put16(&fr->data, 0x0002); - else if (args->flags & AIM_IMFLAGS_ISO_8859_1) + } else if (args->flags & AIM_IMFLAGS_ISO_8859_1) { aimbs_put16(&fr->data, 0x0003); - else + } else { aimbs_put16(&fr->data, 0x0000); + } aimbs_put16(&fr->data, 0x0000); } @@ -212,11 +221,11 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) /* * Message. Not terminated. */ - aimbs_putraw(&fr->data, (guint8 *)args->msg, args->msglen); + aimbs_putraw(&fr->data, (guint8 *) args->msg, args->msglen); } /* - * Set the Request Acknowledge flag. + * Set the Request Acknowledge flag. */ if (args->flags & AIM_IMFLAGS_ACK) { aimbs_put16(&fr->data, 0x0003); @@ -258,14 +267,15 @@ int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args) aim_tx_enqueue(sess, fr); - if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM)) + if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM)) { aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */ + } return 0; } /* - * Simple wrapper for aim_send_im_ext() + * Simple wrapper for aim_send_im_ext() * * You cannot use aim_send_im if you need the HASICON flag. You must * use aim_send_im_ext directly for that. @@ -299,64 +309,66 @@ int aim_send_im(aim_session_t *sess, const char *destsn, guint16 flags, const ch * @return 0 if no error */ int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie, - const char *message, const guint8 state, const guint16 dc) + const char *message, const guint8 state, const guint16 dc) { - aim_conn_t *conn; - aim_frame_t *fr; - aim_snacid_t snacid; - - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, - 10+8+2+1+strlen(sender)+2+0x1d+0x10+9+strlen(message)+1))) - return -ENOMEM; - - snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0); - aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid); - - aimbs_putraw(&fr->data, cookie, 8); - - aimbs_put16(&fr->data, 0x0002); /* channel */ - aimbs_put8(&fr->data, strlen(sender)); - aimbs_putraw(&fr->data, (guint8 *)sender, strlen(sender)); - - aimbs_put16(&fr->data, 0x0003); /* reason: channel specific */ - - aimbs_putle16(&fr->data, 0x001b); /* length of data SEQ1 */ - aimbs_putle16(&fr->data, 0x0008); /* protocol version */ - - aimbs_putle32(&fr->data, 0x0000); /* no plugin -> 16 times 0x00 */ - aimbs_putle32(&fr->data, 0x0000); - aimbs_putle32(&fr->data, 0x0000); - aimbs_putle32(&fr->data, 0x0000); - - aimbs_putle16(&fr->data, 0x0000); /* unknown */ - aimbs_putle32(&fr->data, 0x0003); /* client features */ - aimbs_putle8(&fr->data, 0x00); /* unknown */ - aimbs_putle16(&fr->data, dc); /* Sequence number? XXX - This should decrement by 1 with each request */ - /* end of SEQ1 */ - - aimbs_putle16(&fr->data, 0x000e); /* Length of SEQ2 */ - aimbs_putle16(&fr->data, dc); /* Sequence number? same as above - * XXX - This should decrement by 1 with each request */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ - /* end of SEQ2 */ - - /* now for the real fun */ - aimbs_putle8(&fr->data, state); /* away state */ - aimbs_putle8(&fr->data, 0x03); /* msg-flag: 03 for states */ - aimbs_putle16(&fr->data, 0x0000); /* status code ? */ - aimbs_putle16(&fr->data, 0x0000); /* priority code */ - aimbs_putle16(&fr->data, strlen(message) + 1); /* message length + termination */ - aimbs_putraw(&fr->data, (guint8 *) message, strlen(message) + 1); /* null terminated string */ - - aim_tx_enqueue(sess, fr); - - - return 0; + aim_conn_t *conn; + aim_frame_t *fr; + aim_snacid_t snacid; + + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) { + return -EINVAL; + } + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, + 10 + 8 + 2 + 1 + strlen(sender) + 2 + 0x1d + 0x10 + 9 + strlen(message) + 1))) { + return -ENOMEM; + } + + snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0); + aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid); + + aimbs_putraw(&fr->data, cookie, 8); + + aimbs_put16(&fr->data, 0x0002); /* channel */ + aimbs_put8(&fr->data, strlen(sender)); + aimbs_putraw(&fr->data, (guint8 *) sender, strlen(sender)); + + aimbs_put16(&fr->data, 0x0003); /* reason: channel specific */ + + aimbs_putle16(&fr->data, 0x001b); /* length of data SEQ1 */ + aimbs_putle16(&fr->data, 0x0008); /* protocol version */ + + aimbs_putle32(&fr->data, 0x0000); /* no plugin -> 16 times 0x00 */ + aimbs_putle32(&fr->data, 0x0000); + aimbs_putle32(&fr->data, 0x0000); + aimbs_putle32(&fr->data, 0x0000); + + aimbs_putle16(&fr->data, 0x0000); /* unknown */ + aimbs_putle32(&fr->data, 0x0003); /* client features */ + aimbs_putle8(&fr->data, 0x00); /* unknown */ + aimbs_putle16(&fr->data, dc); /* Sequence number? XXX - This should decrement by 1 with each request */ + /* end of SEQ1 */ + + aimbs_putle16(&fr->data, 0x000e); /* Length of SEQ2 */ + aimbs_putle16(&fr->data, dc); /* Sequence number? same as above + * XXX - This should decrement by 1 with each request */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + aimbs_putle32(&fr->data, 0x00000000); /* Unknown */ + /* end of SEQ2 */ + + /* now for the real fun */ + aimbs_putle8(&fr->data, state); /* away state */ + aimbs_putle8(&fr->data, 0x03); /* msg-flag: 03 for states */ + aimbs_putle16(&fr->data, 0x0000); /* status code ? */ + aimbs_putle16(&fr->data, 0x0000); /* priority code */ + aimbs_putle16(&fr->data, strlen(message) + 1); /* message length + termination */ + aimbs_putraw(&fr->data, (guint8 *) message, strlen(message) + 1); /* null terminated string */ + + aim_tx_enqueue(sess, fr); + + + return 0; } @@ -374,8 +386,9 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a aim_tlv_t *msgblock; /* ICBM Cookie. */ - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { aimbs_get8(bs); + } /* Channel ID */ channel = aimbs_get16(bs); @@ -390,10 +403,12 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a tlvlist = aim_readtlvchain(bs); - if (aim_gettlv(tlvlist, 0x0003, 1)) + if (aim_gettlv(tlvlist, 0x0003, 1)) { icbmflags |= AIM_IMFLAGS_ACK; - if (aim_gettlv(tlvlist, 0x0004, 1)) + } + if (aim_gettlv(tlvlist, 0x0004, 1)) { icbmflags |= AIM_IMFLAGS_AWAY; + } if ((msgblock = aim_gettlv(tlvlist, 0x0002, 1))) { aim_bstream_t mbs; @@ -403,8 +418,9 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a aimbs_get8(&mbs); aimbs_get8(&mbs); - for (featurelen = aimbs_get16(&mbs); featurelen; featurelen--) + for (featurelen = aimbs_get16(&mbs); featurelen; featurelen--) { aimbs_get8(&mbs); + } aimbs_get8(&mbs); aimbs_get8(&mbs); @@ -416,8 +432,9 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a msg = aimbs_getstr(&mbs, msglen); } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2); + } g_free(sn); aim_freetlvchain(&tlvlist); @@ -429,13 +446,13 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a * Ahh, the joys of nearly ridiculous over-engineering. * * Not only do AIM ICBM's support multiple channels. Not only do they - * support multiple character sets. But they support multiple character + * support multiple character sets. But they support multiple character * sets / encodings within the same ICBM. * * These multipart messages allow for complex space savings techniques, which * seem utterly unnecessary by today's standards. In fact, there is only * one client still in popular use that still uses this method: AOL for the - * Macintosh, Version 5.0. Obscure, yes, I know. + * Macintosh, Version 5.0. Obscure, yes, I know. * * In modern (non-"legacy") clients, if the user tries to send a character * that is not ISO-8859-1 or ASCII, the client will send the entire message @@ -443,7 +460,7 @@ static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a * full 16 bit UNICODE field, even if the high order byte would be zero. * Multipart messages prevent this wasted space by allowing the client to * only send the characters in UNICODE that need to be sent that way, and - * the rest of the message can be sent in whatever the native character + * the rest of the message can be sent in whatever the native character * set is (probably ASCII). * * An important note is that sections will be displayed in the order that @@ -470,12 +487,14 @@ int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm) return 0; } -static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, guint8 *data, guint16 datalen) +static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, guint8 *data, + guint16 datalen) { - aim_mpmsg_section_t *sec; - - if (!(sec = g_new0(aim_mpmsg_section_t,1))) + aim_mpmsg_section_t *sec; + + if (!(sec = g_new0(aim_mpmsg_section_t, 1))) { return -1; + } sec->charset = charset; sec->charsubset = charsubset; @@ -483,13 +502,14 @@ static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 chars sec->datalen = datalen; sec->next = NULL; - if (!mpm->parts) + if (!mpm->parts) { mpm->parts = sec; - else { + } else { aim_mpmsg_section_t *cur; - for (cur = mpm->parts; cur->next; cur = cur->next) + for (cur = mpm->parts; cur->next; cur = cur->next) { ; + } cur->next = sec; } @@ -504,13 +524,13 @@ void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm) for (cur = mpm->parts; cur; ) { aim_mpmsg_section_t *tmp; - + tmp = cur->next; g_free(cur->data); g_free(cur); cur = tmp; } - + mpm->numparts = 0; mpm->parts = NULL; @@ -518,7 +538,7 @@ void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm) } /* - * Start by building the multipart structures, then pick the first + * Start by building the multipart structures, then pick the first * human-readable section and stuff it into args->msg so no one gets * suspicious. * @@ -568,7 +588,7 @@ static int incomingim_ch1_parsemsgs(aim_session_t *sess, guint8 *data, int len, * */ msgbuf = aimbs_getstr(&mbs, msglen); - mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, (guint8 *)msgbuf, (guint16) msglen); + mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, (guint8 *) msgbuf, (guint16) msglen); } /* while */ @@ -589,8 +609,9 @@ static int incomingim_ch1_parsemsgs(aim_session_t *sess, guint8 *data, int len, for (i = 0; i < charsetpricount; i++) { for (sec = args->mpmsg.parts; sec; sec = sec->next) { - if (sec->charset != charsetpri[i]) + if (sec->charset != charsetpri[i]) { continue; + } /* Great. We found one. Fill it in. */ args->charset = sec->charset; @@ -598,35 +619,38 @@ static int incomingim_ch1_parsemsgs(aim_session_t *sess, guint8 *data, int len, args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET; /* Set up the simple flags */ - if (args->charset == 0x0000) + if (args->charset == 0x0000) { ; /* ASCII */ - else if (args->charset == 0x0002) + } else if (args->charset == 0x0002) { args->icbmflags |= AIM_IMFLAGS_UNICODE; - else if (args->charset == 0x0003) + } else if (args->charset == 0x0003) { args->icbmflags |= AIM_IMFLAGS_ISO_8859_1; - else if (args->charset == 0xffff) + } else if (args->charset == 0xffff) { ; /* no encoding (yeep!) */ - if (args->charsubset == 0x0000) + } + if (args->charsubset == 0x0000) { ; /* standard subencoding? */ - else if (args->charsubset == 0x000b) + } else if (args->charsubset == 0x000b) { args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH; - else if (args->charsubset == 0xffff) + } else if (args->charsubset == 0xffff) { ; /* no subencoding */ + } #if 0 - /* XXX this isn't really necesary... */ - if ( ((args.flag1 != 0x0000) && - (args.flag1 != 0x0002) && - (args.flag1 != 0x0003) && - (args.flag1 != 0xffff)) || - ((args.flag2 != 0x0000) && - (args.flag2 != 0x000b) && - (args.flag2 != 0xffff))) { - faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", args.flag1, args.flag2); + /* XXX this isn't really necesary... */ + if (((args.flag1 != 0x0000) && + (args.flag1 != 0x0002) && + (args.flag1 != 0x0003) && + (args.flag1 != 0xffff)) || + ((args.flag2 != 0x0000) && + (args.flag2 != 0x000b) && + (args.flag2 != 0xffff))) { + faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n", + args.flag1, args.flag2); } #endif - args->msg = (char *)sec->data; + args->msg = (char *) sec->data; args->msglen = sec->datalen; return 0; @@ -641,7 +665,8 @@ static int incomingim_ch1_parsemsgs(aim_session_t *sess, guint8 *data, int len, return 0; } -static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_bstream_t *bs, guint8 *cookie) +static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, + aim_userinfo_t *userinfo, aim_bstream_t *bs, guint8 *cookie) { guint16 type, length; aim_rxcallback_t userfunc; @@ -689,7 +714,8 @@ static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r * The rest of the TLV contains one or more message * blocks... */ - incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */, length - 2 - 2 - args.featureslen, &args); + incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */, + length - 2 - 2 - args.featureslen, &args); } else if (type == 0x0003) { /* Server Ack Requested */ @@ -719,10 +745,11 @@ static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r * * You really shouldn't advertise a zero-length icon * anyway. - * + * */ - if (args.iconlen) + if (args.iconlen) { args.icbmflags |= AIM_IMFLAGS_HASICON; + } } else if (type == 0x0009) { @@ -749,8 +776,9 @@ static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, channel, userinfo, &args); + } aim_mpmsg_free(sess, &args.mpmsg); g_free(args.extdata); @@ -768,16 +796,18 @@ static void incomingim_ch2_chat_free(aim_session_t *sess, struct aim_incomingim_ return; } -static void incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata) +static void incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata) { /* * Chat room info. */ - if (servdata) + if (servdata) { aim_chat_readroominfo(servdata, &args->info.chat.roominfo); + } - args->destructor = (void *)incomingim_ch2_chat_free; + args->destructor = (void *) incomingim_ch2_chat_free; return; } @@ -785,13 +815,13 @@ static void incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_fram static void incomingim_ch2_icqserverrelay_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args) { - g_free((char *)args->info.rtfmsg.rtfmsg); + g_free((char *) args->info.rtfmsg.rtfmsg); return; } /* - * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is + * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is * kind of odd. This sends the client ICQRTF since that is all that I've seen * SERVERRELAY used for. * @@ -800,79 +830,84 @@ static void incomingim_ch2_icqserverrelay_free(aim_session_t *sess, struct aim_i * This cap is used for auto status message replies, too [ft] * */ -static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata) +static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, + aim_bstream_t *servdata) { guint16 hdrlen, msglen, dc; guint8 msgtype; - guint8 *plugin; - int i = 0, tmp = 0; - struct im_connection *ic = sess->aux_data; + guint8 *plugin; + int i = 0, tmp = 0; + struct im_connection *ic = sess->aux_data; - /* at the moment we just can deal with requests, not with cancel or accept */ - if (args->status != 0) return; + /* at the moment we just can deal with requests, not with cancel or accept */ + if (args->status != 0) { + return; + } hdrlen = aimbs_getle16(servdata); - aim_bstream_advance(servdata, 0x02); /* protocol version */ - plugin = aimbs_getraw(servdata, 0x10); /* following data is a message or - something plugin specific */ - /* as there is no plugin handling, just skip the rest */ - aim_bstream_advance(servdata, hdrlen - 0x12); + aim_bstream_advance(servdata, 0x02); /* protocol version */ + plugin = aimbs_getraw(servdata, 0x10); /* following data is a message or + something plugin specific */ + /* as there is no plugin handling, just skip the rest */ + aim_bstream_advance(servdata, hdrlen - 0x12); hdrlen = aimbs_getle16(servdata); - dc = aimbs_getle16(servdata); /* save the sequence number */ + dc = aimbs_getle16(servdata); /* save the sequence number */ aim_bstream_advance(servdata, hdrlen - 0x02); - /* TODO is it a message or something for a plugin? */ - for (i = 0; i < 0x10; i++) { - tmp |= plugin[i]; - } + /* TODO is it a message or something for a plugin? */ + for (i = 0; i < 0x10; i++) { + tmp |= plugin[i]; + } - if (!tmp) { /* message follows */ + if (!tmp) { /* message follows */ - msgtype = aimbs_getle8(servdata); - aimbs_getle8(servdata); /* msgflags */ + msgtype = aimbs_getle8(servdata); + aimbs_getle8(servdata); /* msgflags */ - aim_bstream_advance(servdata, 0x04); /* status code and priority code */ + aim_bstream_advance(servdata, 0x04); /* status code and priority code */ - msglen = aimbs_getle16(servdata); /* message string length */ - args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen); + msglen = aimbs_getle16(servdata); /* message string length */ + args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen); - switch(msgtype) { - case AIM_MTYPE_PLAIN: + switch (msgtype) { + case AIM_MTYPE_PLAIN: - args->info.rtfmsg.fgcolor = aimbs_getle32(servdata); - args->info.rtfmsg.bgcolor = aimbs_getle32(servdata); + args->info.rtfmsg.fgcolor = aimbs_getle32(servdata); + args->info.rtfmsg.bgcolor = aimbs_getle32(servdata); - hdrlen = aimbs_getle32(servdata); - aim_bstream_advance(servdata, hdrlen); + hdrlen = aimbs_getle32(servdata); + aim_bstream_advance(servdata, hdrlen); - /* XXX This is such a hack. */ - args->reqclass = AIM_CAPS_ICQRTF; - break; + /* XXX This is such a hack. */ + args->reqclass = AIM_CAPS_ICQRTF; + break; - case AIM_MTYPE_AUTOAWAY: - case AIM_MTYPE_AUTOBUSY: - case AIM_MTYPE_AUTONA: - case AIM_MTYPE_AUTODND: - case AIM_MTYPE_AUTOFFC: - case 0x9c: /* ICQ 5 seems to send this */ - aim_send_im_ch2_statusmessage(sess, userinfo->sn, args->cookie, - ic->away ? ic->away : "", sess->aim_icq_state, dc); - break; + case AIM_MTYPE_AUTOAWAY: + case AIM_MTYPE_AUTOBUSY: + case AIM_MTYPE_AUTONA: + case AIM_MTYPE_AUTODND: + case AIM_MTYPE_AUTOFFC: + case 0x9c: /* ICQ 5 seems to send this */ + aim_send_im_ch2_statusmessage(sess, userinfo->sn, args->cookie, + ic->away ? ic->away : "", sess->aim_icq_state, dc); + break; - } - } /* message or plugin specific */ + } + } /* message or plugin specific */ - g_free(plugin); - args->destructor = (void *)incomingim_ch2_icqserverrelay_free; + g_free(plugin); + args->destructor = (void *) incomingim_ch2_icqserverrelay_free; return; } typedef void (*ch2_args_destructor_t)(aim_session_t *sess, struct aim_incomingim_ch2_args *args); -static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) +static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, + aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) { aim_rxcallback_t userfunc; aim_tlv_t *block1, *servdatatlv; @@ -882,14 +917,14 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r guint8 *cookie2; int ret = 0; - char clientip1[30] = {""}; - char clientip2[30] = {""}; - char verifiedip[30] = {""}; + char clientip1[30] = { "" }; + char clientip2[30] = { "" }; + char verifiedip[30] = { "" }; memset(&args, 0, sizeof(args)); /* - * There's another block of TLVs embedded in the type 5 here. + * There's another block of TLVs embedded in the type 5 here. */ block1 = aim_gettlv(tlvlist, 0x0005, 1); aim_bstream_init(&bbs, block1->value, block1->length); @@ -898,15 +933,16 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r * First two bytes represent the status of the connection. * * 0 is a request, 1 is a deny (?), 2 is an accept - */ + */ args.status = aimbs_get16(&bbs); /* * Next comes the cookie. Should match the ICBM cookie. */ cookie2 = aimbs_getraw(&bbs, 8); - if (memcmp(cookie, cookie2, 8) != 0) + if (memcmp(cookie, cookie2, 8) != 0) { imcb_error(sess->aux_data, "rend: warning cookies don't match!"); + } memcpy(args.cookie, cookie2, 8); g_free(cookie2); @@ -916,7 +952,7 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r */ args.reqclass = aim_getcap(sess, &bbs, 0x10); - /* + /* * What follows may be TLVs or nothing, depending on the * purpose of the message. * @@ -933,10 +969,10 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r iptlv = aim_gettlv(list2, 0x0002, 1); g_snprintf(clientip1, sizeof(clientip1), "%d.%d.%d.%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3)); + aimutil_get8(iptlv->value + 0), + aimutil_get8(iptlv->value + 1), + aimutil_get8(iptlv->value + 2), + aimutil_get8(iptlv->value + 3)); } /* @@ -948,10 +984,10 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r iptlv = aim_gettlv(list2, 0x0003, 1); g_snprintf(clientip2, sizeof(clientip2), "%d.%d.%d.%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3)); + aimutil_get8(iptlv->value + 0), + aimutil_get8(iptlv->value + 1), + aimutil_get8(iptlv->value + 2), + aimutil_get8(iptlv->value + 3)); } /* @@ -965,56 +1001,66 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r iptlv = aim_gettlv(list2, 0x0004, 1); g_snprintf(verifiedip, sizeof(verifiedip), "%d.%d.%d.%d", - aimutil_get8(iptlv->value+0), - aimutil_get8(iptlv->value+1), - aimutil_get8(iptlv->value+2), - aimutil_get8(iptlv->value+3)); + aimutil_get8(iptlv->value + 0), + aimutil_get8(iptlv->value + 1), + aimutil_get8(iptlv->value + 2), + aimutil_get8(iptlv->value + 3)); } /* * Port number for something. */ - if (aim_gettlv(list2, 0x0005, 1)) + if (aim_gettlv(list2, 0x0005, 1)) { args.port = aim_gettlv16(list2, 0x0005, 1); + } /* * Error code. */ - if (aim_gettlv(list2, 0x000b, 1)) + if (aim_gettlv(list2, 0x000b, 1)) { args.errorcode = aim_gettlv16(list2, 0x000b, 1); + } /* * Invitation message / chat description. */ - if (aim_gettlv(list2, 0x000c, 1)) + if (aim_gettlv(list2, 0x000c, 1)) { args.msg = aim_gettlv_str(list2, 0x000c, 1); + } /* * Character set. */ - if (aim_gettlv(list2, 0x000d, 1)) + if (aim_gettlv(list2, 0x000d, 1)) { args.encoding = aim_gettlv_str(list2, 0x000d, 1); - + } + /* * Language. */ - if (aim_gettlv(list2, 0x000e, 1)) + if (aim_gettlv(list2, 0x000e, 1)) { args.language = aim_gettlv_str(list2, 0x000e, 1); + } /* Unknown -- two bytes = 0x0001 */ - if (aim_gettlv(list2, 0x000a, 1)) + if (aim_gettlv(list2, 0x000a, 1)) { ; + } /* Unknown -- no value */ - if (aim_gettlv(list2, 0x000f, 1)) + if (aim_gettlv(list2, 0x000f, 1)) { ; + } - if (strlen(clientip1)) - args.clientip = (char *)clientip1; - if (strlen(clientip2)) - args.clientip2 = (char *)clientip2; - if (strlen(verifiedip)) - args.verifiedip = (char *)verifiedip; + if (strlen(clientip1)) { + args.clientip = (char *) clientip1; + } + if (strlen(clientip2)) { + args.clientip2 = (char *) clientip2; + } + if (strlen(verifiedip)) { + args.verifiedip = (char *) verifiedip; + } /* * This is must be present in PROPOSALs, but will probably not @@ -1028,29 +1074,33 @@ static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r sdbsptr = &sdbs; } - if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) + if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) { incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr); - else if (args.reqclass & AIM_CAPS_CHAT) + } else if (args.reqclass & AIM_CAPS_CHAT) { incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, sdbsptr); + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, channel, userinfo, &args); + } - if (args.destructor) - ((ch2_args_destructor_t)args.destructor)(sess, &args); + if (args.destructor) { + ((ch2_args_destructor_t) args.destructor)(sess, &args); + } - g_free((char *)args.msg); - g_free((char *)args.encoding); - g_free((char *)args.language); + g_free((char *) args.msg); + g_free((char *) args.encoding); + g_free((char *) args.language); aim_freetlvchain(&list2); return ret; } -static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) +static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, + aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie) { aim_bstream_t meat; aim_rxcallback_t userfunc; @@ -1061,16 +1111,18 @@ static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r /* * Make a bstream for the meaty part. Yum. Meat. */ - if (!(block = aim_gettlv(tlvlist, 0x0005, 1))) + if (!(block = aim_gettlv(tlvlist, 0x0005, 1))) { return -1; + } aim_bstream_init(&meat, block->value, block->length); args.uin = aimbs_getle32(&meat); args.type = aimbs_getle16(&meat); - args.msg = (char *)aimbs_getraw(&meat, aimbs_getle16(&meat)); + args.msg = (char *) aimbs_getraw(&meat, aimbs_getle16(&meat)); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, channel, userinfo, &args); + } g_free(args.msg); @@ -1100,22 +1152,23 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a /* * Read ICBM Cookie. And throw away. */ - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { cookie[i] = aimbs_get8(bs); + } /* * Channel ID. * - * Channel 0x0001 is the message channel. There are + * Channel 0x0001 is the message channel. There are * other channels for things called "rendevous" * which represent chat and some of the other new - * features of AIM2/3/3.5. + * features of AIM2/3/3.5. * * Channel 0x0002 is the Rendevous channel, which * is where Chat Invitiations and various client-client * connection negotiations come from. * - * Channel 0x0004 is used for ICQ authorization, or + * Channel 0x0004 is used for ICQ authorization, or * possibly any system notice. * */ @@ -1130,12 +1183,12 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a * information, the rest are not even though there is no seperation. * aim_extractuserinfo() returns the number of bytes used by the * userinfo tlvs, so you can start reading the rest of them right - * afterward. + * afterward. * * That also means that TLV types can be duplicated between the * userinfo block and the rest of the message, however there should * never be two TLVs of the same type in one block. - * + * */ aim_extractuserinfo(sess, bs, &userinfo); @@ -1154,7 +1207,7 @@ static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a aim_tlvlist_t *tlvlist; /* - * Read block of TLVs (not including the userinfo data). All + * Read block of TLVs (not including the userinfo data). All * further data is derived from what is parsed here. */ tlvlist = aim_readtlvchain(bs); @@ -1190,8 +1243,9 @@ int aim_reqicbmparams(aim_session_t *sess) { aim_conn_t *conn; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) { return -EINVAL; + } return aim_genericreq_n(sess, conn, 0x0004, 0x0004); } @@ -1200,7 +1254,7 @@ int aim_reqicbmparams(aim_session_t *sess) * * I definitly recommend sending this. If you don't, you'll be stuck * with the rather unreasonable defaults. You don't want those. Send this. - * + * */ int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) { @@ -1208,14 +1262,17 @@ int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) { return -EINVAL; + } - if (!params) + if (!params) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+16))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 16))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid); @@ -1224,10 +1281,10 @@ int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params) aimbs_put16(&fr->data, 0x0000); /* These are all read-write */ - aimbs_put32(&fr->data, params->flags); + aimbs_put32(&fr->data, params->flags); aimbs_put16(&fr->data, params->maxmsglen); - aimbs_put16(&fr->data, params->maxsenderwarn); - aimbs_put16(&fr->data, params->maxrecverwarn); + aimbs_put16(&fr->data, params->maxsenderwarn); + aimbs_put16(&fr->data, params->maxrecverwarn); aimbs_put32(&fr->data, params->minmsginterval); aim_tx_enqueue(sess, fr); @@ -1246,9 +1303,10 @@ static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai params.maxsenderwarn = aimbs_get16(bs); params.maxrecverwarn = aimbs_get16(bs); params.minmsginterval = aimbs_get32(bs); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, ¶ms); + } return 0; } @@ -1260,25 +1318,27 @@ static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a guint16 channel, nummissed, reason; aim_userinfo_t userinfo; - while (aim_bstream_empty(bs)) { + while (aim_bstream_empty(bs)) { channel = aimbs_get16(bs); aim_extractuserinfo(sess, bs, &userinfo); nummissed = aimbs_get16(bs); reason = aimbs_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason); + } } return ret; } /* - * Receive the response from an ICQ status message request. This contains the + * Receive the response from an ICQ status message request. This contains the * ICQ status message. Go figure. */ -static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs) { int ret = 0; aim_rxcallback_t userfunc; @@ -1293,56 +1353,58 @@ static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r reason = aimbs_get16(bs); switch (reason) { - case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ - guint8 statusmsgtype, *msg; - guint16 len; - guint32 state; - - len = aimbs_getle16(bs); /* Should be 0x001b */ - aim_bstream_advance(bs, len); /* Unknown */ - - len = aimbs_getle16(bs); /* Should be 0x000e */ - aim_bstream_advance(bs, len); /* Unknown */ - - statusmsgtype = aimbs_getle8(bs); - switch (statusmsgtype) { - case 0xe8: - state = AIM_ICQ_STATE_AWAY; - break; - case 0xe9: - state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; - break; - case 0xea: - state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; - break; - case 0xeb: - state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; - break; - case 0xec: - state = AIM_ICQ_STATE_CHAT; - break; - default: - state = 0; - break; - } + case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */ + guint8 statusmsgtype, *msg; + guint16 len; + guint32 state; + + len = aimbs_getle16(bs); /* Should be 0x001b */ + aim_bstream_advance(bs, len); /* Unknown */ + + len = aimbs_getle16(bs); /* Should be 0x000e */ + aim_bstream_advance(bs, len); /* Unknown */ + + statusmsgtype = aimbs_getle8(bs); + switch (statusmsgtype) { + case 0xe8: + state = AIM_ICQ_STATE_AWAY; + break; + case 0xe9: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY; + break; + case 0xea: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT; + break; + case 0xeb: + state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY; + break; + case 0xec: + state = AIM_ICQ_STATE_CHAT; + break; + default: + state = 0; + break; + } - aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ - aimbs_getle16(bs); /* Unknown - 0x0000 */ - aimbs_getle16(bs); /* Unknown - 0x0000 */ + aimbs_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */ + aimbs_getle16(bs); /* Unknown - 0x0000 */ + aimbs_getle16(bs); /* Unknown - 0x0000 */ - len = aimbs_getle16(bs); - msg = aimbs_getraw(bs, len); + len = aimbs_getle16(bs); + msg = aimbs_getraw(bs, len); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason, state, msg); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + ret = userfunc(sess, rx, channel, sn, reason, state, msg); + } - g_free(msg); - } break; + g_free(msg); + } break; - default: { - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - ret = userfunc(sess, rx, channel, sn, reason); - } break; + default: { + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + ret = userfunc(sess, rx, channel, sn, reason); + } + } break; } /* end switch */ g_free(ck); @@ -1364,8 +1426,9 @@ static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m snlen = aimbs_get8(bs); sn = aimbs_getstr(bs, snlen); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, type, sn); + } g_free(sn); g_free(ck); @@ -1376,7 +1439,7 @@ static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m /* * Subtype 0x0014 - Send a mini typing notification (mtn) packet. * - * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, + * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, * and Gaim 0.60 and newer. * */ @@ -1386,14 +1449,17 @@ int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 t aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) { return -EINVAL; + } - if (!sn) + if (!sn) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+11+strlen(sn)+2))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11 + strlen(sn) + 2))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid); @@ -1416,7 +1482,7 @@ int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 t * Dest sn */ aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (const guint8*)sn, strlen(sn)); + aimbs_putraw(&fr->data, (const guint8 *) sn, strlen(sn)); /* * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn) @@ -1431,7 +1497,7 @@ int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 t /* * Subtype 0x0014 - Receive a mini typing notification (mtn) packet. * - * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, + * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer, * and Gaim 0.60 and newer. * */ @@ -1449,8 +1515,9 @@ static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, sn = aimbs_getstr(bs, snlen); type2 = aimbs_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, type1, sn, type2); + } g_free(sn); @@ -1460,20 +1527,21 @@ static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0005) + if (snac->subtype == 0x0005) { return paraminfo(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0006) + } else if (snac->subtype == 0x0006) { return outgoingim(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0007) + } else if (snac->subtype == 0x0007) { return incomingim(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000a) + } else if (snac->subtype == 0x000a) { return missedcall(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000b) + } else if (snac->subtype == 0x000b) { return clientautoresp(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000c) + } else if (snac->subtype == 0x000c) { return msgack(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0014) + } else if (snac->subtype == 0x0014) { return mtn_receive(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/im.h b/protocols/oscar/im.h index 34d5e238..54c68acd 100644 --- a/protocols/oscar/im.h +++ b/protocols/oscar/im.h @@ -5,7 +5,7 @@ /* * SNAC Family: Messaging Services. - */ + */ #define AIM_CB_MSG_ERROR 0x0001 #define AIM_CB_MSG_PARAMINFO 0x0005 #define AIM_CB_MSG_INCOMING 0x0007 @@ -16,18 +16,18 @@ #define AIM_CB_MSG_MTN 0x0014 #define AIM_CB_MSG_DEFAULT 0xffff -#define AIM_IMFLAGS_AWAY 0x0001 /* mark as an autoreply */ -#define AIM_IMFLAGS_ACK 0x0002 /* request a receipt notice */ -#define AIM_IMFLAGS_UNICODE 0x0004 -#define AIM_IMFLAGS_ISO_8859_1 0x0008 -#define AIM_IMFLAGS_BUDDYREQ 0x0010 /* buddy icon requested */ -#define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */ -#define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */ -#define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */ -#define AIM_IMFLAGS_EXTDATA 0x0100 -#define AIM_IMFLAGS_CUSTOMCHARSET 0x0200 /* charset fields set */ -#define AIM_IMFLAGS_MULTIPART 0x0400 /* ->mpmsg section valid */ -#define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */ +#define AIM_IMFLAGS_AWAY 0x0001 /* mark as an autoreply */ +#define AIM_IMFLAGS_ACK 0x0002 /* request a receipt notice */ +#define AIM_IMFLAGS_UNICODE 0x0004 +#define AIM_IMFLAGS_ISO_8859_1 0x0008 +#define AIM_IMFLAGS_BUDDYREQ 0x0010 /* buddy icon requested */ +#define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */ +#define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */ +#define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */ +#define AIM_IMFLAGS_EXTDATA 0x0100 +#define AIM_IMFLAGS_CUSTOMCHARSET 0x0200 /* charset fields set */ +#define AIM_IMFLAGS_MULTIPART 0x0400 /* ->mpmsg section valid */ +#define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */ /* * Multipart message structures. @@ -83,7 +83,7 @@ struct aim_sendimext_args { /* * This information is provided in the Incoming ICBM callback for - * Channel 1 ICBM's. + * Channel 1 ICBM's. * * Note that although CUSTOMFEATURES and CUSTOMCHARSET say they * are optional, both are always set by the current libfaim code. @@ -99,7 +99,7 @@ struct aim_incomingim_ch1_args { /* Always provided */ aim_mpmsg_t mpmsg; guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */ - + /* Only provided if message has a human-readable section */ char *msg; int msglen; @@ -178,6 +178,7 @@ aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn); aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const guint8 *cookie); int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2); -int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie, const char *message, const guint8 state, const guint16 dc); +int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie, const char *message, + const guint8 state, const guint16 dc); #endif /* __OSCAR_IM_H__ */ diff --git a/protocols/oscar/info.c b/protocols/oscar/info.c index a5a65147..6a929fc0 100644 --- a/protocols/oscar/info.c +++ b/protocols/oscar/info.c @@ -2,7 +2,7 @@ * aim_info.c * * The functions here are responsible for requesting and parsing information- - * gathering SNACs. Or something like that. + * gathering SNACs. Or something like that. * */ @@ -10,7 +10,7 @@ #include "info.h" struct aim_priv_inforeq { - char sn[MAXSNLEN+1]; + char sn[MAXSNLEN + 1]; guint16 infotype; }; @@ -20,20 +20,22 @@ int aim_getinfo(aim_session_t *sess, aim_conn_t *conn, const char *sn, guint16 i aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !conn || !sn) + if (!sess || !conn || !sn) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12+1+strlen(sn)))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12 + 1 + strlen(sn)))) { return -ENOMEM; + } strncpy(privdata.sn, sn, sizeof(privdata.sn)); privdata.infotype = infotype; snacid = aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq)); - + aim_putsnac(&fr->data, 0x0002, 0x0005, 0x0000, snacid); aimbs_put16(&fr->data, infotype); aimbs_put8(&fr->data, strlen(sn)); - aimbs_putraw(&fr->data, (guint8 *)sn, strlen(sn)); + aimbs_putraw(&fr->data, (guint8 *) sn, strlen(sn)); aim_tx_enqueue(sess, fr); @@ -41,7 +43,7 @@ int aim_getinfo(aim_session_t *sess, aim_conn_t *conn, const char *sn, guint16 i } /* - * Capability blocks. + * Capability blocks. * * These are CLSIDs. They should actually be of the form: * @@ -58,111 +60,111 @@ static const struct { /* * Chat is oddball. */ - {AIM_CAPS_CHAT, - {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + { AIM_CAPS_CHAT, + { 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, /* * These are mostly in order. */ - {AIM_CAPS_VOICE, - {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + { AIM_CAPS_VOICE, + { 0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, - {AIM_CAPS_SENDFILE, - {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + { AIM_CAPS_SENDFILE, + { 0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, /* * Advertised by the EveryBuddy client. */ - {AIM_CAPS_ICQ, - {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_IMIMAGE, - {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_BUDDYICON, - {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_SAVESTOCKS, - {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_GETFILE, - {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - /* - * Client supports channel 2 extended, TLV(0x2711) based messages. - * Currently used only by ICQ clients. ICQ clients and clones use this GUID - * as message format sign. Trillian client use another GUID in channel 2 - * messages to implement its own message format (trillian doesn't use - * TLV(x2711) in SecureIM channel 2 messages!). - */ - {AIM_CAPS_ICQSERVERRELAY, - {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, + { AIM_CAPS_ICQ, + { 0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_IMIMAGE, + { 0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_BUDDYICON, + { 0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_SAVESTOCKS, + { 0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_GETFILE, + { 0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + /* + * Client supports channel 2 extended, TLV(0x2711) based messages. + * Currently used only by ICQ clients. ICQ clients and clones use this GUID + * as message format sign. Trillian client use another GUID in channel 2 + * messages to implement its own message format (trillian doesn't use + * TLV(x2711) in SecureIM channel 2 messages!). + */ + { AIM_CAPS_ICQSERVERRELAY, + { 0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, /* - * Indeed, there are two of these. The former appears to be correct, - * but in some versions of winaim, the second one is set. Either they - * forgot to fix endianness, or they made a typo. It really doesn't + * Indeed, there are two of these. The former appears to be correct, + * but in some versions of winaim, the second one is set. Either they + * forgot to fix endianness, or they made a typo. It really doesn't * matter which. */ - {AIM_CAPS_GAMES, - {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - {AIM_CAPS_GAMES2, - {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, - 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_SENDBUDDYLIST, - {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_UTF8, - {0x09, 0x46, 0x13, 0x4E, 0x4C, 0x7F, 0x11, 0xD1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_ICQRTF, - {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, - 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}}, - - {AIM_CAPS_ICQUNKNOWN, - {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, - 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}}, - - {AIM_CAPS_EMPTY, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - - {AIM_CAPS_TRILLIANCRYPT, - {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, - 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}}, - - {AIM_CAPS_APINFO, - {0xAA, 0x4A, 0x32, 0xB5, 0xF8, 0x84, 0x48, 0xc6, - 0xA3, 0xD7, 0x8C, 0x50, 0x97, 0x19, 0xFD, 0x5B}}, - - {AIM_CAPS_INTEROP, - {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_ICHAT, - {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, - 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}, - - {AIM_CAPS_LAST} + { AIM_CAPS_GAMES, + { 0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + { AIM_CAPS_GAMES2, + { 0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1, + 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_SENDBUDDYLIST, + { 0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_UTF8, + { 0x09, 0x46, 0x13, 0x4E, 0x4C, 0x7F, 0x11, 0xD1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_ICQRTF, + { 0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34, + 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92 } }, + + { AIM_CAPS_ICQUNKNOWN, + { 0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8, + 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf } }, + + { AIM_CAPS_EMPTY, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + + { AIM_CAPS_TRILLIANCRYPT, + { 0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb, + 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00 } }, + + { AIM_CAPS_APINFO, + { 0xAA, 0x4A, 0x32, 0xB5, 0xF8, 0x84, 0x48, 0xc6, + 0xA3, 0xD7, 0x8C, 0x50, 0x97, 0x19, 0xFD, 0x5B } }, + + { AIM_CAPS_INTEROP, + { 0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_ICHAT, + { 0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1, + 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } }, + + { AIM_CAPS_LAST } }; /* * This still takes a length parameter even with a bstream because capabilities * are not naturally bounded. - * + * */ guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len) { @@ -189,12 +191,12 @@ guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len) /*FIXME*/ /*REMOVEME :-) g_strdup_printf("unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", - cap[0], cap[1], cap[2], cap[3], - cap[4], cap[5], - cap[6], cap[7], - cap[8], cap[9], - cap[10], cap[11], cap[12], cap[13], - cap[14], cap[15]); + cap[0], cap[1], cap[2], cap[3], + cap[4], cap[5], + cap[6], cap[7], + cap[8], cap[9], + cap[10], cap[11], cap[12], cap[13], + cap[14], cap[15]); */ } @@ -208,16 +210,19 @@ int aim_putcap(aim_bstream_t *bs, guint32 caps) { int i; - if (!bs) + if (!bs) { return -EINVAL; + } for (i = 0; aim_bstream_empty(bs); i++) { - if (aim_caps[i].flag == AIM_CAPS_LAST) + if (aim_caps[i].flag == AIM_CAPS_LAST) { break; + } - if (caps & aim_caps[i].flag) + if (caps & aim_caps[i].flag) { aimbs_putraw(bs, aim_caps[i].data, 0x10); + } } @@ -225,7 +230,7 @@ int aim_putcap(aim_bstream_t *bs, guint32 caps) } /* - * AIM is fairly regular about providing user info. This is a generic + * AIM is fairly regular about providing user info. This is a generic * routine to extract it in its standard form. */ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo) @@ -233,18 +238,19 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * int curtlv, tlvcnt; guint8 snlen; - if (!bs || !outinfo) + if (!bs || !outinfo) { return -EINVAL; + } /* Clear out old data first */ memset(outinfo, 0x00, sizeof(aim_userinfo_t)); /* - * Screen name. Stored as an unterminated string prepended with a + * Screen name. Stored as an unterminated string prepended with a * byte containing its length. */ snlen = aimbs_get8(bs); - aimbs_getrawbuf(bs, (guint8 *)outinfo->sn, snlen); + aimbs_getrawbuf(bs, (guint8 *) outinfo->sn, snlen); /* * Warning Level. Stored as an unsigned short. @@ -252,12 +258,12 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * outinfo->warnlevel = aimbs_get16(bs); /* - * TLV Count. Unsigned short representing the number of + * TLV Count. Unsigned short representing the number of * Type-Length-Value triples that follow. */ tlvcnt = aimbs_get16(bs); - /* + /* * Parse out the Type-Length-Value triples as they're found. */ for (curtlv = 0; curtlv < tlvcnt; curtlv++) { @@ -272,13 +278,13 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * if (type == 0x0001) { /* * Type = 0x0001: User flags - * + * * Specified as any of the following ORed together: * 0x0001 Trial (user less than 60days) * 0x0002 Unknown bit 2 * 0x0004 AOL Main Service user * 0x0008 Unknown bit 4 - * 0x0010 Free (AIM) user + * 0x0010 Free (AIM) user * 0x0020 Away * 0x0400 ActiveBuddy * @@ -288,7 +294,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * } else if (type == 0x0002) { /* - * Type = 0x0002: Member-Since date. + * Type = 0x0002: Member-Since date. * * The time/date that the user originally registered for * the service, stored in time_t format. @@ -300,7 +306,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * /* * Type = 0x0003: On-Since date. * - * The time/date that the user started their current + * The time/date that the user started their current * session, stored in time_t format. */ outinfo->onlinesince = aimbs_get32(bs); @@ -310,11 +316,11 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * /* * Type = 0x0004: Idle time. * - * Number of seconds since the user actively used the + * Number of seconds since the user actively used the * service. * * Note that the client tells the server when to start - * counting idle times, so this may or may not be + * counting idle times, so this may or may not be * related to reality. */ outinfo->idletime = aimbs_get16(bs); @@ -324,7 +330,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * /* * Type = 0x0006: ICQ Online Status * - * ICQ's Away/DND/etc "enriched" status. Some decoding + * ICQ's Away/DND/etc "enriched" status. Some decoding * of values done by Scott <darkagl@pcnet.com> */ aimbs_get16(bs); @@ -342,7 +348,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR; } else if (type == 0x000c) { - /* + /* * Type = 0x000c * * random crap containing the IP address, @@ -378,7 +384,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * * Type = 0x000f: Session Length. (AIM) * Type = 0x0010: Session Length. (AOL) * - * The duration, in seconds, of the user's current + * The duration, in seconds, of the user's current * session. * * Which TLV type this comes in depends on the @@ -392,7 +398,7 @@ int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t * /* * Reaching here indicates that either AOL has - * added yet another TLV for us to deal with, + * added yet another TLV for us to deal with, * or the parsing has gone Terribly Wrong. * * Either way, inform the owner and attempt @@ -428,11 +434,13 @@ static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_m tlvlist = aim_readtlvchain(bs); - if (aim_gettlv(tlvlist, 0x0001, 1)) + if (aim_gettlv(tlvlist, 0x0001, 1)) { maxsiglen = aim_gettlv16(tlvlist, 0x0001, 1); + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, maxsiglen); + } aim_freetlvchain(&tlvlist); @@ -458,11 +466,11 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim return 0; } - inforeq = (struct aim_priv_inforeq *)origsnac->data; + inforeq = (struct aim_priv_inforeq *) origsnac->data; if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) && - (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) && - (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) { + (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) && + (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) { imcb_error(sess->aux_data, "unknown infotype in request!"); return 0; } @@ -471,7 +479,7 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim tlvlist = aim_readtlvchain(bs); - /* + /* * Depending on what informational text was requested, different * TLVs will appear here. * @@ -480,14 +488,14 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim */ if (inforeq->infotype == AIM_GETINFO_GENERALINFO) { text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1); - if((tlv = aim_gettlv(tlvlist, 0x0002, 1))) { + if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) { text = g_new0(char, tlv->length); memcpy(text, tlv->value, tlv->length); text_length = tlv->length; } } else if (inforeq->infotype == AIM_GETINFO_AWAYMESSAGE) { text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1); - if((tlv = aim_gettlv(tlvlist, 0x0004, 1))) { + if ((tlv = aim_gettlv(tlvlist, 0x0004, 1))) { text = g_new0(char, tlv->length); memcpy(text, tlv->value, tlv->length); text_length = tlv->length; @@ -505,16 +513,18 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim } } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, &userinfo, inforeq->infotype, text_encoding, text, text_length); + } g_free(text_encoding); g_free(text); aim_freetlvchain(&tlvlist); - if (origsnac) + if (origsnac) { g_free(origsnac->data); + } g_free(origsnac); return ret; @@ -523,10 +533,11 @@ static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return rights(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0006) + } else if (snac->subtype == 0x0006) { return userinfo(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/info.h b/protocols/oscar/info.h index 5651f187..4ccd1fb7 100644 --- a/protocols/oscar/info.h +++ b/protocols/oscar/info.h @@ -5,7 +5,7 @@ /* * SNAC Family: Location Services. - */ + */ #define AIM_CB_LOC_ERROR 0x0001 #define AIM_CB_LOC_REQRIGHTS 0x0002 #define AIM_CB_LOC_RIGHTSINFO 0x0003 @@ -28,8 +28,8 @@ #define AIM_CAPS_GAMES2 0x00000200 #define AIM_CAPS_ICQ 0x00000400 #define AIM_CAPS_APINFO 0x00000800 -#define AIM_CAPS_ICQRTF 0x00001000 -#define AIM_CAPS_EMPTY 0x00002000 +#define AIM_CAPS_ICQRTF 0x00001000 +#define AIM_CAPS_EMPTY 0x00002000 #define AIM_CAPS_ICQSERVERRELAY 0x00004000 #define AIM_CAPS_ICQUNKNOWN 0x00008000 #define AIM_CAPS_TRILLIANCRYPT 0x00010000 diff --git a/protocols/oscar/misc.c b/protocols/oscar/misc.c index 950cd852..6d55e7fc 100644 --- a/protocols/oscar/misc.c +++ b/protocols/oscar/misc.c @@ -6,30 +6,30 @@ * * Other things... * - * - Idle setting - * + * - Idle setting + * * */ -#include <aim.h> +#include <aim.h> -/* +/* * aim_bos_setprofile(profile) * * Gives BOS your profile. - * + * */ int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps) { - static const char defencoding[] = {"text/aolrtf; charset=\"utf-8\""}; + static const char defencoding[] = { "text/aolrtf; charset=\"utf-8\"" }; aim_frame_t *fr; aim_tlvlist_t *tl = NULL; aim_snacid_t snacid; /* Build to packet first to get real length */ if (profile) { - aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), (guint8 *)defencoding); - aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), (guint8 *)profile); + aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), (guint8 *) defencoding); + aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), (guint8 *) profile); } /* @@ -42,19 +42,21 @@ int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profil */ if (awaymsg) { if (strlen(awaymsg)) { - aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), (guint8 *)defencoding); - aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), (guint8 *)awaymsg); - } else + aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), (guint8 *) defencoding); + aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), (guint8 *) awaymsg); + } else { aim_addtlvtochain_noval(&tl, 0x0004); + } } aim_addtlvtochain_caps(&tl, 0x0005, caps); - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl)))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl)))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0); - + aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid); aim_writetlvchain(&fr->data, &tl); aim_freetlvchain(&tl); @@ -92,8 +94,9 @@ int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, guint16 family, guin aim_frame_t *fr; aim_snacid_t snacid = 0x00000000; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) { return -ENOMEM; + } aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); @@ -107,8 +110,9 @@ int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, guint16 famil aim_frame_t *fr; aim_snacid_t snacid; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); aim_putsnac(&fr->data, family, subtype, 0x0000, snacid); @@ -123,11 +127,13 @@ int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, guint16 family, guin aim_frame_t *fr; aim_snacid_t snacid; - if (!longdata) + if (!longdata) { return aim_genericreq_n(sess, conn, family, subtype); + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4))) - return -ENOMEM; + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4))) { + return -ENOMEM; + } snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); @@ -144,11 +150,13 @@ int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, guint16 family, guin aim_frame_t *fr; aim_snacid_t snacid; - if (!shortdata) + if (!shortdata) { return aim_genericreq_n(sess, conn, family, subtype); + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2))) - return -ENOMEM; + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2))) { + return -ENOMEM; + } snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0); @@ -184,14 +192,17 @@ static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim snac2 = aim_remsnac(sess, snac->id); - if (aim_bstream_empty(bs)) + if (aim_bstream_empty(bs)) { error = aimbs_get16(bs); + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL); + } - if (snac2) + if (snac2) { g_free(snac2->data); + } g_free(snac2); return ret; @@ -200,13 +211,14 @@ static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0001) + if (snac->subtype == 0x0001) { return generror(sess, mod, rx, snac, bs); - else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) { + } else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx); + } } return 0; diff --git a/protocols/oscar/msgcookie.c b/protocols/oscar/msgcookie.c index efeb8cbf..1fcdd7c2 100644 --- a/protocols/oscar/msgcookie.c +++ b/protocols/oscar/msgcookie.c @@ -1,7 +1,7 @@ /* * Cookie Caching stuff. Adam wrote this, apparently just some * derivatives of n's SNAC work. I cleaned it up, added comments. - * + * */ /* @@ -25,24 +25,26 @@ * * returns -1 on error, 0 on append, 1 on update. the cookie you pass * in may be free'd, so don't count on its value after calling this! - * + * */ int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie) { aim_msgcookie_t *newcook; - if (!sess || !cookie) + if (!sess || !cookie) { return -EINVAL; + } newcook = aim_checkcookie(sess, cookie->cookie, cookie->type); - + if (newcook == cookie) { newcook->addtime = time(NULL); return 1; - } else if (newcook) + } else if (newcook) { aim_cookie_free(sess, newcook); + } - cookie->addtime = time(NULL); + cookie->addtime = time(NULL); cookie->next = sess->msgcookies; sess->msgcookies = cookie; @@ -64,12 +66,13 @@ aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, guint8 *cookie, int type { aim_msgcookie_t *cur, **prev; - if (!cookie || !sess->msgcookies) + if (!cookie || !sess->msgcookies) { return NULL; + } for (prev = &sess->msgcookies; (cur = *prev); ) { - if ((cur->type == type) && - (memcmp(cur->cookie, cookie, 8) == 0)) { + if ((cur->type == type) && + (memcmp(cur->cookie, cookie, 8) == 0)) { *prev = cur->next; return cur; } @@ -89,15 +92,17 @@ aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, guint8 *cookie, int type * success. * */ -aim_msgcookie_t *aim_mkcookie(guint8 *c, int type, void *data) +aim_msgcookie_t *aim_mkcookie(guint8 *c, int type, void *data) { aim_msgcookie_t *cookie; - if (!c) + if (!c) { return NULL; + } - if (!(cookie = g_new0(aim_msgcookie_t,1))) + if (!(cookie = g_new0(aim_msgcookie_t, 1))) { return NULL; + } cookie->data = data; cookie->type = type; @@ -122,9 +127,10 @@ aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const guint8 *cookie, int aim_msgcookie_t *cur; for (cur = sess->msgcookies; cur; cur = cur->next) { - if ((cur->type == type) && - (memcmp(cur->cookie, cookie, 8) == 0)) - return cur; + if ((cur->type == type) && + (memcmp(cur->cookie, cookie, 8) == 0)) { + return cur; + } } return NULL; @@ -143,22 +149,24 @@ aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const guint8 *cookie, int * returns -1 on error, 0 on success. * */ -int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie) +int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie) { aim_msgcookie_t *cur, **prev; - if (!sess || !cookie) + if (!sess || !cookie) { return -EINVAL; + } for (prev = &sess->msgcookies; (cur = *prev); ) { - if (cur == cookie) + if (cur == cookie) { *prev = cur->next; - else + } else { prev = &cur->next; + } } g_free(cookie->data); g_free(cookie); return 0; -} +} diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 1c74e7a2..22244f6c 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -49,25 +49,25 @@ #define USEROPT_AUTH 0 #define USEROPT_AUTHPORT 1 -#define UC_AOL 0x02 -#define UC_ADMIN 0x04 -#define UC_UNCONFIRMED 0x08 -#define UC_NORMAL 0x10 -#define UC_AB 0x20 -#define UC_WIRELESS 0x40 +#define UC_AOL 0x02 +#define UC_ADMIN 0x04 +#define UC_UNCONFIRMED 0x08 +#define UC_NORMAL 0x10 +#define UC_AB 0x20 +#define UC_WIRELESS 0x40 #define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3" #define OSCAR_GROUP "Friends" #define BUF_LEN 2048 -#define BUF_LONG ( BUF_LEN * 2 ) +#define BUF_LONG (BUF_LEN * 2) /* Don't know if support for UTF8 is really working. For now it's UTF16 here. static int gaim_caps = AIM_CAPS_UTF8; */ static int gaim_caps = AIM_CAPS_INTEROP | AIM_CAPS_ICHAT | AIM_CAPS_ICQSERVERRELAY | AIM_CAPS_CHAT; -static guint8 gaim_features[] = {0x01, 0x01, 0x01, 0x02}; +static guint8 gaim_features[] = { 0x01, 0x01, 0x01, 0x02 }; struct oscar_data { aim_session_t *sess; @@ -93,7 +93,7 @@ struct oscar_data { gboolean killme, no_reconnect; gboolean icq; GSList *evilhack; - + GHashTable *ips; struct { @@ -138,13 +138,19 @@ struct icq_auth { guint32 uin; }; -static char *extract_name(const char *name) { +static char *extract_name(const char *name) +{ char *tmp; int i, j; char *x = strchr(name, '-'); - if (!x) return g_strdup(name); + + if (!x) { + return g_strdup(name); + } x = strchr(++x, '-'); - if (!x) return g_strdup(name); + if (!x) { + return g_strdup(name); + } tmp = g_strdup(++x); for (i = 0, j = 0; x[i]; i++) { @@ -155,7 +161,7 @@ static char *extract_name(const char *name) { } strncpy(hex, x + ++i, 2); hex[2] = 0; i++; - tmp[j++] = (char)strtol(hex, NULL, 16); + tmp[j++] = (char) strtol(hex, NULL, 16); } tmp[j] = 0; @@ -163,14 +169,16 @@ static char *extract_name(const char *name) { } static struct chat_connection *find_oscar_chat_by_conn(struct im_connection *ic, - aim_conn_t *conn) { - GSList *g = ((struct oscar_data *)ic->proto_data)->oscar_chats; + aim_conn_t *conn) +{ + GSList *g = ((struct oscar_data *) ic->proto_data)->oscar_chats; struct chat_connection *c = NULL; while (g) { - c = (struct chat_connection *)g->data; - if (c->conn == conn) + c = (struct chat_connection *) g->data; + if (c->conn == conn) { break; + } g = g->next; c = NULL; } @@ -178,41 +186,41 @@ static struct chat_connection *find_oscar_chat_by_conn(struct im_connection *ic, return c; } -static int gaim_parse_auth_resp (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_login (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_logout (aim_session_t *, aim_frame_t *, ...); -static int gaim_handle_redirect (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_oncoming (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_offgoing (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_auth_resp(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_login(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_logout(aim_session_t *, aim_frame_t *, ...); +static int gaim_handle_redirect(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_oncoming(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_offgoing(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_misses (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_motd (aim_session_t *, aim_frame_t *, ...); -static int gaim_chatnav_info (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_join (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_leave (aim_session_t *, aim_frame_t *, ...); -static int gaim_chat_info_update (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_misses(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_motd(aim_session_t *, aim_frame_t *, ...); +static int gaim_chatnav_info(aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_join(aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_leave(aim_session_t *, aim_frame_t *, ...); +static int gaim_chat_info_update(aim_session_t *, aim_frame_t *, ...); static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_ratechange (aim_session_t *, aim_frame_t *, ...); -static int gaim_bosrights (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_bos (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_admin (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_chat (aim_session_t *, aim_frame_t *, ...); -static int conninitdone_chatnav (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_ratechange(aim_session_t *, aim_frame_t *, ...); +static int gaim_bosrights(aim_session_t *, aim_frame_t *, ...); +static int conninitdone_bos(aim_session_t *, aim_frame_t *, ...); +static int conninitdone_admin(aim_session_t *, aim_frame_t *, ...); +static int conninitdone_chat(aim_session_t *, aim_frame_t *, ...); +static int conninitdone_chatnav(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_msgerr(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_locerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_icbm_param_info (aim_session_t *, aim_frame_t *, ...); -static int gaim_parse_genericerr (aim_session_t *, aim_frame_t *, ...); -static int gaim_selfinfo (aim_session_t *, aim_frame_t *, ...); -static int gaim_offlinemsg (aim_session_t *, aim_frame_t *, ...); -static int gaim_offlinemsgdone (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parserights (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parselist (aim_session_t *, aim_frame_t *, ...); -static int gaim_ssi_parseack (aim_session_t *, aim_frame_t *, ...); -static int gaim_parsemtn (aim_session_t *, aim_frame_t *, ...); -static int gaim_icqinfo (aim_session_t *, aim_frame_t *, ...); -static int gaim_parseaiminfo (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_locerr(aim_session_t *, aim_frame_t *, ...); +static int gaim_icbm_param_info(aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_genericerr(aim_session_t *, aim_frame_t *, ...); +static int gaim_selfinfo(aim_session_t *, aim_frame_t *, ...); +static int gaim_offlinemsg(aim_session_t *, aim_frame_t *, ...); +static int gaim_offlinemsgdone(aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parserights(aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parselist(aim_session_t *, aim_frame_t *, ...); +static int gaim_ssi_parseack(aim_session_t *, aim_frame_t *, ...); +static int gaim_parsemtn(aim_session_t *, aim_frame_t *, ...); +static int gaim_icqinfo(aim_session_t *, aim_frame_t *, ...); +static int gaim_parseaiminfo(aim_session_t *, aim_frame_t *, ...); static char *msgerrreason[] = { "Invalid error", @@ -267,8 +275,9 @@ static char *normalize(const char *s) } static gboolean oscar_callback(gpointer data, gint source, - b_input_condition condition) { - aim_conn_t *conn = (aim_conn_t *)data; + b_input_condition condition) +{ + aim_conn_t *conn = (aim_conn_t *) data; aim_session_t *sess = aim_conn_getsess(conn); struct im_connection *ic = sess ? sess->aux_data : NULL; struct oscar_data *odata; @@ -277,50 +286,54 @@ static gboolean oscar_callback(gpointer data, gint source, /* ic is null. we return, else we seg SIGSEG on next line. */ return FALSE; } - + if (!g_slist_find(get_connections(), ic)) { - /* oh boy. this is probably bad. i guess the only thing we + /* oh boy. this is probably bad. i guess the only thing we * can really do is return? */ return FALSE; } - odata = (struct oscar_data *)ic->proto_data; + odata = (struct oscar_data *) ic->proto_data; if (condition & B_EV_IO_READ) { if (aim_get_command(odata->sess, conn) >= 0) { aim_rxdispatch(odata->sess); - if (odata->killme) - imc_logout(ic, !odata->no_reconnect); + if (odata->killme) { + imc_logout(ic, !odata->no_reconnect); + } } else { if ((conn->type == AIM_CONN_TYPE_BOS) || - !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { + !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) { imcb_error(ic, _("Disconnected.")); imc_logout(ic, TRUE); } else if (conn->type == AIM_CONN_TYPE_CHAT) { struct chat_connection *c = find_oscar_chat_by_conn(ic, conn); c->conn = NULL; - if (c->inpa > 0) + if (c->inpa > 0) { b_event_remove(c->inpa); + } c->inpa = 0; c->fd = -1; aim_conn_kill(odata->sess, &conn); imcb_error(sess->aux_data, _("You have been disconnected from chat room %s."), c->name); } else if (conn->type == AIM_CONN_TYPE_CHATNAV) { - if (odata->cnpa > 0) + if (odata->cnpa > 0) { b_event_remove(odata->cnpa); + } odata->cnpa = 0; while (odata->create_rooms) { struct create_room *cr = odata->create_rooms->data; g_free(cr->name); odata->create_rooms = - g_slist_remove(odata->create_rooms, cr); + g_slist_remove(odata->create_rooms, cr); g_free(cr); imcb_error(sess->aux_data, _("Chat is currently unavailable")); } aim_conn_kill(odata->sess, &conn); } else if (conn->type == AIM_CONN_TYPE_AUTH) { - if (odata->paspa > 0) + if (odata->paspa > 0) { b_event_remove(odata->paspa); + } odata->paspa = 0; aim_conn_kill(odata->sess, &conn); } else { @@ -331,7 +344,7 @@ static gboolean oscar_callback(gpointer data, gint source, /* WTF??? */ return FALSE; } - + return TRUE; } @@ -359,8 +372,8 @@ static gboolean oscar_login_connect(gpointer data, gint source, b_input_conditio aim_conn_completeconnect(sess, conn); ic->inpa = b_input_add(conn->fd, B_EV_IO_READ, - oscar_callback, conn); - + oscar_callback, conn); + return FALSE; } @@ -368,35 +381,37 @@ static void oscar_init(account_t *acc) { set_t *s; gboolean icq = g_ascii_isdigit(acc->user[0]); - + if (icq) { set_add(&acc->set, "ignore_auth_requests", "false", set_eval_bool, acc); set_add(&acc->set, "old_icq_auth", "false", set_eval_bool, acc); } - + s = set_add(&acc->set, "server", icq ? AIM_DEFAULT_LOGIN_SERVER_ICQ - : AIM_DEFAULT_LOGIN_SERVER_AIM, set_eval_account, acc); + : AIM_DEFAULT_LOGIN_SERVER_AIM, set_eval_account, acc); s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY; - + if (icq) { s = set_add(&acc->set, "web_aware", "false", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY; } - + acc->flags |= ACC_FLAG_AWAY_MESSAGE; } -static void oscar_login(account_t *acc) { +static void oscar_login(account_t *acc) +{ aim_session_t *sess; aim_conn_t *conn; struct im_connection *ic = imcb_new(acc); struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1); - if (g_ascii_isdigit(acc->user[0])) + if (g_ascii_isdigit(acc->user[0])) { odata->icq = TRUE; - else + } else { ic->flags |= OPT_DOES_HTML; + } sess = g_new0(aim_session_t, 1); @@ -414,7 +429,7 @@ static void oscar_login(account_t *acc) { imc_logout(ic, TRUE); return; } - + imcb_log(ic, _("Signon: %s"), ic->acc->user); aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0); @@ -431,13 +446,15 @@ static void oscar_login(account_t *acc) { aim_request_login(sess, conn, ic->acc->user); } -static void oscar_logout(struct im_connection *ic) { - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; - +static void oscar_logout(struct im_connection *ic) +{ + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; + while (odata->oscar_chats) { struct chat_connection *n = odata->oscar_chats->data; - if (n->inpa > 0) + if (n->inpa > 0) { b_event_remove(n->inpa); + } g_free(n->name); g_free(n->show); odata->oscar_chats = g_slist_remove(odata->oscar_chats, n); @@ -449,20 +466,27 @@ static void oscar_logout(struct im_connection *ic) { odata->create_rooms = g_slist_remove(odata->create_rooms, cr); g_free(cr); } - if (odata->ips) + if (odata->ips) { g_hash_table_destroy(odata->ips); - if (odata->email) + } + if (odata->email) { g_free(odata->email); - if (odata->newp) + } + if (odata->newp) { g_free(odata->newp); - if (odata->oldp) + } + if (odata->oldp) { g_free(odata->oldp); - if (ic->inpa > 0) + } + if (ic->inpa > 0) { b_event_remove(ic->inpa); - if (odata->cnpa > 0) + } + if (odata->cnpa > 0) { b_event_remove(odata->cnpa); - if (odata->paspa > 0) + } + if (odata->paspa > 0) { b_event_remove(odata->paspa); + } aim_session_kill(odata->sess); g_free(odata->sess); odata->sess = NULL; @@ -470,7 +494,8 @@ static void oscar_logout(struct im_connection *ic) { ic->proto_data = NULL; } -static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond) { +static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond) +{ struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; @@ -493,20 +518,22 @@ static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition aim_conn_completeconnect(sess, bosconn); ic->inpa = b_input_add(bosconn->fd, B_EV_IO_READ, - oscar_callback, bosconn); + oscar_callback, bosconn); imcb_log(ic, _("Connection established, cookie sent")); - + return FALSE; } -static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; struct aim_authresp_info *info; int i; char *host; int port; aim_conn_t *bosconn; struct im_connection *ic = sess->aux_data; - struct oscar_data *od = ic->proto_data; + struct oscar_data *od = ic->proto_data; + port = AIM_LOGIN_PORT; va_start(ap, fr); @@ -520,11 +547,12 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { imcb_error(ic, _("Incorrect nickname or password.")); { int max = od->icq ? 8 : 16; - if (strlen(ic->acc->pass) > max) + if (strlen(ic->acc->pass) > max) { imcb_log(ic, "Note that the maximum password " "length supported by this protocol is " "%d characters, try logging in using " "a shorter password.", max); + } } // plugin_event(event_error, (void *)980, 0, 0, 0); break; @@ -535,7 +563,9 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { case 0x18: /* connecting too frequently */ od->no_reconnect = TRUE; - imcb_error(ic, _("You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); + imcb_error(ic, + _( + "You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; case 0x1c: /* client too old */ @@ -588,10 +618,10 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parsemtn, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_parse_logout, 0); - ((struct oscar_data *)ic->proto_data)->conn = bosconn; - for (i = 0; i < (int)strlen(info->bosip); i++) { + ((struct oscar_data *) ic->proto_data)->conn = bosconn; + for (i = 0; i < (int) strlen(info->bosip); i++) { if (info->bosip[i] == ':') { - port = atoi(&(info->bosip[i+1])); + port = atoi(&(info->bosip[i + 1])); break; } } @@ -613,9 +643,10 @@ static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...) { /* size of icbmui.ocm, the largest module in AIM 3.5 */ #define AIM_MAX_FILE_SIZE 98304 -static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) +{ #if 0 - struct client_info_s info = {"gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b}; + struct client_info_s info = { "gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b }; #else struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD; #endif @@ -632,7 +663,8 @@ static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_parse_logout(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_logout(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct im_connection *ic = sess->aux_data; struct oscar_data *odata = ic->proto_data; int code; @@ -641,22 +673,23 @@ static int gaim_parse_logout(aim_session_t *sess, aim_frame_t *fr, ...) { va_start(ap, fr); code = va_arg(ap, int); va_end(ap); - - imcb_error( ic, "Connection aborted by server: %s", code == 1 ? - "someone else logged in with your account" : - "unknown reason" ); - + + imcb_error(ic, "Connection aborted by server: %s", code == 1 ? + "someone else logged in with your account" : + "unknown reason"); + /* Tell BitlBee to disable auto_reconnect if code == 1, since that means a concurrent login somewhere else. */ odata->no_reconnect = code == 1; - + /* DO NOT log out here! Just tell the callback to do it. */ odata->killme = TRUE; return 1; } -static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { +static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct im_connection *ic = sess->aux_data; struct chat_connection *chatcon; struct groupchat *c = NULL; @@ -672,18 +705,20 @@ static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...) { chatcon = find_oscar_chat_by_conn(ic, fr->conn); chatcon->id = id; - + c = bee_chat_by_title(ic->bee, ic, chatcon->show); - if (c && !c->data) + if (c && !c->data) { chatcon->cnv = c; - else + } else { chatcon->cnv = imcb_chat_new(ic, chatcon->show); + } chatcon->cnv->data = chatcon; return 1; } -static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) { +static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) +{ aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_ERROR, gaim_parse_genericerr, 0); aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0); @@ -695,7 +730,8 @@ static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond) { +static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond) +{ struct im_connection *ic = data; struct oscar_data *odata; aim_session_t *sess; @@ -717,8 +753,8 @@ static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condit aim_conn_completeconnect(sess, tstconn); odata->cnpa = b_input_add(tstconn->fd, B_EV_IO_READ, - oscar_callback, tstconn); - + oscar_callback, tstconn); + return FALSE; } @@ -745,8 +781,8 @@ static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition aim_conn_completeconnect(sess, tstconn); odata->paspa = b_input_add(tstconn->fd, B_EV_IO_READ, - oscar_callback, tstconn); - + oscar_callback, tstconn); + return FALSE; } @@ -780,15 +816,16 @@ static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition aim_conn_completeconnect(sess, ccon->conn); ccon->inpa = b_input_add(tstconn->fd, - B_EV_IO_READ, - oscar_callback, tstconn); + B_EV_IO_READ, + oscar_callback, tstconn); odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon); - + return FALSE; } /* Hrmph. I don't know how to make this look better. --mid */ -static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; struct aim_redirect_data *redir; struct im_connection *ic = sess->aux_data; @@ -802,22 +839,23 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); port = AIM_LOGIN_PORT; - for (i = 0; i < (int)strlen(redir->ip); i++) { + for (i = 0; i < (int) strlen(redir->ip); i++) { if (redir->ip[i] == ':') { - port = atoi(&(redir->ip[i+1])); + port = atoi(&(redir->ip[i + 1])); break; } } host = g_strndup(redir->ip, i); - switch(redir->group) { + switch (redir->group) { case 0x7: /* Authorizer */ tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL); if (tstconn == NULL) { g_free(host); return 1; } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, 0); + aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin, + 0); // aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0); // aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0); // aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0); @@ -837,7 +875,8 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { g_free(host); return 1; } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chatnav, 0); + aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, + conninitdone_chatnav, 0); tstconn->status |= AIM_CONN_STATUS_INPROGRESS; tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, ic); @@ -849,7 +888,7 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { aim_sendcookie(sess, tstconn, redir->cookie); break; case 0xe: /* Chat */ - { + { struct chat_connection *ccon; tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL); @@ -858,7 +897,8 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } - aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, 0); + aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat, + 0); ccon = g_new0(struct chat_connection, 1); ccon->conn = tstconn; @@ -868,7 +908,7 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { ccon->exchange = redir->chat.exchange; ccon->instance = redir->chat.instance; ccon->show = extract_name(redir->chat.room); - + ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS; ccon->conn->fd = proxy_connect(host, port, oscar_chat_connect, ccon); if (ccon->conn->fd < 0) { @@ -880,8 +920,8 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } aim_sendcookie(sess, tstconn, redir->cookie); - } - break; + } + break; default: /* huh? */ break; } @@ -890,7 +930,8 @@ static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct im_connection *ic = sess->aux_data; struct oscar_data *od = ic->proto_data; aim_userinfo_t *info; @@ -899,51 +940,58 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { char *tmp, *state_string = NULL; va_list ap; + va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); va_end(ap); if ((!od->icq) && (info->present & AIM_USERINFO_PRESENT_FLAGS)) { - if (info->flags & AIM_FLAG_AWAY) + if (info->flags & AIM_FLAG_AWAY) { flags |= OPT_AWAY; + } } - + /* Maybe this should be done just for AIM contacts, not sure. */ - if (info->flags & AIM_FLAG_WIRELESS) + if (info->flags & AIM_FLAG_WIRELESS) { flags |= OPT_MOBILE; - + } + if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) { if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) && - (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) { + (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) { flags |= OPT_AWAY; } - - if( info->icqinfo.status & AIM_ICQ_STATE_DND ) + + if (info->icqinfo.status & AIM_ICQ_STATE_DND) { state_string = "Do Not Disturb"; - else if( info->icqinfo.status & AIM_ICQ_STATE_OUT ) + } else if (info->icqinfo.status & AIM_ICQ_STATE_OUT) { state_string = "Not Available"; - else if( info->icqinfo.status & AIM_ICQ_STATE_BUSY ) + } else if (info->icqinfo.status & AIM_ICQ_STATE_BUSY) { state_string = "Occupied"; - else if( info->icqinfo.status & AIM_ICQ_STATE_INVISIBLE ) + } else if (info->icqinfo.status & AIM_ICQ_STATE_INVISIBLE) { state_string = "Invisible"; + } } if (info->present & AIM_USERINFO_PRESENT_IDLE) { time(&time_idle); - time_idle -= info->idletime*60; + time_idle -= info->idletime * 60; } - if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) + if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) { signon = time(NULL) - info->sessionlen; + } if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR) { uint32_t *uin = g_new0(uint32_t, 1); - - if (od->ips == NULL) + + if (od->ips == NULL) { od->ips = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL); - - if (sscanf(info->sn, "%d", uin) == 1) + } + + if (sscanf(info->sn, "%d", uin) == 1) { g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr); + } } tmp = normalize(info->sn); @@ -954,7 +1002,8 @@ static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) +{ aim_userinfo_t *info; va_list ap; struct im_connection *ic = sess->aux_data; @@ -963,42 +1012,46 @@ static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...) { info = va_arg(ap, aim_userinfo_t *); va_end(ap); - imcb_buddy_status(ic, normalize(info->sn), 0, NULL, NULL ); + imcb_buddy_status(ic, normalize(info->sn), 0, NULL, NULL); return 1; } -static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { +static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, + struct aim_incomingim_ch1_args *args) +{ char *tmp = g_malloc(BUF_LONG + 1); struct im_connection *ic = sess->aux_data; int flags = 0; - - if (args->icbmflags & AIM_IMFLAGS_AWAY) + + if (args->icbmflags & AIM_IMFLAGS_AWAY) { flags |= OPT_AWAY; - + } + if ((args->icbmflags & AIM_IMFLAGS_UNICODE) || (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)) { char *src; - - if (args->icbmflags & AIM_IMFLAGS_UNICODE) + + if (args->icbmflags & AIM_IMFLAGS_UNICODE) { src = "UCS-2BE"; - else + } else { src = "ISO8859-1"; - + } + /* Try to use iconv first to convert the message to UTF8 - which is what BitlBee expects */ if (do_iconv(src, "UTF-8", args->msg, tmp, args->msglen, BUF_LONG) >= 0) { // Successfully converted! } else if (args->icbmflags & AIM_IMFLAGS_UNICODE) { int i; - + for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) { unsigned short uni; - - uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff); - + + uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i + 1] & 0xff); + if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */ - g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "%c", uni); + g_snprintf(tmp + strlen(tmp), BUF_LONG - strlen(tmp), "%c", uni); } else { /* something else, do UNICODE entity */ - g_snprintf(tmp+strlen(tmp), BUF_LONG-strlen(tmp), "&#%04x;", uni); + g_snprintf(tmp + strlen(tmp), BUF_LONG - strlen(tmp), "&#%04x;", uni); } } } else { @@ -1008,31 +1061,34 @@ static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ g_snprintf(tmp, BUF_LONG, "%s", args->msg); } else { aim_mpmsg_section_t *part; - + *tmp = 0; for (part = args->mpmsg.parts; part; part = part->next) { if (part->data) { - g_strlcat(tmp, (char*) part->data, BUF_LONG); + g_strlcat(tmp, (char *) part->data, BUF_LONG); g_strlcat(tmp, "\n", BUF_LONG); } } } - + strip_linefeed(tmp); imcb_buddy_msg(ic, normalize(userinfo->sn), tmp, flags, 0); g_free(tmp); - + return 1; } void oscar_accept_chat(void *data); void oscar_reject_chat(void *data); - -static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args) { + +static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, + struct aim_incomingim_ch2_args *args) +{ struct im_connection *ic = sess->aux_data; - if (args->status != AIM_RENDEZVOUS_PROPOSE) + if (args->status != AIM_RENDEZVOUS_PROPOSE) { return 1; + } if (args->reqclass & AIM_CAPS_CHAT) { char *name = extract_name(args->info.chat.roominfo.name); @@ -1050,14 +1106,15 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ inv->ic = ic; inv->exchange = *exch; inv->name = g_strdup(name); - + imcb_ask(ic, txt, inv, oscar_accept_chat, oscar_reject_chat); - - if (name) + + if (name) { g_free(name); + } } else if (args->reqclass & AIM_CAPS_ICQRTF) { // TODO: constify - char text[strlen(args->info.rtfmsg.rtfmsg)+1]; + char text[strlen(args->info.rtfmsg.rtfmsg) + 1]; strncpy(text, args->info.rtfmsg.rtfmsg, sizeof(text)); imcb_buddy_msg(ic, normalize(userinfo->sn), text, 0, 0); } @@ -1065,32 +1122,34 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ return 1; } -static void gaim_icq_authgrant(void *data_) { +static void gaim_icq_authgrant(void *data_) +{ struct icq_auth *data = data_; char *uin; - struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; - + struct oscar_data *od = (struct oscar_data *) data->ic->proto_data; + uin = g_strdup_printf("%u", data->uin); aim_ssi_auth_reply(od->sess, od->conn, uin, 1, ""); // char *message = 0; // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message); imcb_ask_add(data->ic, uin, NULL); - + g_free(uin); g_free(data); } -static void gaim_icq_authdeny(void *data_) { +static void gaim_icq_authdeny(void *data_) +{ struct icq_auth *data = data_; char *uin, *message; - struct oscar_data *od = (struct oscar_data *)data->ic->proto_data; - + struct oscar_data *od = (struct oscar_data *) data->ic->proto_data; + uin = g_strdup_printf("%u", data->uin); message = g_strdup_printf("No reason given."); aim_ssi_auth_reply(od->sess, od->conn, uin, 0, ""); // aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHDENIED, message); g_free(message); - + g_free(uin); g_free(data); } @@ -1098,84 +1157,94 @@ static void gaim_icq_authdeny(void *data_) { /* * For when other people ask you for authorization */ -static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) { +static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg) +{ struct icq_auth *data; char *reason = NULL; char *dialog_msg; - if (set_getbool(&ic->acc->set, "ignore_auth_requests")) + if (set_getbool(&ic->acc->set, "ignore_auth_requests")) { return; - + } + data = g_new(struct icq_auth, 1); - if (strlen(msg) > 6) + if (strlen(msg) > 6) { reason = msg + 6; - - dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s", uin, reason ? reason : "No reason given."); + } + + dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s", + uin, reason ? reason : "No reason given."); data->ic = ic; data->uin = uin; imcb_ask(ic, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny); g_free(dialog_msg); } -static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args) { +static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, + struct aim_incomingim_ch4_args *args) +{ struct im_connection *ic = sess->aux_data; switch (args->type) { - case 0x0001: { /* An almost-normal instant message. Mac ICQ sends this. It's peculiar. */ - char *uin, *message; - uin = g_strdup_printf("%u", args->uin); - message = g_strdup(args->msg); - strip_linefeed(message); - imcb_buddy_msg(ic, normalize(uin), message, 0, 0); - g_free(uin); - g_free(message); - } break; - - case 0x0004: { /* Someone sent you a URL */ - char *uin, *message; - char **m; - - uin = g_strdup_printf("%u", args->uin); - m = g_strsplit(args->msg, "\376", 2); - - if ((strlen(m[0]) != 0)) { - message = g_strjoinv(" -- ", m); - } else { - message = m[1]; - } + case 0x0001: { /* An almost-normal instant message. Mac ICQ sends this. It's peculiar. */ + char *uin, *message; + uin = g_strdup_printf("%u", args->uin); + message = g_strdup(args->msg); + strip_linefeed(message); + imcb_buddy_msg(ic, normalize(uin), message, 0, 0); + g_free(uin); + g_free(message); + } break; + + case 0x0004: { /* Someone sent you a URL */ + char *uin, *message; + char **m; + + uin = g_strdup_printf("%u", args->uin); + m = g_strsplit(args->msg, "\376", 2); + + if ((strlen(m[0]) != 0)) { + message = g_strjoinv(" -- ", m); + } else { + message = m[1]; + } + + strip_linefeed(message); + imcb_buddy_msg(ic, normalize(uin), message, 0, 0); + g_free(uin); + g_free(m); + g_free(message); + } break; - strip_linefeed(message); - imcb_buddy_msg(ic, normalize(uin), message, 0, 0); - g_free(uin); - g_free(m); - g_free(message); - } break; - - case 0x0006: { /* Someone requested authorization */ - gaim_icq_authask(ic, args->uin, args->msg); - } break; + case 0x0006: { /* Someone requested authorization */ + gaim_icq_authask(ic, args->uin, args->msg); + } break; - case 0x0007: { /* Someone has denied you authorization */ - imcb_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); - } break; + case 0x0007: { /* Someone has denied you authorization */ + imcb_log(sess->aux_data, + "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin, + args->msg ? args->msg : _("No reason given.")); + } break; - case 0x0008: { /* Someone has granted you authorization */ - imcb_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, args->msg ? args->msg : _("No reason given.") ); - } break; + case 0x0008: { /* Someone has granted you authorization */ + imcb_log(sess->aux_data, + "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin, + args->msg ? args->msg : _("No reason given.")); + } break; - case 0x0012: { - /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ - } break; + case 0x0012: { + /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ + } break; - default: {; - } break; + default: {; } break; } return 1; } -static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) +{ int channel, ret = 0; aim_userinfo_t *userinfo; va_list ap; @@ -1185,26 +1254,25 @@ static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) { userinfo = va_arg(ap, aim_userinfo_t *); switch (channel) { - case 1: { /* standard message */ - struct aim_incomingim_ch1_args *args; - args = va_arg(ap, struct aim_incomingim_ch1_args *); - ret = incomingim_chan1(sess, fr->conn, userinfo, args); - } break; + case 1: { /* standard message */ + struct aim_incomingim_ch1_args *args; + args = va_arg(ap, struct aim_incomingim_ch1_args *); + ret = incomingim_chan1(sess, fr->conn, userinfo, args); + } break; - case 2: { /* rendevous */ - struct aim_incomingim_ch2_args *args; - args = va_arg(ap, struct aim_incomingim_ch2_args *); - ret = incomingim_chan2(sess, fr->conn, userinfo, args); - } break; + case 2: { /* rendevous */ + struct aim_incomingim_ch2_args *args; + args = va_arg(ap, struct aim_incomingim_ch2_args *); + ret = incomingim_chan2(sess, fr->conn, userinfo, args); + } break; - case 4: { /* ICQ */ - struct aim_incomingim_ch4_args *args; - args = va_arg(ap, struct aim_incomingim_ch4_args *); - ret = incomingim_chan4(sess, fr->conn, userinfo, args); - } break; + case 4: { /* ICQ */ + struct aim_incomingim_ch4_args *args; + args = va_arg(ap, struct aim_incomingim_ch4_args *); + ret = incomingim_chan4(sess, fr->conn, userinfo, args); + } break; - default: {; - } break; + default: {; } break; } va_end(ap); @@ -1212,7 +1280,8 @@ static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...) { return ret; } -static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; guint16 nummissed, reason; aim_userinfo_t *userinfo; @@ -1220,183 +1289,190 @@ static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...) { va_start(ap, fr); va_arg(ap, unsigned int); /* chan */ userinfo = va_arg(ap, aim_userinfo_t *); - nummissed = (guint16)va_arg(ap, unsigned int); - reason = (guint16)va_arg(ap, unsigned int); + nummissed = (guint16) va_arg(ap, unsigned int); + reason = (guint16) va_arg(ap, unsigned int); va_end(ap); - switch(reason) { - case 0: - /* Invalid (0) */ - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s because it was invalid.") : - _("You missed %d messages from %s because they were invalid."), - nummissed, - userinfo->sn); - break; - case 1: - /* Message too large */ - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s because it was too large.") : - _("You missed %d messages from %s because they were too large."), - nummissed, - userinfo->sn); - break; - case 2: - /* Rate exceeded */ - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s because the rate limit has been exceeded.") : - _("You missed %d messages from %s because the rate limit has been exceeded."), - nummissed, - userinfo->sn); - break; - case 3: - /* Evil Sender */ - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s because it was too evil.") : - _("You missed %d messages from %s because they are too evil."), - nummissed, - userinfo->sn); - break; - case 4: - /* Evil Receiver */ - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s because you are too evil.") : - _("You missed %d messages from %s because you are too evil."), - nummissed, - userinfo->sn); - break; - default: - imcb_error(sess->aux_data, - nummissed == 1 ? - _("You missed %d message from %s for unknown reasons.") : - _("You missed %d messages from %s for unknown reasons."), - nummissed, - userinfo->sn); - break; + switch (reason) { + case 0: + /* Invalid (0) */ + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s because it was invalid.") : + _("You missed %d messages from %s because they were invalid."), + nummissed, + userinfo->sn); + break; + case 1: + /* Message too large */ + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s because it was too large.") : + _("You missed %d messages from %s because they were too large."), + nummissed, + userinfo->sn); + break; + case 2: + /* Rate exceeded */ + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s because the rate limit has been exceeded.") : + _("You missed %d messages from %s because the rate limit has been exceeded."), + nummissed, + userinfo->sn); + break; + case 3: + /* Evil Sender */ + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s because it was too evil.") : + _("You missed %d messages from %s because they are too evil."), + nummissed, + userinfo->sn); + break; + case 4: + /* Evil Receiver */ + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s because you are too evil.") : + _("You missed %d messages from %s because you are too evil."), + nummissed, + userinfo->sn); + break; + default: + imcb_error(sess->aux_data, + nummissed == 1 ? + _("You missed %d message from %s for unknown reasons.") : + _("You missed %d messages from %s for unknown reasons."), + nummissed, + userinfo->sn); + break; } return 1; } -static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; guint16 reason; va_start(ap, fr); - reason = (guint16)va_arg(ap, unsigned int); + reason = (guint16) va_arg(ap, unsigned int); va_end(ap); imcb_error(sess->aux_data, _("SNAC threw error: %s"), - reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error"); + reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error"); return 1; } -static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; char *destn; guint16 reason; va_start(ap, fr); - reason = (guint16)va_arg(ap, unsigned int); + reason = (guint16) va_arg(ap, unsigned int); destn = va_arg(ap, char *); va_end(ap); imcb_error(sess->aux_data, _("Your message to %s did not get sent: %s"), destn, - (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); + (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); return 1; } -static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; char *destn; guint16 reason; va_start(ap, fr); - reason = (guint16)va_arg(ap, unsigned int); + reason = (guint16) va_arg(ap, unsigned int); destn = va_arg(ap, char *); va_end(ap); imcb_error(sess->aux_data, _("User information for %s unavailable: %s"), destn, - (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); + (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown")); return 1; } -static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...) +{ guint16 id; va_list ap; va_start(ap, fr); - id = (guint16)va_arg(ap, unsigned int); + id = (guint16) va_arg(ap, unsigned int); va_arg(ap, char *); /* msg */ va_end(ap); - if (id < 4) + if (id < 4) { imcb_error(sess->aux_data, _("Your connection may be lost.")); + } return 1; } -static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; guint16 type; struct im_connection *ic = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; va_start(ap, fr); - type = (guint16)va_arg(ap, unsigned int); - - switch(type) { - case 0x0002: { - va_arg(ap, unsigned int); /* maxrooms */ - va_arg(ap, int); /* exchangecount */ - va_arg(ap, struct aim_chat_exchangeinfo *); /* exchanges */ - va_end(ap); - - while (odata->create_rooms) { - struct create_room *cr = odata->create_rooms->data; - aim_chatnav_createroom(sess, fr->conn, cr->name, cr->exchange); - g_free(cr->name); - odata->create_rooms = g_slist_remove(odata->create_rooms, cr); - g_free(cr); - } - } - break; - case 0x0008: { - char *ck; - guint16 instance, exchange; - - va_arg(ap, char *); /* fqcn */ - instance = (guint16)va_arg(ap, unsigned int); - exchange = (guint16)va_arg(ap, unsigned int); - va_arg(ap, unsigned int); /* flags */ - va_arg(ap, guint32); /* createtime */ - va_arg(ap, unsigned int); /* maxmsglen */ - va_arg(ap, unsigned int); /* maxoccupancy */ - va_arg(ap, int); /* createperms */ - va_arg(ap, unsigned int); /* unknown */ - va_arg(ap, char *); /* name */ - ck = va_arg(ap, char *); - va_end(ap); - - aim_chat_join(odata->sess, odata->conn, exchange, ck, instance); - } - break; - default: - va_end(ap); - break; + type = (guint16) va_arg(ap, unsigned int); + + switch (type) { + case 0x0002: { + va_arg(ap, unsigned int); /* maxrooms */ + va_arg(ap, int); /* exchangecount */ + va_arg(ap, struct aim_chat_exchangeinfo *); /* exchanges */ + va_end(ap); + + while (odata->create_rooms) { + struct create_room *cr = odata->create_rooms->data; + aim_chatnav_createroom(sess, fr->conn, cr->name, cr->exchange); + g_free(cr->name); + odata->create_rooms = g_slist_remove(odata->create_rooms, cr); + g_free(cr); + } + } + break; + case 0x0008: { + char *ck; + guint16 instance, exchange; + + va_arg(ap, char *); /* fqcn */ + instance = (guint16) va_arg(ap, unsigned int); + exchange = (guint16) va_arg(ap, unsigned int); + va_arg(ap, unsigned int); /* flags */ + va_arg(ap, guint32); /* createtime */ + va_arg(ap, unsigned int); /* maxmsglen */ + va_arg(ap, unsigned int); /* maxoccupancy */ + va_arg(ap, int); /* createperms */ + va_arg(ap, unsigned int); /* unknown */ + va_arg(ap, char *); /* name */ + ck = va_arg(ap, char *); + va_end(ap); + + aim_chat_join(odata->sess, odata->conn, exchange, ck, instance); + } + break; + default: + va_end(ap); + break; } return 1; } -static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; int count, i; aim_userinfo_t *info; @@ -1410,16 +1486,19 @@ static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); c = find_oscar_chat_by_conn(g, fr->conn); - if (!c) + if (!c) { return 1; + } - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { imcb_chat_add_buddy(c->cnv, normalize(info[i].sn)); + } return 1; } -static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; int count, i; aim_userinfo_t *info; @@ -1433,16 +1512,19 @@ static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); c = find_oscar_chat_by_conn(g, fr->conn); - if (!c) + if (!c) { return 1; + } - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { imcb_chat_remove_buddy(c->cnv, normalize(info[i].sn), NULL); + } return 1; } -static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; guint16 maxmsglen, maxvisiblemsglen; struct im_connection *ic = sess->aux_data; @@ -1456,10 +1538,10 @@ static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) { va_arg(ap, char *); /* roomdesc */ va_arg(ap, int); /* unknown_c9 */ va_arg(ap, unsigned long); /* creationtime */ - maxmsglen = (guint16)va_arg(ap, int); + maxmsglen = (guint16) va_arg(ap, int); va_arg(ap, int); /* unknown_d2 */ va_arg(ap, int); /* unknown_d5 */ - maxvisiblemsglen = (guint16)va_arg(ap, int); + maxvisiblemsglen = (guint16) va_arg(ap, int); va_end(ap); ccon->maxlen = maxmsglen; @@ -1468,7 +1550,8 @@ static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; aim_userinfo_t *info; char *msg; @@ -1488,42 +1571,44 @@ static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) +{ #if 0 static const char *codes[5] = { "invalid", - "change", - "warning", - "limit", - "limit cleared", + "change", + "warning", + "limit", + "limit cleared", }; #endif va_list ap; guint16 code; guint32 windowsize, clear, currentavg; - va_start(ap, fr); - code = (guint16)va_arg(ap, unsigned int); + va_start(ap, fr); + code = (guint16) va_arg(ap, unsigned int); va_arg(ap, unsigned int); /* rateclass */ - windowsize = (guint32)va_arg(ap, unsigned long); - clear = (guint32)va_arg(ap, unsigned long); + windowsize = (guint32) va_arg(ap, unsigned long); + clear = (guint32) va_arg(ap, unsigned long); va_arg(ap, unsigned long); /* alert */ va_arg(ap, unsigned long); /* limit */ va_arg(ap, unsigned long); /* disconnect */ - currentavg = (guint32)va_arg(ap, unsigned long); + currentavg = (guint32) va_arg(ap, unsigned long); va_arg(ap, unsigned long); /* maxavg */ va_end(ap); /* XXX fix these values */ if (code == AIM_RATE_CODE_CHANGE) { - if (currentavg >= clear) + if (currentavg >= clear) { aim_conn_setlatency(fr->conn, 0); + } } else if (code == AIM_RATE_CODE_WARNING) { - aim_conn_setlatency(fr->conn, windowsize/4); + aim_conn_setlatency(fr->conn, windowsize / 4); } else if (code == AIM_RATE_CODE_LIMIT) { imcb_error(sess->aux_data, _("The last message was not sent because you are over the rate limit. " - "Please wait 10 seconds and try again.")); - aim_conn_setlatency(fr->conn, windowsize/2); + "Please wait 10 seconds and try again.")); + aim_conn_setlatency(fr->conn, windowsize / 2); } else if (code == AIM_RATE_CODE_CLEARLIMIT) { aim_conn_setlatency(fr->conn, 0); } @@ -1531,11 +1616,13 @@ static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...) +{ return 1; } -static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) { +static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) +{ aim_reqpersonalinfo(sess, fr->conn); aim_bos_reqlocaterights(sess, fr->conn); @@ -1546,12 +1633,13 @@ static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) { aim_bos_reqrights(sess, fr->conn); aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS); aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE | - AIM_PRIVFLAGS_ALLOWMEMBERSINCE); + AIM_PRIVFLAGS_ALLOWMEMBERSINCE); return 1; } -static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) { +static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct im_connection *ic = sess->aux_data; struct oscar_data *od = ic->proto_data; @@ -1588,7 +1676,8 @@ static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_icbm_param_info(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_icbm_param_info(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct aim_icbmparameters *params; va_list ap; @@ -1611,52 +1700,54 @@ static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) va_list ap; guint16 maxsiglen; struct im_connection *ic = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; va_start(ap, fr); maxsiglen = va_arg(ap, int); va_end(ap); - odata->rights.maxsiglen = odata->rights.maxawaymsglen = (guint)maxsiglen; + odata->rights.maxsiglen = odata->rights.maxawaymsglen = (guint) maxsiglen; /* FIXME: It seems we're not really using this, and it broke now that struct aim_user is dead. aim_bos_setprofile(sess, fr->conn, ic->user->user_info, NULL, gaim_caps); */ - + return 1; } -static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; guint16 maxbuddies, maxwatchers; struct im_connection *ic = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; va_start(ap, fr); - maxbuddies = (guint16)va_arg(ap, unsigned int); - maxwatchers = (guint16)va_arg(ap, unsigned int); + maxbuddies = (guint16) va_arg(ap, unsigned int); + maxwatchers = (guint16) va_arg(ap, unsigned int); va_end(ap); - odata->rights.maxbuddies = (guint)maxbuddies; - odata->rights.maxwatchers = (guint)maxwatchers; + odata->rights.maxbuddies = (guint) maxbuddies; + odata->rights.maxwatchers = (guint) maxwatchers; return 1; } -static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) +{ guint16 maxpermits, maxdenies; va_list ap; struct im_connection *ic = sess->aux_data; - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; va_start(ap, fr); - maxpermits = (guint16)va_arg(ap, unsigned int); - maxdenies = (guint16)va_arg(ap, unsigned int); + maxpermits = (guint16) va_arg(ap, unsigned int); + maxdenies = (guint16) va_arg(ap, unsigned int); va_end(ap); - odata->rights.maxpermits = (guint)maxpermits; - odata->rights.maxdenies = (guint)maxdenies; + odata->rights.maxpermits = (guint) maxpermits; + odata->rights.maxdenies = (guint) maxdenies; aim_clientready(sess, fr->conn); @@ -1668,7 +1759,8 @@ static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) { return 1; } -static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) +{ va_list ap; struct aim_icq_offlinemsg *msg; struct im_connection *ic = sess->aux_data; @@ -1678,56 +1770,59 @@ static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...) { va_end(ap); switch (msg->type) { - case 0x0001: { /* Basic offline message */ - char sender[32]; - char *dialog_msg = g_strdup(msg->msg); - time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); - g_snprintf(sender, sizeof(sender), "%u", msg->sender); - strip_linefeed(dialog_msg); - imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t); - g_free(dialog_msg); - } break; - - case 0x0004: { /* Someone sent you a URL */ - char sender[32]; - char *dialog_msg; - char **m; - - time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); - g_snprintf(sender, sizeof(sender), "%u", msg->sender); - - m = g_strsplit(msg->msg, "\376", 2); - - if ((strlen(m[0]) != 0)) { - dialog_msg = g_strjoinv(" -- ", m); - } else { - dialog_msg = m[1]; - } - - strip_linefeed(dialog_msg); - imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t); - g_free(dialog_msg); - g_free(m); - } break; - - case 0x0006: { /* Authorization request */ - gaim_icq_authask(ic, msg->sender, msg->msg); - } break; - - case 0x0007: { /* Someone has denied you authorization */ - imcb_log(sess->aux_data, "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); - } break; - - case 0x0008: { /* Someone has granted you authorization */ - imcb_log(sess->aux_data, "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, msg->msg ? msg->msg : _("No reason given.") ); - } break; - - case 0x0012: { - /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ - } break; - - default: {; + case 0x0001: { /* Basic offline message */ + char sender[32]; + char *dialog_msg = g_strdup(msg->msg); + time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); + g_snprintf(sender, sizeof(sender), "%u", msg->sender); + strip_linefeed(dialog_msg); + imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t); + g_free(dialog_msg); + } break; + + case 0x0004: { /* Someone sent you a URL */ + char sender[32]; + char *dialog_msg; + char **m; + + time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0); + g_snprintf(sender, sizeof(sender), "%u", msg->sender); + + m = g_strsplit(msg->msg, "\376", 2); + + if ((strlen(m[0]) != 0)) { + dialog_msg = g_strjoinv(" -- ", m); + } else { + dialog_msg = m[1]; } + + strip_linefeed(dialog_msg); + imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t); + g_free(dialog_msg); + g_free(m); + } break; + + case 0x0006: { /* Authorization request */ + gaim_icq_authask(ic, msg->sender, msg->msg); + } break; + + case 0x0007: { /* Someone has denied you authorization */ + imcb_log(sess->aux_data, + "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender, + msg->msg ? msg->msg : _("No reason given.")); + } break; + + case 0x0008: { /* Someone has granted you authorization */ + imcb_log(sess->aux_data, + "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender, + msg->msg ? msg->msg : _("No reason given.")); + } break; + + case 0x0012: { + /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */ + } break; + + default: {; } } return 1; @@ -1739,27 +1834,34 @@ static int gaim_offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...) return 1; } -static void oscar_keepalive(struct im_connection *ic) { - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; +static void oscar_keepalive(struct im_connection *ic) +{ + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; + aim_flap_nop(odata->sess, odata->conn); } -static int oscar_buddy_msg(struct im_connection *ic, char *name, char *message, int imflags) { - struct oscar_data *odata = (struct oscar_data *)ic->proto_data; +static int oscar_buddy_msg(struct im_connection *ic, char *name, char *message, int imflags) +{ + struct oscar_data *odata = (struct oscar_data *) ic->proto_data; int ret = 0, len = strlen(message); + if (imflags & OPT_AWAY) { ret = aim_send_im(odata->sess, name, AIM_IMFLAGS_AWAY, message); } else { struct aim_sendimext_args args; char *s; - + args.flags = AIM_IMFLAGS_ACK; - if (odata->icq) + if (odata->icq) { args.flags |= AIM_IMFLAGS_OFFLINE; - for (s = message; *s; s++) - if (*s & 128) + } + for (s = message; *s; s++) { + if (*s & 128) { break; - + } + } + /* Message contains high ASCII chars, time for some translation! */ if (*s) { s = g_malloc(BUF_LONG); @@ -1773,59 +1875,66 @@ static int oscar_buddy_msg(struct im_connection *ic, char *name, char *message, len = ret; } else { /* OOF, translation failed... Oh well.. */ - g_free( s ); + g_free(s); s = message; } } else { s = message; } - + args.features = gaim_features; args.featureslen = sizeof(gaim_features); - + args.destsn = name; args.msg = s; args.msglen = len; - + ret = aim_send_im_ext(odata->sess, &args); - + if (s != message) { g_free(s); } } - if (ret >= 0) + if (ret >= 0) { return 1; + } return ret; } -static void oscar_get_info(struct im_connection *g, char *name) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; - if (odata->icq) +static void oscar_get_info(struct im_connection *g, char *name) +{ + struct oscar_data *odata = (struct oscar_data *) g->proto_data; + + if (odata->icq) { aim_icq_getallinfo(odata->sess, name); - else { + } else { aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE); aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_GENERALINFO); } } -static void oscar_get_away(struct im_connection *g, char *who) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; +static void oscar_get_away(struct im_connection *g, char *who) +{ + struct oscar_data *odata = (struct oscar_data *) g->proto_data; + if (odata->icq) { /** FIXME(wilmer): Hmm, lost the ability to get away msgs here, do we care to get that back? struct buddy *budlight = imcb_find_buddy(g, who); if (budlight) - if ((budlight->uc & 0xff80) >> 7) - if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) - aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7); + if ((budlight->uc & 0xff80) >> 7) + if (budlight->caps & AIM_CAPS_ICQSERVERRELAY) + aim_send_im_ch2_geticqmessage(odata->sess, who, (budlight->uc & 0xff80) >> 7); */ - } else + } else { aim_getinfo(odata->sess, odata->conn, who, AIM_GETINFO_AWAYMESSAGE); + } } static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message) { - if (state == NULL) + if (state == NULL) { state = ""; + } if (!g_strcasecmp(state, _("Visible"))) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1837,8 +1946,9 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, message = state; } - if (od->rights.maxawaymsglen == 0) + if (od->rights.maxawaymsglen == 0) { imcb_error(ic, "oscar_set_away_aim called before locate rights received"); + } aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); @@ -1851,7 +1961,8 @@ static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, } if (strlen(message) > od->rights.maxawaymsglen) { - imcb_error(ic, "Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); + imcb_error(ic, "Maximum away message length of %d bytes exceeded, truncating", + od->rights.maxawaymsglen); } ic->away = g_strndup(message, od->rights.maxawaymsglen); @@ -1904,7 +2015,7 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE); ic->away = g_strdup(msg); } else { - if (no_message) { + if (no_message) { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } else { aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY); @@ -1918,36 +2029,48 @@ static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, static void oscar_set_away(struct im_connection *ic, char *state, char *message) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; + struct oscar_data *od = (struct oscar_data *) ic->proto_data; oscar_set_away_aim(ic, od, state, message); - if (od->icq) + if (od->icq) { oscar_set_away_icq(ic, od, state, message); + } return; } -static void oscar_add_buddy(struct im_connection *g, char *name, char *group) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; +static void oscar_add_buddy(struct im_connection *g, char *name, char *group) +{ + struct oscar_data *odata = (struct oscar_data *) g->proto_data; bee_user_t *bu; - - if (group && (bu = bee_user_by_handle(g->bee, g, name)) && bu->group) + + if (group && (bu = bee_user_by_handle(g->bee, g, name)) && bu->group) { aim_ssi_movebuddy(odata->sess, odata->conn, bu->group->name, group, name); - else + } else { aim_ssi_addbuddies(odata->sess, odata->conn, group ? : OSCAR_GROUP, &name, 1, 0); + } } -static void oscar_remove_buddy(struct im_connection *g, char *name, char *group) { - struct oscar_data *odata = (struct oscar_data *)g->proto_data; +static void oscar_remove_buddy(struct im_connection *g, char *name, char *group) +{ + struct oscar_data *odata = (struct oscar_data *) g->proto_data; struct aim_ssi_item *ssigroup; - while ((ssigroup = aim_ssi_itemlist_findparent(odata->sess->ssi.items, name)) && !aim_ssi_delbuddies(odata->sess, odata->conn, ssigroup->name, &name, 1)); + + while ((ssigroup = + aim_ssi_itemlist_findparent(odata->sess->ssi.items, + name)) && + !aim_ssi_delbuddies(odata->sess, odata->conn, ssigroup->name, &name, 1)) { + ; + } } -static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...) +{ return 1; } -static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { +static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) +{ struct im_connection *ic = sess->aux_data; struct aim_ssi_item *curitem, *curgroup = NULL; int tmp; @@ -1955,172 +2078,185 @@ static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...) { /* Add from server list to local list */ tmp = 0; - for (curitem=sess->ssi.items; curitem; curitem=curitem->next) { + for (curitem = sess->ssi.items; curitem; curitem = curitem->next) { nrm = curitem->name ? normalize(curitem->name) : NULL; - + switch (curitem->type) { - case 0x0000: /* Buddy */ - if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) { - char *realname = NULL; - - if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) - realname = aim_gettlv_str(curitem->data, 0x0131, 1); - - imcb_add_buddy(ic, nrm, curgroup ? (curgroup->gid == curitem->gid ? curgroup->name : NULL) : NULL); - - if (realname) { - imcb_buddy_nick_hint(ic, nrm, realname); - imcb_rename_buddy(ic, nrm, realname); - g_free(realname); - } + case 0x0000: /* Buddy */ + if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) { + char *realname = NULL; + + if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) { + realname = aim_gettlv_str(curitem->data, 0x0131, 1); } - break; - case 0x0001: /* Group */ - curgroup = curitem; - break; + imcb_add_buddy(ic, nrm, + curgroup ? (curgroup->gid == + curitem->gid ? curgroup->name : NULL) : NULL); - case 0x0002: /* Permit buddy */ - if (curitem->name) { - GSList *list; - for (list=ic->permit; (list && aim_sncmp(curitem->name, list->data)); list=list->next); - if (!list) { - char *name; - name = g_strdup(nrm); - ic->permit = g_slist_append(ic->permit, name); - tmp++; - } + if (realname) { + imcb_buddy_nick_hint(ic, nrm, realname); + imcb_rename_buddy(ic, nrm, realname); + g_free(realname); } - break; + } + break; - case 0x0003: /* Deny buddy */ - if (curitem->name) { - GSList *list; - for (list=ic->deny; (list && aim_sncmp(curitem->name, list->data)); list=list->next); - if (!list) { - char *name; - name = g_strdup(nrm); - ic->deny = g_slist_append(ic->deny, name); - tmp++; - } + case 0x0001: /* Group */ + curgroup = curitem; + break; + + case 0x0002: /* Permit buddy */ + if (curitem->name) { + GSList *list; + for (list = ic->permit; (list && aim_sncmp(curitem->name, list->data)); + list = list->next) { + ; } - break; + if (!list) { + char *name; + name = g_strdup(nrm); + ic->permit = g_slist_append(ic->permit, name); + tmp++; + } + } + break; - case 0x0004: /* Permit/deny setting */ - if (curitem->data) { - guint8 permdeny; - if ((permdeny = aim_ssi_getpermdeny(sess->ssi.items)) && (permdeny != ic->permdeny)) { - ic->permdeny = permdeny; - tmp++; - } + case 0x0003: /* Deny buddy */ + if (curitem->name) { + GSList *list; + for (list = ic->deny; + (list && aim_sncmp(curitem->name, list->data)); list = list->next) { + ; } - break; + if (!list) { + char *name; + name = g_strdup(nrm); + ic->deny = g_slist_append(ic->deny, name); + tmp++; + } + } + break; - case 0x0005: /* Presence setting */ - /* We don't want to change Gaim's setting because it applies to all accounts */ - break; + case 0x0004: /* Permit/deny setting */ + if (curitem->data) { + guint8 permdeny; + if ((permdeny = aim_ssi_getpermdeny(sess->ssi.items)) && (permdeny != ic->permdeny)) { + ic->permdeny = permdeny; + tmp++; + } + } + break; + + case 0x0005: /* Presence setting */ + /* We don't want to change Gaim's setting because it applies to all accounts */ + break; } /* End of switch on curitem->type */ } /* End of for loop */ aim_ssi_enable(sess, fr->conn); - + /* Request offline messages, now that the buddy list is complete. */ aim_icq_reqofflinemsgs(sess); - + /* Now that we have a buddy list, we can tell BitlBee that we're online. */ imcb_connected(ic); - + return 1; } -static int gaim_ssi_parseack( aim_session_t *sess, aim_frame_t *fr, ... ) +static int gaim_ssi_parseack(aim_session_t *sess, aim_frame_t *fr, ...) { aim_snac_t *origsnac; va_list ap; - va_start( ap, fr ); - origsnac = va_arg( ap, aim_snac_t * ); - va_end( ap ); - - if( origsnac && origsnac->family == AIM_CB_FAM_SSI && origsnac->type == AIM_CB_SSI_ADD && origsnac->data ) - { - int i, st, count = aim_bstream_empty( &fr->data ); + va_start(ap, fr); + origsnac = va_arg(ap, aim_snac_t *); + va_end(ap); + + if (origsnac && origsnac->family == AIM_CB_FAM_SSI && origsnac->type == AIM_CB_SSI_ADD && origsnac->data) { + int i, st, count = aim_bstream_empty(&fr->data); char *list; - - if( count & 1 ) - { + + if (count & 1) { /* Hmm, the length should be even... */ - imcb_error( sess->aux_data, "Received SSI ACK package with non-even length"); - return( 0 ); + imcb_error(sess->aux_data, "Received SSI ACK package with non-even length"); + return(0); } count >>= 1; - + list = (char *) origsnac->data; - for( i = 0; i < count; i ++ ) - { - struct aim_ssi_item *ssigroup = aim_ssi_itemlist_findparent( sess->ssi.items, list ); + for (i = 0; i < count; i++) { + struct aim_ssi_item *ssigroup = aim_ssi_itemlist_findparent(sess->ssi.items, list); char *group = ssigroup ? ssigroup->name : NULL; - - st = aimbs_get16( &fr->data ); - if( st == 0x00 ) - { - imcb_add_buddy( sess->aux_data, normalize(list), group ); - } - else if( st == 0x0E ) - { - imcb_log( sess->aux_data, "Buddy %s can't be added without authorization, requesting authorization", list ); - - aim_ssi_auth_request( sess, fr->conn, list, "" ); - aim_ssi_addbuddies( sess, fr->conn, OSCAR_GROUP, &list, 1, 1 ); - } - else if( st == 0x0A ) - { - imcb_error( sess->aux_data, "Buddy %s is already in your list", list ); - } - else - { - imcb_error( sess->aux_data, "Error while adding buddy: 0x%04x", st ); + + st = aimbs_get16(&fr->data); + if (st == 0x00) { + imcb_add_buddy(sess->aux_data, normalize(list), group); + } else if (st == 0x0E) { + imcb_log(sess->aux_data, + "Buddy %s can't be added without authorization, requesting authorization", + list); + + aim_ssi_auth_request(sess, fr->conn, list, ""); + aim_ssi_addbuddies(sess, fr->conn, OSCAR_GROUP, &list, 1, 1); + } else if (st == 0x0A) { + imcb_error(sess->aux_data, "Buddy %s is already in your list", list); + } else { + imcb_error(sess->aux_data, "Error while adding buddy: 0x%04x", st); } - list += strlen( list ) + 1; + list += strlen(list) + 1; } } - - return( 1 ); + + return(1); } -static void oscar_add_permit(struct im_connection *ic, char *who) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; +static void oscar_add_permit(struct im_connection *ic, char *who) +{ + struct oscar_data *od = (struct oscar_data *) ic->proto_data; + if (od->icq) { aim_ssi_auth_reply(od->sess, od->conn, who, 1, ""); } else { - if (od->sess->ssi.received_data) + if (od->sess->ssi.received_data) { aim_ssi_addpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_PERMIT); + } } } -static void oscar_add_deny(struct im_connection *ic, char *who) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; +static void oscar_add_deny(struct im_connection *ic, char *who) +{ + struct oscar_data *od = (struct oscar_data *) ic->proto_data; + if (od->icq) { aim_ssi_auth_reply(od->sess, od->conn, who, 0, ""); } else { - if (od->sess->ssi.received_data) + if (od->sess->ssi.received_data) { aim_ssi_addpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_DENY); + } } } -static void oscar_rem_permit(struct im_connection *ic, char *who) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; +static void oscar_rem_permit(struct im_connection *ic, char *who) +{ + struct oscar_data *od = (struct oscar_data *) ic->proto_data; + if (!od->icq) { - if (od->sess->ssi.received_data) + if (od->sess->ssi.received_data) { aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_PERMIT); + } } } -static void oscar_rem_deny(struct im_connection *ic, char *who) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; +static void oscar_rem_deny(struct im_connection *ic, char *who) +{ + struct oscar_data *od = (struct oscar_data *) ic->proto_data; + if (!od->icq) { - if (od->sess->ssi.received_data) + if (od->sess->ssi.received_data) { aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_DENY); + } } } @@ -2158,14 +2294,15 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) info = va_arg(ap, struct aim_icq_info *); va_end(ap); - if (!info->uin) + if (!info->uin) { return 0; + } str = g_string_sized_new(512); g_snprintf(who, sizeof(who), "%u", info->uin); - g_string_printf(str, "%s: %s - %s: %s", _("UIN"), who, _("Nick"), - info->nick ? info->nick : "-"); + g_string_printf(str, "%s: %s - %s: %s", _("UIN"), who, _("Nick"), + info->nick ? info->nick : "-"); g_string_append_printf(str, "\n%s: %s", _("First Name"), info->first); g_string_append_printf(str, "\n%s: %s", _("Last Name"), info->last); g_string_append_printf(str, "\n%s: %s", _("Email Address"), info->email); @@ -2180,15 +2317,16 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) (ip >> 24), (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); } g_string_append_printf(str, "\n%s: %s", _("Mobile Phone"), info->mobile); - if (info->gender != 0) - g_string_append_printf(str, "\n%s: %s", _("Gender"), info->gender==1 ? _("Female") : _("Male")); + if (info->gender != 0) { + g_string_append_printf(str, "\n%s: %s", _("Gender"), info->gender == 1 ? _("Female") : _("Male")); + } if (info->birthyear || info->birthmonth || info->birthday) { char date[30]; struct tm tm; memset(&tm, 0, sizeof(struct tm)); - tm.tm_mday = (int)info->birthday; - tm.tm_mon = (int)info->birthmonth-1; - tm.tm_year = (int)info->birthyear%100; + tm.tm_mday = (int) info->birthday; + tm.tm_mon = (int) info->birthmonth - 1; + tm.tm_year = (int) info->birthyear % 100; strftime(date, sizeof(date), "%Y-%m-%d", &tm); g_string_append_printf(str, "\n%s: %s", _("Birthday"), date); } @@ -2199,19 +2337,25 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) } g_string_append_printf(str, "\n%s: %s", _("Personal Web Page"), info->personalwebpage); if (info->info && info->info[0]) { - g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Additional Information"), - info->info, _("End of Additional Information")); + g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Additional Information"), + info->info, _("End of Additional Information")); } g_string_append_c(str, '\n'); - if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { + if ((info->homeaddr && + (info->homeaddr[0])) || + (info->homecity && + info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) { g_string_append_printf(str, "%s:", _("Home Address")); g_string_append_printf(str, "\n%s: %s", _("Address"), info->homeaddr); g_string_append_printf(str, "\n%s: %s", _("City"), info->homecity); - g_string_append_printf(str, "\n%s: %s", _("State"), info->homestate); + g_string_append_printf(str, "\n%s: %s", _("State"), info->homestate); g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->homezip); g_string_append_c(str, '\n'); } - if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { + if ((info->workaddr && + info->workaddr[0]) || + (info->workcity && + info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) { g_string_append_printf(str, "%s:", _("Work Address")); g_string_append_printf(str, "\n%s: %s", _("Address"), info->workaddr); g_string_append_printf(str, "\n%s: %s", _("City"), info->workcity); @@ -2219,7 +2363,11 @@ static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...) g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->workzip); g_string_append_c(str, '\n'); } - if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { + if ((info->workcompany && + info->workcompany[0]) || + (info->workdivision && + info->workdivision[0]) || + (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) { g_string_append_printf(str, "%s:", _("Work Information")); g_string_append_printf(str, "\n%s: %s", _("Company"), info->workcompany); g_string_append_printf(str, "\n%s: %s", _("Division"), info->workdivision); @@ -2246,19 +2394,19 @@ static char *oscar_encoding_extract(const char *encoding) /* Make sure encoding begins with charset= */ if (strncmp(encoding, "text/plain; charset=", 20) && - strncmp(encoding, "text/aolrtf; charset=", 21) && - strncmp(encoding, "text/x-aolrtf; charset=", 23)) - { + strncmp(encoding, "text/aolrtf; charset=", 21) && + strncmp(encoding, "text/x-aolrtf; charset=", 23)) { return NULL; } begin = strchr(encoding, '"'); end = strrchr(encoding, '"'); - if ((begin == NULL) || (end == NULL) || (begin >= end)) + if ((begin == NULL) || (end == NULL) || (begin >= end)) { return NULL; + } - ret = g_strndup(begin+1, (end-1) - begin); + ret = g_strndup(begin + 1, (end - 1) - begin); return ret; } @@ -2287,7 +2435,7 @@ static char *oscar_encoding_to_utf8(char *encoding, char *text, int textlen) * that was specified. So we assume it's UTF-8 and hope for the best. */ if (*utf8 == 0) { - strncpy(utf8, text, textlen); + strncpy(utf8, text, textlen); } return utf8; @@ -2311,13 +2459,14 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) text_length = va_arg(ap, int); va_end(ap); - if(text_encoding) + if (text_encoding) { extracted_encoding = oscar_encoding_extract(text_encoding); - if(infotype == AIM_GETINFO_GENERALINFO) { + } + if (infotype == AIM_GETINFO_GENERALINFO) { /*Display idle time*/ char buff[256]; struct tm idletime; - if(userinfo->idletime) { + if (userinfo->idletime) { memset(&idletime, 0, sizeof(struct tm)); idletime.tm_mday = (userinfo->idletime / 60) / 24; idletime.tm_hour = (userinfo->idletime / 60) % 24; @@ -2326,20 +2475,20 @@ static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...) strftime(buff, 256, _("%d days %H hours %M minutes"), &idletime); imcb_log(ic, "%s: %s", _("Idle Time"), buff); } - - if(text) { + + if (text) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); imcb_log(ic, "%s\n%s", _("User Info"), utf8); } else { imcb_log(ic, _("No user info available.")); } - } else if(infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { + } else if (infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) { utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length); imcb_log(ic, "%s\n%s", _("Away Message"), utf8); } g_free(utf8); - + return 1; } @@ -2355,48 +2504,50 @@ int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...) sn = va_arg(ap, char*); type2 = va_arg(ap, int); va_end(ap); - - if(type2 == 0x0002) { + + if (type2 == 0x0002) { /* User is typing */ imcb_buddy_typing(ic, normalize(sn), OPT_TYPING); - } - else if (type2 == 0x0001) { + } else if (type2 == 0x0001) { /* User has typed something, but is not actively typing (stale) */ imcb_buddy_typing(ic, normalize(sn), OPT_THINKING); - } - else { + } else { /* User has stopped typing */ imcb_buddy_typing(ic, normalize(sn), 0); } - + return 1; } int oscar_send_typing(struct im_connection *ic, char * who, int typing) { struct oscar_data *od = ic->proto_data; - return( aim_im_sendmtn(od->sess, 1, who, (typing & OPT_TYPING) ? 0x0002 : 0x0000) ); + + return(aim_im_sendmtn(od->sess, 1, who, (typing & OPT_TYPING) ? 0x0002 : 0x0000)); } void oscar_chat_msg(struct groupchat *c, char *message, int msgflags) { struct im_connection *ic = c->ic; - struct oscar_data * od = (struct oscar_data*)ic->proto_data; + struct oscar_data * od = (struct oscar_data*) ic->proto_data; struct chat_connection * ccon; int ret; guint8 len = strlen(message); guint16 flags; char *s; - - if (!(ccon = c->data)) + + if (!(ccon = c->data)) { return; - - for (s = message; *s; s++) - if (*s & 128) + } + + for (s = message; *s; s++) { + if (*s & 128) { break; - + } + } + flags = AIM_CHATFLAGS_NOREFLECT; - + /* Message contains high ASCII chars, time for some translation! */ if (*s) { s = g_malloc(BUF_LONG); @@ -2410,46 +2561,48 @@ void oscar_chat_msg(struct groupchat *c, char *message, int msgflags) len = ret; } else { /* OOF, translation failed... Oh well.. */ - g_free( s ); + g_free(s); s = message; } } else { s = message; } - + ret = aim_chat_send_im(od->sess, ccon->conn, flags, s, len); - - if (s != message) { + + if (s != message) { g_free(s); - } - + } + /* return (ret >= 0); */ } void oscar_chat_invite(struct groupchat *c, char *who, char *message) { struct im_connection *ic = c->ic; - struct oscar_data * od = (struct oscar_data *)ic->proto_data; + struct oscar_data * od = (struct oscar_data *) ic->proto_data; struct chat_connection *ccon; - - if (!(ccon = c->data)) + + if (!(ccon = c->data)) { return; - + } + aim_chat_invite(od->sess, od->conn, who, message ? message : "", - ccon->exchange, ccon->name, 0x0); + ccon->exchange, ccon->name, 0x0); } void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc) { - struct oscar_data *od = (struct oscar_data *)ic->proto_data; + struct oscar_data *od = (struct oscar_data *) ic->proto_data; /* Notify the conversation window that we've left the chat */ imcb_chat_free(cc->cnv); /* Destroy the chat_connection */ od->oscar_chats = g_slist_remove(od->oscar_chats, cc); - if (cc->inpa > 0) + if (cc->inpa > 0) { b_event_remove(cc->inpa); + } aim_conn_kill(od->sess, &cc->conn); g_free(cc->name); g_free(cc->show); @@ -2458,66 +2611,69 @@ void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc) void oscar_chat_leave(struct groupchat *c) { - if (!c->data) + if (!c->data) { return; + } oscar_chat_kill(c->ic, c->data); } struct groupchat *oscar_chat_join_internal(struct im_connection *ic, const char *room, - const char *nick, const char *password, int exchange_number) + const char *nick, const char *password, int exchange_number) { - struct oscar_data * od = (struct oscar_data *)ic->proto_data; + struct oscar_data * od = (struct oscar_data *) ic->proto_data; struct groupchat *ret = imcb_chat_new(ic, room); aim_conn_t * cur; - if((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) { + if ((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) { aim_chatnav_createroom(od->sess, cur, room, exchange_number); - + return ret; } else { struct create_room * cr = g_new0(struct create_room, 1); - + cr->exchange = exchange_number; cr->name = g_strdup(room); od->create_rooms = g_slist_append(od->create_rooms, cr); aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_CHATNAV); - + return ret; } } struct groupchat *oscar_chat_join(struct im_connection *ic, const char *room, - const char *nick, const char *password, set_t **sets) + const char *nick, const char *password, set_t **sets) { return oscar_chat_join_internal(ic, room, nick, password, set_getint(sets, "exchange_number")); } struct groupchat *oscar_chat_with(struct im_connection * ic, char *who) { - struct oscar_data * od = (struct oscar_data *)ic->proto_data; + struct oscar_data * od = (struct oscar_data *) ic->proto_data; struct groupchat *ret; static int chat_id = 0; char * chatname, *s; - + chatname = g_strdup_printf("%s%s%d", g_ascii_isdigit(*ic->acc->user) ? "icq" : "", ic->acc->user, chat_id++); - - for (s = chatname; *s; s ++) - if (!g_ascii_isalnum(*s)) + + for (s = chatname; *s; s++) { + if (!g_ascii_isalnum(*s)) { *s = '0'; - + } + } + ret = oscar_chat_join_internal(ic, chatname, NULL, NULL, 4); aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0); g_free(chatname); - + return ret; } void oscar_accept_chat(void *data) { struct aim_chat_invitation * inv = data; - + oscar_chat_join_internal(inv->ic, inv->name, NULL, NULL, 4); g_free(inv->name); g_free(inv); @@ -2526,7 +2682,7 @@ void oscar_accept_chat(void *data) void oscar_reject_chat(void *data) { struct aim_chat_invitation * inv = data; - + g_free(inv->name); g_free(inv); } @@ -2541,11 +2697,12 @@ void oscar_chat_free_settings(account_t *acc, set_t **head) set_del(head, "exchange_number"); } -void oscar_initmodule() +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->mms = 2343; /* this guess taken from libotr UPGRADING file */ ret->away_states = oscar_away_states; ret->init = oscar_init; ret->login = oscar_login; @@ -2569,7 +2726,7 @@ void oscar_initmodule() ret->rem_permit = oscar_rem_permit; ret->rem_deny = oscar_rem_deny; ret->send_typing = oscar_send_typing; - + ret->handle_cmp = aim_sncmp; register_protocol(ret); diff --git a/protocols/oscar/oscar_util.c b/protocols/oscar/oscar_util.c index 806632ff..c2ce8e4d 100644 --- a/protocols/oscar/oscar_util.c +++ b/protocols/oscar/oscar_util.c @@ -3,9 +3,9 @@ /* * int snlen(const char *) -* +* * This takes a screen name and returns its length without -* spaces. If there are no spaces in the SN, then the +* spaces. If there are no spaces in the SN, then the * return is equal to that of strlen(). * */ @@ -14,13 +14,15 @@ static int aim_snlen(const char *sn) int i = 0; const char *curPtr = NULL; - if (!sn) + if (!sn) { return 0; + } curPtr = sn; - while ( (*curPtr) != (char) '\0') { - if ((*curPtr) != ' ') - i++; + while ((*curPtr) != (char) '\0') { + if ((*curPtr) != ' ') { + i++; + } curPtr++; } @@ -44,28 +46,33 @@ int aim_sncmp(const char *sn1, const char *sn2) { const char *curPtr1 = NULL, *curPtr2 = NULL; - if (aim_snlen(sn1) != aim_snlen(sn2)) + if (aim_snlen(sn1) != aim_snlen(sn2)) { return 1; + } curPtr1 = sn1; curPtr2 = sn2; - while ( (*curPtr1 != (char) '\0') && (*curPtr2 != (char) '\0') ) { - if ( (*curPtr1 == ' ') || (*curPtr2 == ' ') ) { - if (*curPtr1 == ' ') + while ((*curPtr1 != (char) '\0') && (*curPtr2 != (char) '\0')) { + if ((*curPtr1 == ' ') || (*curPtr2 == ' ')) { + if (*curPtr1 == ' ') { curPtr1++; - if (*curPtr2 == ' ') + } + if (*curPtr2 == ' ') { curPtr2++; + } } else { - if ( g_ascii_toupper(*curPtr1) != g_ascii_toupper(*curPtr2)) + if (g_ascii_toupper(*curPtr1) != g_ascii_toupper(*curPtr2)) { return 1; + } curPtr1++; curPtr2++; } } /* Should both be NULL */ - if (*curPtr1 != *curPtr2) + if (*curPtr1 != *curPtr2) { return 1; + } return 0; } diff --git a/protocols/oscar/rxhandlers.c b/protocols/oscar/rxhandlers.c index bd071505..9ca2764a 100644 --- a/protocols/oscar/rxhandlers.c +++ b/protocols/oscar/rxhandlers.c @@ -21,9 +21,10 @@ aim_module_t *aim__findmodulebygroup(aim_session_t *sess, guint16 group) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { - if (cur->family == group) + for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) { + if (cur->family == group) { return cur; + } } return NULL; @@ -33,9 +34,10 @@ static aim_module_t *aim__findmodule(aim_session_t *sess, const char *name) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { - if (strcmp(name, cur->name) == 0) + for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) { + if (strcmp(name, cur->name) == 0) { return cur; + } } return NULL; @@ -45,11 +47,13 @@ int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, ai { aim_module_t *mod; - if (!sess || !modfirst) + if (!sess || !modfirst) { return -1; + } - if (!(mod = g_new0(aim_module_t,1))) + if (!(mod = g_new0(aim_module_t, 1))) { return -1; + } if (modfirst(sess, mod) == -1) { g_free(mod); @@ -57,13 +61,14 @@ int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, ai } if (aim__findmodule(sess, mod->name)) { - if (mod->shutdown) + if (mod->shutdown) { mod->shutdown(sess, mod); + } g_free(mod); return -1; } - mod->next = (aim_module_t *)sess->modlistv; + mod->next = (aim_module_t *) sess->modlistv; sess->modlistv = mod; @@ -74,13 +79,14 @@ void aim__shutdownmodules(aim_session_t *sess) { aim_module_t *cur; - for (cur = (aim_module_t *)sess->modlistv; cur; ) { + for (cur = (aim_module_t *) sess->modlistv; cur; ) { aim_module_t *tmp; tmp = cur->next; - if (cur->shutdown) + if (cur->shutdown) { cur->shutdown(sess, cur); + } g_free(cur); @@ -97,8 +103,9 @@ static int consumesnac(aim_session_t *sess, aim_frame_t *rx) aim_module_t *cur; aim_modsnac_t snac; - if (aim_bstream_empty(&rx->data) < 10) + if (aim_bstream_empty(&rx->data) < 10) { return 0; + } snac.family = aimbs_get16(&rx->data); snac.subtype = aimbs_get16(&rx->data); @@ -106,20 +113,22 @@ static int consumesnac(aim_session_t *sess, aim_frame_t *rx) snac.id = aimbs_get32(&rx->data); /* Contains TLV(s) in the FNAC header */ - if(snac.flags & 0x8000) { + if (snac.flags & 0x8000) { aim_bstream_advance(&rx->data, aimbs_get16(&rx->data)); - } else if(snac.flags & 0x0001) { + } else if (snac.flags & 0x0001) { /* Following SNAC will be related */ } - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { + for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) { - if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && - (cur->family != snac.family)) + if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && + (cur->family != snac.family)) { continue; + } - if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) + if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) { return 1; + } } @@ -135,14 +144,16 @@ static int consumenonsnac(aim_session_t *sess, aim_frame_t *rx, guint16 family, snac.subtype = subtype; snac.flags = snac.id = 0; - for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) { + for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) { - if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && - (cur->family != snac.family)) + if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && + (cur->family != snac.family)) { continue; + } - if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) + if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) { return 1; + } } @@ -164,19 +175,23 @@ static int negchan_middle(aim_session_t *sess, aim_frame_t *fr) /* Used only by the older login protocol */ /* XXX remove this special case? */ - if (fr->conn->type == AIM_CONN_TYPE_AUTH) + if (fr->conn->type == AIM_CONN_TYPE_AUTH) { return consumenonsnac(sess, fr, 0x0017, 0x0003); + } tlvlist = aim_readtlvchain(&fr->data); - if (aim_gettlv(tlvlist, 0x0009, 1)) + if (aim_gettlv(tlvlist, 0x0009, 1)) { code = aim_gettlv16(tlvlist, 0x0009, 1); + } - if (aim_gettlv(tlvlist, 0x000b, 1)) + if (aim_gettlv(tlvlist, 0x000b, 1)) { msg = aim_gettlv_str(tlvlist, 0x000b, 1); + } - if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) + if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) { ret = userfunc(sess, fr, code, msg); + } aim_freetlvchain(&tlvlist); @@ -194,39 +209,43 @@ static int checkdisallowed(guint16 group, guint16 type) guint16 group; guint16 type; } dontuse[] = { - {0x0001, 0x0002}, - {0x0001, 0x0003}, - {0x0001, 0x0006}, - {0x0001, 0x0007}, - {0x0001, 0x0008}, - {0x0001, 0x0017}, - {0x0001, 0x0018}, - {0x0000, 0x0000} + { 0x0001, 0x0002 }, + { 0x0001, 0x0003 }, + { 0x0001, 0x0006 }, + { 0x0001, 0x0007 }, + { 0x0001, 0x0008 }, + { 0x0001, 0x0017 }, + { 0x0001, 0x0018 }, + { 0x0000, 0x0000 } }; int i; for (i = 0; dontuse[i].group != 0x0000; i++) { - if ((dontuse[i].group == group) && (dontuse[i].type == type)) + if ((dontuse[i].group == group) && (dontuse[i].type == type)) { return 1; + } } return 0; } -int aim_conn_addhandler(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type, aim_rxcallback_t newhandler, guint16 flags) +int aim_conn_addhandler(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type, + aim_rxcallback_t newhandler, guint16 flags) { struct aim_rxcblist_s *newcb; - if (!conn) + if (!conn) { return -1; + } if (checkdisallowed(family, type)) { g_assert(0); return -1; } - if (!(newcb = (struct aim_rxcblist_s *)g_new0(struct aim_rxcblist_s, 1))) + if (!(newcb = (struct aim_rxcblist_s *) g_new0(struct aim_rxcblist_s, 1))) { return -1; + } newcb->family = family; newcb->type = type; @@ -234,13 +253,14 @@ int aim_conn_addhandler(aim_session_t *sess, aim_conn_t *conn, guint16 family, g newcb->handler = newhandler; newcb->next = NULL; - if (!conn->handlerlist) - conn->handlerlist = (void *)newcb; - else { + if (!conn->handlerlist) { + conn->handlerlist = (void *) newcb; + } else { struct aim_rxcblist_s *cur; - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur->next; cur = cur->next) + for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur->next; cur = cur->next) { ; + } cur->next = newcb; } @@ -251,10 +271,11 @@ int aim_clearhandlers(aim_conn_t *conn) { struct aim_rxcblist_s *cur; - if (!conn) + if (!conn) { return -1; + } - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; ) { + for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur; ) { struct aim_rxcblist_s *tmp; tmp = cur->next; @@ -270,12 +291,14 @@ aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, guint16 { struct aim_rxcblist_s *cur; - if (!conn) + if (!conn) { return NULL; + } - for (cur = (struct aim_rxcblist_s *)conn->handlerlist; cur; cur = cur->next) { - if ((cur->family == family) && (cur->type == type)) + for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur; cur = cur->next) { + if ((cur->family == family) && (cur->type == type)) { return cur->handler; + } } if (type == AIM_CB_SPECIAL_DEFAULT) { @@ -285,12 +308,14 @@ aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, guint16 return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT); } -static int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn,guint16 family, guint16 type, aim_frame_t *ptr) +static int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type, + aim_frame_t *ptr) { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, conn, family, type))) + if ((userfunc = aim_callhandler(sess, conn, family, type))) { return userfunc(sess, ptr); + } return 1; /* XXX */ } @@ -321,35 +346,39 @@ void aim_rxdispatch(aim_session_t *sess) * XXX: This is still fairly ugly. */ - if (cur->handled) + if (cur->handled) { continue; + } if (cur->hdr.flap.type == 0x01) { - - cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, cur); /* XXX use consumenonsnac */ - + + cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL, + AIM_CB_SPECIAL_FLAPVER, cur); /* XXX use consumenonsnac */ + continue; - + } else if (cur->hdr.flap.type == 0x02) { - if ((cur->handled = consumesnac(sess, cur))) + if ((cur->handled = consumesnac(sess, cur))) { continue; + } } else if (cur->hdr.flap.type == 0x04) { cur->handled = negchan_middle(sess, cur); continue; - } else if (cur->hdr.flap.type == 0x05) + } else if (cur->hdr.flap.type == 0x05) { ; - + } + if (!cur->handled) { consumenonsnac(sess, cur, 0xffff, 0xffff); /* last chance! */ cur->handled = 1; } } - /* + /* * This doesn't have to be called here. It could easily be done * by a seperate thread or something. It's an administrative operation, * and can take a while. Though the less you call it the less memory diff --git a/protocols/oscar/rxqueue.c b/protocols/oscar/rxqueue.c index 9ac8466e..e5c52376 100644 --- a/protocols/oscar/rxqueue.c +++ b/protocols/oscar/rxqueue.c @@ -6,7 +6,7 @@ * aim_rxhandlers.c. */ -#include <aim.h> +#include <aim.h> #include <sys/socket.h> @@ -15,16 +15,17 @@ */ int aim_recv(int fd, void *buf, size_t count) { - int left, cur; + int left, cur; for (cur = 0, left = count; left; ) { int ret; - - ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); + + ret = recv(fd, ((unsigned char *) buf) + cur, left, 0); /* Of course EOF is an error, only morons disagree with that. */ - if (ret <= 0) + if (ret <= 0) { return -1; + } cur += ret; left -= ret; @@ -41,18 +42,21 @@ static int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count) { int red = 0; - if (!bs || (fd < 0) || (count < 0)) + if (!bs || (fd < 0) || (count < 0)) { return -1; - - if (count > (bs->len - bs->offset)) + } + + if (count > (bs->len - bs->offset)) { count = bs->len - bs->offset; /* truncate to remaining space */ + } if (count) { red = aim_recv(fd, bs->data + bs->offset, count); - if (red <= 0) + if (red <= 0) { return -1; + } } bs->offset += red; @@ -62,9 +66,10 @@ static int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count) int aim_bstream_init(aim_bstream_t *bs, guint8 *data, int len) { - - if (!bs) + + if (!bs) { return -1; + } bs->data = data; bs->len = len; @@ -86,8 +91,9 @@ int aim_bstream_curpos(aim_bstream_t *bs) int aim_bstream_setpos(aim_bstream_t *bs, int off) { - if (off > bs->len) + if (off > bs->len) { return -1; + } bs->offset = off; @@ -105,9 +111,10 @@ void aim_bstream_rewind(aim_bstream_t *bs) int aim_bstream_advance(aim_bstream_t *bs, int n) { - if (aim_bstream_empty(bs) < n) + if (aim_bstream_empty(bs) < n) { return 0; /* XXX throw an exception */ + } bs->offset += n; return n; @@ -115,76 +122,83 @@ int aim_bstream_advance(aim_bstream_t *bs, int n) guint8 aimbs_get8(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 1) + + if (aim_bstream_empty(bs) < 1) { return 0; /* XXX throw an exception */ - + + } bs->offset++; - + return aimutil_get8(bs->data + bs->offset - 1); } guint16 aimbs_get16(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 2) + + if (aim_bstream_empty(bs) < 2) { return 0; /* XXX throw an exception */ - + + } bs->offset += 2; - + return aimutil_get16(bs->data + bs->offset - 2); } guint32 aimbs_get32(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 4) + + if (aim_bstream_empty(bs) < 4) { return 0; /* XXX throw an exception */ - + + } bs->offset += 4; - + return aimutil_get32(bs->data + bs->offset - 4); } guint8 aimbs_getle8(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 1) + + if (aim_bstream_empty(bs) < 1) { return 0; /* XXX throw an exception */ - + + } bs->offset++; - + return aimutil_getle8(bs->data + bs->offset - 1); } guint16 aimbs_getle16(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 2) + + if (aim_bstream_empty(bs) < 2) { return 0; /* XXX throw an exception */ - + + } bs->offset += 2; - + return aimutil_getle16(bs->data + bs->offset - 2); } guint32 aimbs_getle32(aim_bstream_t *bs) { - - if (aim_bstream_empty(bs) < 4) + + if (aim_bstream_empty(bs) < 4) { return 0; /* XXX throw an exception */ - + + } bs->offset += 4; - + return aimutil_getle32(bs->data + bs->offset - 4); } int aimbs_put8(aim_bstream_t *bs, guint8 v) { - if (aim_bstream_empty(bs) < 1) + if (aim_bstream_empty(bs) < 1) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_put8(bs->data + bs->offset, v); return 1; @@ -193,9 +207,10 @@ int aimbs_put8(aim_bstream_t *bs, guint8 v) int aimbs_put16(aim_bstream_t *bs, guint16 v) { - if (aim_bstream_empty(bs) < 2) + if (aim_bstream_empty(bs) < 2) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_put16(bs->data + bs->offset, v); return 2; @@ -204,9 +219,10 @@ int aimbs_put16(aim_bstream_t *bs, guint16 v) int aimbs_put32(aim_bstream_t *bs, guint32 v) { - if (aim_bstream_empty(bs) < 4) + if (aim_bstream_empty(bs) < 4) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_put32(bs->data + bs->offset, v); return 1; @@ -215,9 +231,10 @@ int aimbs_put32(aim_bstream_t *bs, guint32 v) int aimbs_putle8(aim_bstream_t *bs, guint8 v) { - if (aim_bstream_empty(bs) < 1) + if (aim_bstream_empty(bs) < 1) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_putle8(bs->data + bs->offset, v); return 1; @@ -226,9 +243,10 @@ int aimbs_putle8(aim_bstream_t *bs, guint8 v) int aimbs_putle16(aim_bstream_t *bs, guint16 v) { - if (aim_bstream_empty(bs) < 2) + if (aim_bstream_empty(bs) < 2) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_putle16(bs->data + bs->offset, v); return 2; @@ -237,9 +255,10 @@ int aimbs_putle16(aim_bstream_t *bs, guint16 v) int aimbs_putle32(aim_bstream_t *bs, guint32 v) { - if (aim_bstream_empty(bs) < 4) + if (aim_bstream_empty(bs) < 4) { return 0; /* XXX throw an exception */ + } bs->offset += aimutil_putle32(bs->data + bs->offset, v); return 1; @@ -248,8 +267,9 @@ int aimbs_putle32(aim_bstream_t *bs, guint32 v) int aimbs_getrawbuf(aim_bstream_t *bs, guint8 *buf, int len) { - if (aim_bstream_empty(bs) < len) + if (aim_bstream_empty(bs) < len) { return 0; + } memcpy(buf, bs->data + bs->offset, len); bs->offset += len; @@ -261,8 +281,9 @@ guint8 *aimbs_getraw(aim_bstream_t *bs, int len) { guint8 *ob; - if (!(ob = g_malloc(len))) + if (!(ob = g_malloc(len))) { return NULL; + } if (aimbs_getrawbuf(bs, ob, len) < len) { g_free(ob); @@ -276,25 +297,27 @@ char *aimbs_getstr(aim_bstream_t *bs, int len) { guint8 *ob; - if (!(ob = g_malloc(len+1))) + if (!(ob = g_malloc(len + 1))) { return NULL; + } if (aimbs_getrawbuf(bs, ob, len) < len) { g_free(ob); return NULL; } - + ob[len] = '\0'; - return (char *)ob; + return (char *) ob; } int aimbs_putraw(aim_bstream_t *bs, const guint8 *v, int len) { - if (aim_bstream_empty(bs) < len) + if (aim_bstream_empty(bs) < len) { return 0; /* XXX throw an exception */ + } memcpy(bs->data + bs->offset, v, len); bs->offset += len; @@ -304,12 +327,14 @@ int aimbs_putraw(aim_bstream_t *bs, const guint8 *v, int len) int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len) { - if (aim_bstream_empty(srcbs) < len) + if (aim_bstream_empty(srcbs) < len) { return 0; /* XXX throw exception (underrun) */ - if (aim_bstream_empty(bs) < len) + } + if (aim_bstream_empty(bs) < len) { return 0; /* XXX throw exception (overflow) */ + } memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len); bs->offset += len; srcbs->offset += len; @@ -318,10 +343,10 @@ int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len) } /** - * aim_frame_destroy - free aim_frame_t - * @frame: the frame to free + * aim_frame_destroy - free aim_frame_t + * @frame: the frame to free * - * returns -1 on error; 0 on success. + * returns -1 on error; 0 on success. * */ void aim_frame_destroy(aim_frame_t *frame) @@ -330,7 +355,7 @@ void aim_frame_destroy(aim_frame_t *frame) g_free(frame->data.data); /* XXX aim_bstream_free */ g_free(frame); -} +} /* @@ -343,34 +368,37 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) aim_bstream_t flaphdr; aim_frame_t *newrx; guint16 payloadlen; - - if (!sess || !conn) + + if (!sess || !conn) { return 0; + } - if (conn->fd == -1) + if (conn->fd == -1) { return -1; /* its a aim_conn_close()'d connection */ + } /* KIDS, THIS IS WHAT HAPPENS IF YOU USE CODE WRITTEN FOR GUIS IN A DAEMON! - + And wouldn't it make sense to return something that prevents this function from being called again IMMEDIATELY (and making the program suck up all CPU time)?... - + if (conn->fd < 3) - return 0; + return 0; */ - if (conn->status & AIM_CONN_STATUS_INPROGRESS) + if (conn->status & AIM_CONN_STATUS_INPROGRESS) { return aim_conn_completeconnect(sess, conn); + } aim_bstream_init(&flaphdr, flaphdr_raw, sizeof(flaphdr_raw)); /* * Read FLAP header. Six bytes: - * + * * 0 char -- Always 0x2a * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login. - * 2 short -- Sequence number + * 2 short -- Sequence number * 4 short -- Number of data bytes that follow. */ if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) { @@ -390,15 +418,16 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) imcb_error(sess->aux_data, "FLAP framing disrupted"); aim_conn_close(conn); return -1; - } + } /* allocate a new struct */ - if (!(newrx = (aim_frame_t *)g_new0(aim_frame_t,1))) + if (!(newrx = (aim_frame_t *) g_new0(aim_frame_t, 1))) { return -1; + } /* we're doing FLAP if we're here */ newrx->hdrtype = AIM_FRAMETYPE_FLAP; - + newrx->hdr.flap.type = aimbs_get8(&flaphdr); newrx->hdr.flap.seqnum = aimbs_get16(&flaphdr); payloadlen = aimbs_get16(&flaphdr); @@ -421,8 +450,9 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) aim_conn_close(conn); return -1; } - } else + } else { aim_bstream_init(&newrx->data, NULL, 0); + } aim_bstream_rewind(&newrx->data); @@ -431,27 +461,28 @@ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) newrx->next = NULL; /* this will always be at the bottom */ - if (!sess->queue_incoming) + if (!sess->queue_incoming) { sess->queue_incoming = newrx; - else { + } else { aim_frame_t *cur; - for (cur = sess->queue_incoming; cur->next; cur = cur->next) + for (cur = sess->queue_incoming; cur->next; cur = cur->next) { ; + } cur->next = newrx; } newrx->conn->lastactivity = time(NULL); - return 0; + return 0; } /* * Purge recieve queue of all handled commands (->handled==1). Also * allows for selective freeing using ->nofree so that the client can - * keep the data for various purposes. + * keep the data for various purposes. * - * If ->nofree is nonzero, the frame will be delinked from the global list, + * If ->nofree is nonzero, the frame will be delinked from the global list, * but will not be free'ed. The client _must_ keep a pointer to the * data -- libfaim will not! If the client marks ->nofree but * does not keep a pointer, it's lost forever. @@ -465,12 +496,14 @@ void aim_purge_rxqueue(aim_session_t *sess) if (cur->handled) { *prev = cur->next; - - if (!cur->nofree) + + if (!cur->nofree) { aim_frame_destroy(cur); + } - } else + } else { prev = &cur->next; + } } return; @@ -488,9 +521,10 @@ void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn) aim_frame_t *currx; for (currx = sess->queue_incoming; currx; currx = currx->next) { - if ((!currx->handled) && (currx->conn == conn)) + if ((!currx->handled) && (currx->conn == conn)) { currx->handled = 1; - } + } + } return; } diff --git a/protocols/oscar/search.c b/protocols/oscar/search.c index 4e0d3858..30d392ae 100644 --- a/protocols/oscar/search.c +++ b/protocols/oscar/search.c @@ -21,12 +21,14 @@ static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo return 0; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, snac2->data /* address */); + } /* XXX freesnac()? */ - if (snac2) + if (snac2) { g_free(snac2->data); + } g_free(snac2); return ret; @@ -41,30 +43,33 @@ static int reply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo aim_snac_t *snac2; char *searchaddr = NULL; - if ((snac2 = aim_remsnac(sess, snac->id))) - searchaddr = (char *)snac2->data; + if ((snac2 = aim_remsnac(sess, snac->id))) { + searchaddr = (char *) snac2->data; + } tlvlist = aim_readtlvchain(bs); m = aim_counttlvchain(&tlvlist); /* XXX uhm. */ - while ((cur = aim_gettlv_str(tlvlist, 0x0001, j+1)) && j < m) { - buf = g_realloc(buf, (j+1) * (MAXSNLEN+1)); + while ((cur = aim_gettlv_str(tlvlist, 0x0001, j + 1)) && j < m) { + buf = g_realloc(buf, (j + 1) * (MAXSNLEN + 1)); - strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN); + strncpy(&buf[j * (MAXSNLEN + 1)], cur, MAXSNLEN); g_free(cur); - j++; + j++; } aim_freetlvchain(&tlvlist); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, searchaddr, j, buf); + } /* XXX freesnac()? */ - if (snac2) + if (snac2) { g_free(snac2->data); + } g_free(snac2); g_free(buf); @@ -75,10 +80,11 @@ static int reply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mo static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0001) + if (snac->subtype == 0x0001) { return error(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0003) + } else if (snac->subtype == 0x0003) { return reply(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/service.c b/protocols/oscar/service.c index a3b37c33..673cc5ad 100644 --- a/protocols/oscar/service.c +++ b/protocols/oscar/service.c @@ -10,23 +10,25 @@ /* Client Online (group 1, subtype 2) */ int aim_clientready(aim_session_t *sess, aim_conn_t *conn) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside; struct snacgroup *sg; aim_frame_t *fr; aim_snacid_t snacid; - if (!ins) + if (!ins) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid); /* * Send only the tool versions that the server cares about (that it - * marked as supporting in the server ready SNAC). + * marked as supporting in the server ready SNAC). */ for (sg = ins->groups; sg; sg = sg->next) { aim_module_t *mod; @@ -36,7 +38,7 @@ int aim_clientready(aim_session_t *sess, aim_conn_t *conn) aimbs_put16(&fr->data, mod->version); aimbs_put16(&fr->data, mod->toolid); aimbs_put16(&fr->data, mod->toolversion); - } + } } aim_tx_enqueue(sess, fr); @@ -46,7 +48,7 @@ int aim_clientready(aim_session_t *sess, aim_conn_t *conn) /* * Host Online (group 1, type 3) - * + * * See comments in conn.c about how the group associations are supposed * to work, and how they really work. * @@ -54,9 +56,9 @@ int aim_clientready(aim_session_t *sess, aim_conn_t *conn) * * We don't actually call the client here. This starts off the connection * initialization routine required by all AIM connections. The next time - * the client is called is the CONNINITDONE callback, which should be + * the client is called is the CONNINITDONE callback, which should be * shortly after the rate information is acknowledged. - * + * */ static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { @@ -64,8 +66,9 @@ static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a int famcount; - if (!(families = g_malloc(aim_bstream_empty(bs)))) + if (!(families = g_malloc(aim_bstream_empty(bs)))) { return 0; + } for (famcount = 0; aim_bstream_empty(bs); famcount++) { families[famcount] = aimbs_get16(bs); @@ -85,7 +88,7 @@ static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a */ aim_setversions(sess, rx->conn); - return 1; + return 1; } /* Service request (group 1, type 4) */ @@ -108,35 +111,37 @@ static int redirect(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim tlvlist = aim_readtlvchain(bs); if (!aim_gettlv(tlvlist, 0x000d, 1) || - !aim_gettlv(tlvlist, 0x0005, 1) || - !aim_gettlv(tlvlist, 0x0006, 1)) { + !aim_gettlv(tlvlist, 0x0005, 1) || + !aim_gettlv(tlvlist, 0x0006, 1)) { aim_freetlvchain(&tlvlist); return 0; } redir.group = aim_gettlv16(tlvlist, 0x000d, 1); redir.ip = aim_gettlv_str(tlvlist, 0x0005, 1); - redir.cookie = (guint8 *)aim_gettlv_str(tlvlist, 0x0006, 1); + redir.cookie = (guint8 *) aim_gettlv_str(tlvlist, 0x0006, 1); /* Fetch original SNAC so we can get csi if needed */ origsnac = aim_remsnac(sess, snac->id); if ((redir.group == AIM_CONN_TYPE_CHAT) && origsnac) { - struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data; + struct chatsnacinfo *csi = (struct chatsnacinfo *) origsnac->data; redir.chat.exchange = csi->exchange; redir.chat.room = csi->name; redir.chat.instance = csi->instance; } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, &redir); + } - g_free((void *)redir.ip); - g_free((void *)redir.cookie); + g_free((void *) redir.ip); + g_free((void *) redir.cookie); - if (origsnac) + if (origsnac) { g_free(origsnac->data); + } g_free(origsnac); aim_freetlvchain(&tlvlist); @@ -156,7 +161,7 @@ int aim_reqrates(aim_session_t *sess, aim_conn_t *conn) * level, etc), and a set of SNAC family/type pairs associated with * it. The rate classes, their limiting properties, and the definitions * of which SNACs are belong to which class, are defined in the - * Rate Response packet at login to each host. + * Rate Response packet at login to each host. * * Logically, all rate offenses within one class count against further * offenses for other SNACs in the same class (ie, sending messages @@ -170,10 +175,10 @@ int aim_reqrates(aim_session_t *sess, aim_conn_t *conn) * members as follows... * * Rate class 0x0001: - * - Everything thats not in any of the other classes + * - Everything thats not in any of the other classes * * Rate class 0x0002: - * - Buddy list add/remove + * - Buddy list add/remove * - Permit list add/remove * - Deny list add/remove * @@ -189,32 +194,35 @@ int aim_reqrates(aim_session_t *sess, aim_conn_t *conn) * - Outgoing chat ICBMs * * The only other thing of note is that class 5 (chat) has slightly looser - * limiting properties than class 3 (normal messages). But thats just a + * limiting properties than class 3 (normal messages). But thats just a * small bit of trivia for you. * * The last thing that needs to be learned about the rate limiting * system is how the actual numbers relate to the passing of time. This * seems to be a big mystery. - * + * */ static void rc_addclass(struct rateclass **head, struct rateclass *inrc) { struct rateclass *rc, *rc2; - if (!(rc = g_malloc(sizeof(struct rateclass)))) + if (!(rc = g_malloc(sizeof(struct rateclass)))) { return; + } memcpy(rc, inrc, sizeof(struct rateclass)); rc->next = NULL; - for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next) + for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next) { ; + } - if (!rc2) + if (!rc2) { *head = rc; - else + } else { rc2->next = rc; + } return; } @@ -224,8 +232,9 @@ static struct rateclass *rc_findclass(struct rateclass **head, guint16 id) struct rateclass *rc; for (rc = *head; rc; rc = rc->next) { - if (rc->classid == id) + if (rc->classid == id) { return rc; + } } return NULL; @@ -235,20 +244,23 @@ static void rc_addpair(struct rateclass *rc, guint16 group, guint16 type) { struct snacpair *sp, *sp2; - if (!(sp = g_new0(struct snacpair, 1))) + if (!(sp = g_new0(struct snacpair, 1))) { return; + } sp->group = group; sp->subtype = type; sp->next = NULL; - for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next) + for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next) { ; + } - if (!sp2) + if (!sp2) { rc->members = sp; - else + } else { sp2->next = sp; + } return; } @@ -256,7 +268,7 @@ static void rc_addpair(struct rateclass *rc, guint16 group, guint16 type) /* Rate Parameters (group 1, type 7) */ static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)rx->conn->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *) rx->conn->inside; guint16 numclasses, i; aim_rxcallback_t userfunc; @@ -283,11 +295,12 @@ static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim * The server will send an extra five bytes of parameters * depending on the version we advertised in 1/17. If we * didn't send 1/17 (evil!), then this will crash and you - * die, as it will default to the old version but we have - * the new version hardcoded here. + * die, as it will default to the old version but we have + * the new version hardcoded here. */ - if (mod->version >= 3) + if (mod->version >= 3) { aimbs_getrawbuf(bs, rc.unknown, sizeof(rc.unknown)); + } rc_addclass(&ins->rates, &rc); } @@ -311,8 +324,9 @@ static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim group = aimbs_get16(bs); subtype = aimbs_get16(bs); - if (rc) + if (rc) { rc_addpair(rc, group, subtype); + } } } @@ -331,8 +345,9 @@ static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim /* * Finally, tell the client it's ready to go... */ - if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) + if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) { userfunc(sess, rx); + } return 1; @@ -341,19 +356,21 @@ static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim /* Add Rate Parameter (group 1, type 8) */ int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; - aim_frame_t *fr; + aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside; + aim_frame_t *fr; aim_snacid_t snacid; struct rateclass *rc; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) - return -ENOMEM; + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) { + return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid); - for (rc = ins->rates; rc; rc = rc->next) + for (rc = ins->rates; rc; rc = rc->next) { aimbs_put16(&fr->data, rc->classid); + } aim_tx_enqueue(sess, fr); @@ -369,7 +386,7 @@ static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a code = aimbs_get16(bs); rateclass = aimbs_get16(bs); - + windowsize = aimbs_get32(bs); clear = aimbs_get32(bs); alert = aimbs_get32(bs); @@ -378,19 +395,21 @@ static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a currentavg = aimbs_get32(bs); maxavg = aimbs_get32(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) - return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { + return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, + maxavg); + } return 0; } /* - * How Migrations work. + * How Migrations work. * - * The server sends a Server Pause message, which the client should respond to - * with a Server Pause Ack, which contains the families it needs on this - * connection. The server will send a Migration Notice with an IP address, and - * then disconnect. Next the client should open the connection and send the + * The server sends a Server Pause message, which the client should respond to + * with a Server Pause Ack, which contains the families it needs on this + * connection. The server will send a Migration Notice with an IP address, and + * then disconnect. Next the client should open the connection and send the * cookie. Repeat the normal login process and pretend this never happened. * * The Server Pause contains no data. @@ -402,8 +421,9 @@ static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx); + } return 0; } @@ -413,8 +433,9 @@ static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, { aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx); + } return 0; } @@ -433,8 +454,9 @@ static int selfinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim aim_extractuserinfo(sess, bs, &userinfo); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, &userinfo); + } return 0; } @@ -447,14 +469,16 @@ static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a aim_userinfo_t userinfo; memset(&userinfo, 0, sizeof(aim_userinfo_t)); - + newevil = aimbs_get16(bs); - if (aim_bstream_empty(bs)) + if (aim_bstream_empty(bs)) { aim_extractuserinfo(sess, bs, &userinfo); + } - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, newevil, &userinfo); + } return 0; } @@ -463,7 +487,7 @@ static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a * Service Migrate (group 1, type 0x12) * * This is the final SNAC sent on the original connection during a migration. - * It contains the IP and cookie used to connect to the new server, and + * It contains the IP and cookie used to connect to the new server, and * optionally a list of the SNAC groups being migrated. * */ @@ -481,7 +505,7 @@ static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_ * migration can actually be quite selective about what groups it * moves to the new server. When not all the groups for a connection * are migrated, or they are all migrated but some groups are moved - * to a different server than others, it is called a bifurcated + * to a different server than others, it is called a bifurcated * migration. * * Let's play dumb and not support that. @@ -496,13 +520,15 @@ static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_ tl = aim_readtlvchain(bs); - if (aim_gettlv(tl, 0x0005, 1)) + if (aim_gettlv(tl, 0x0005, 1)) { ip = aim_gettlv_str(tl, 0x0005, 1); + } cktlv = aim_gettlv(tl, 0x0006, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL); + } aim_freetlvchain(&tl); g_free(ip); @@ -527,20 +553,21 @@ static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mod * 2 Advisory upgrade * 3 System bulletin * 4 Nothing's wrong ("top o the world" -- normal) - * 5 Lets-break-something. + * 5 Lets-break-something. * */ id = aimbs_get16(bs); - /* - * TLVs follow + /* + * TLVs follow */ tlvlist = aim_readtlvchain(bs); msg = aim_gettlv_str(tlvlist, 0x000b, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, id, msg); + } g_free(msg); @@ -549,7 +576,7 @@ static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_mod return ret; } -/* +/* * Set privacy flags (group 1, type 0x14) * * Normally 0x03. @@ -564,14 +591,14 @@ int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, guint32 flags } -/* - * Set client versions (group 1, subtype 0x17) +/* + * Set client versions (group 1, subtype 0x17) * - * If you've seen the clientonline/clientready SNAC you're probably + * If you've seen the clientonline/clientready SNAC you're probably * wondering what the point of this one is. And that point seems to be * that the versions in the client online SNAC are sent too late for the * server to be able to use them to change the protocol for the earlier - * login packets (client versions are sent right after Host Online is + * login packets (client versions are sent right after Host Online is * received, but client online versions aren't sent until quite a bit later). * We can see them already making use of this by changing the format of * the rate information based on what version of group 1 we advertise here. @@ -579,23 +606,25 @@ int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, guint32 flags */ int aim_setversions(aim_session_t *sess, aim_conn_t *conn) { - aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; + aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside; struct snacgroup *sg; aim_frame_t *fr; aim_snacid_t snacid; - if (!ins) + if (!ins) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid); /* * Send only the versions that the server cares about (that it - * marked as supporting in the server ready SNAC). + * marked as supporting in the server ready SNAC). */ for (sg = ins->groups; sg; sg = sg->next) { aim_module_t *mod; @@ -629,12 +658,12 @@ static int hostversions(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, return 1; } -/* +/* * Subtype 0x001e - Extended Status * * Sets your ICQ status (available, away, do not disturb, etc.) * - * These are the same TLVs seen in user info. You can + * These are the same TLVs seen in user info. You can * also set 0x0008 and 0x000c. */ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status) @@ -646,21 +675,23 @@ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status) struct im_connection *ic = sess ? sess->aux_data : NULL; data = AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */ - - if (ic && set_getbool(&ic->acc->set, "web_aware")) + + if (ic && set_getbool(&ic->acc->set, "web_aware")) { data |= AIM_ICQ_STATE_WEBAWARE; + } aim_addtlvtochain32(&tl, 0x0006, data); /* tlvlen */ - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid); - + aim_writetlvchain(&fr->data, &tl); aim_freetlvchain(&tl); - + aim_tx_enqueue(sess, fr); return 0; @@ -687,14 +718,14 @@ int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status) * If the client does not send any data back, or the data does not match * the data that the specific client should have, the client will get the * following message from "AOL Instant Messenger": - * "You have been disconnected from the AOL Instant Message Service (SM) + * "You have been disconnected from the AOL Instant Message Service (SM) * for accessing the AOL network using unauthorized software. You can - * download a FREE, fully featured, and authorized client, here + * download a FREE, fully featured, and authorized client, here * http://www.aol.com/aim/download2.html" * The connection is then closed, recieving disconnect code 1, URL - * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html. + * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html. * - * Note, however, that numerous inconsistencies can cause the above error, + * Note, however, that numerous inconsistencies can cause the above error, * not just sending back a bad hash. Do not immediatly suspect this code * if you get disconnected. AOL and the open/free software community have * played this game for a couple years now, generating the above message @@ -717,8 +748,9 @@ static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a modname = aim_gettlv_str(list, 0x0001, 1); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, offset, len, modname); + } g_free(modname); aim_freetlvchain(&list); @@ -729,30 +761,31 @@ static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, a static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0003) + if (snac->subtype == 0x0003) { return hostonline(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0005) + } else if (snac->subtype == 0x0005) { return redirect(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0007) + } else if (snac->subtype == 0x0007) { return rateresp(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000a) + } else if (snac->subtype == 0x000a) { return ratechange(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000b) + } else if (snac->subtype == 0x000b) { return serverpause(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000d) + } else if (snac->subtype == 0x000d) { return serverresume(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x000f) + } else if (snac->subtype == 0x000f) { return selfinfo(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0010) + } else if (snac->subtype == 0x0010) { return evilnotify(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0012) + } else if (snac->subtype == 0x0012) { return migrate(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0013) + } else if (snac->subtype == 0x0013) { return motd(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x0018) + } else if (snac->subtype == 0x0018) { return hostversions(sess, mod, rx, snac, bs); - else if (snac->subtype == 0x001f) + } else if (snac->subtype == 0x001f) { return memrequest(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/snac.c b/protocols/oscar/snac.c index 8a75b2a0..d5c4e053 100644 --- a/protocols/oscar/snac.c +++ b/protocols/oscar/snac.c @@ -1,10 +1,10 @@ /* * - * Various SNAC-related dodads... + * Various SNAC-related dodads... * * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added * whenever a new SNAC is sent and it should remain in the list until the - * response for it has been receieved. + * response for it has been receieved. * * cleansnacs() should be called periodically by the client in order * to facilitate the aging out of unreplied-to SNACs. This can and does @@ -23,13 +23,15 @@ void aim_initsnachash(aim_session_t *sess) { int i; - for (i = 0; i < AIM_SNAC_HASH_SIZE; i++) + for (i = 0; i < AIM_SNAC_HASH_SIZE; i++) { sess->snac_hash[i] = NULL; + } return; } -aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen) +aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags, + const void *data, const int datalen) { aim_snac_t snac; @@ -39,11 +41,13 @@ aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guin snac.flags = flags; if (datalen) { - if (!(snac.data = g_malloc(datalen))) + if (!(snac.data = g_malloc(datalen))) { return 0; /* er... */ + } memcpy(snac.data, data, datalen); - } else + } else { snac.data = NULL; + } return aim_newsnac(sess, &snac); } @@ -57,42 +61,45 @@ static aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac) aim_snac_t *snac; int index; - if (!newsnac) + if (!newsnac) { return 0; + } - if (!(snac = g_malloc(sizeof(aim_snac_t)))) + if (!(snac = g_malloc(sizeof(aim_snac_t)))) { return 0; + } memcpy(snac, newsnac, sizeof(aim_snac_t)); snac->issuetime = time(NULL); index = snac->id % AIM_SNAC_HASH_SIZE; - snac->next = (aim_snac_t *)sess->snac_hash[index]; - sess->snac_hash[index] = (void *)snac; + snac->next = (aim_snac_t *) sess->snac_hash[index]; + sess->snac_hash[index] = (void *) snac; return snac->id; } /* - * Finds a snac structure with the passed SNAC ID, + * Finds a snac structure with the passed SNAC ID, * removes it from the list/hash, and returns a pointer to it. * * The returned structure must be freed by the caller. * */ -aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id) +aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id) { aim_snac_t *cur, **prev; int index; index = id % AIM_SNAC_HASH_SIZE; - for (prev = (aim_snac_t **)&sess->snac_hash[index]; (cur = *prev); ) { + for (prev = (aim_snac_t **) &sess->snac_hash[index]; (cur = *prev); ) { if (cur->id == id) { *prev = cur->next; return cur; - } else + } else { prev = &cur->next; + } } return cur; @@ -113,12 +120,13 @@ void aim_cleansnacs(aim_session_t *sess, int maxage) aim_snac_t *cur, **prev; time_t curtime; - if (!sess->snac_hash[i]) + if (!sess->snac_hash[i]) { continue; + } curtime = time(NULL); /* done here in case we waited for the lock */ - for (prev = (aim_snac_t **)&sess->snac_hash[i]; (cur = *prev); ) { + for (prev = (aim_snac_t **) &sess->snac_hash[i]; (cur = *prev); ) { if ((curtime - cur->issuetime) > maxage) { *prev = cur->next; @@ -127,8 +135,9 @@ void aim_cleansnacs(aim_session_t *sess, int maxage) g_free(cur->data); g_free(cur); - } else + } else { prev = &cur->next; + } } } diff --git a/protocols/oscar/ssi.c b/protocols/oscar/ssi.c index e8502f68..7583114f 100644 --- a/protocols/oscar/ssi.c +++ b/protocols/oscar/ssi.c @@ -2,16 +2,16 @@ * Server-Side/Stored Information. * * Relatively new facility that allows storing of certain types of information, - * such as a users buddy list, permit/deny list, and permit/deny preferences, + * such as a users buddy list, permit/deny list, and permit/deny preferences, * to be stored on the server, so that they can be accessed from any client. * - * We keep a copy of the ssi data in sess->ssi, because the data needs to be - * accessed for various reasons. So all the "aim_ssi_itemlist_bleh" functions + * We keep a copy of the ssi data in sess->ssi, because the data needs to be + * accessed for various reasons. So all the "aim_ssi_itemlist_bleh" functions * near the top just manage the local data. * - * The SNAC sending and receiving functions are lower down in the file, and - * they're simpler. They are in the order of the subtypes they deal with, - * starting with the request rights function (subtype 0x0002), then parse + * The SNAC sending and receiving functions are lower down in the file, and + * they're simpler. They are in the order of the subtypes they deal with, + * starting with the request rights function (subtype 0x0002), then parse * rights (subtype 0x0003), then--well, you get the idea. * * This is entirely too complicated. @@ -29,50 +29,59 @@ * Locally add a new item to the given item list. * * @param list A pointer to a pointer to the current list of items. - * @param parent A pointer to the parent group, or NULL if the item should have no + * @param parent A pointer to the parent group, or NULL if the item should have no * parent group (ie. the group ID# should be 0). - * @param name A null terminated string of the name of the new item, or NULL if the + * @param name A null terminated string of the name of the new item, or NULL if the * item should have no name. * @param type The type of the item, 0x0001 for a contact, 0x0002 for a group, etc. * @return The newly created item. */ -static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, struct aim_ssi_item *parent, char *name, guint16 type) +static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, struct aim_ssi_item *parent, char *name, + guint16 type) { int i; struct aim_ssi_item *cur, *newitem; - if (!(newitem = g_new0(struct aim_ssi_item, 1))) + if (!(newitem = g_new0(struct aim_ssi_item, 1))) { return NULL; + } /* Set the name */ if (name) { - if (!(newitem->name = (char *)g_malloc((strlen(name)+1)*sizeof(char)))) { + if (!(newitem->name = (char *) g_malloc((strlen(name) + 1) * sizeof(char)))) { g_free(newitem); return NULL; } strcpy(newitem->name, name); - } else + } else { newitem->name = NULL; + } /* Set the group ID# and the buddy ID# */ newitem->gid = 0x0000; newitem->bid = 0x0000; if (type == AIM_SSI_TYPE_GROUP) { - if (name) + if (name) { do { newitem->gid += 0x0001; - for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) - if ((cur->gid == newitem->gid) && (cur->gid == newitem->gid)) - i=1; + for (cur = *list, i = 0; ((cur) && (!i)); cur = cur->next) { + if ((cur->gid == newitem->gid) && (cur->gid == newitem->gid)) { + i = 1; + } + } } while (i); + } } else { - if (parent) + if (parent) { newitem->gid = parent->gid; + } do { newitem->bid += 0x0001; - for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) - if ((cur->bid == newitem->bid) && (cur->gid == newitem->gid)) - i=1; + for (cur = *list, i = 0; ((cur) && (!i)); cur = cur->next) { + if ((cur->bid == newitem->bid) && (cur->gid == newitem->gid)) { + i = 1; + } + } } while (i); } @@ -99,39 +108,48 @@ static int aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item **list, struct aim_ /* Free the old additional data */ if (parentgroup->data) { - aim_freetlvchain((aim_tlvlist_t **)&parentgroup->data); + aim_freetlvchain((aim_tlvlist_t **) &parentgroup->data); parentgroup->data = NULL; } /* Find the length for the new additional data */ newlen = 0; if (parentgroup->gid == 0x0000) { - for (cur=*list; cur; cur=cur->next) - if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) + for (cur = *list; cur; cur = cur->next) { + if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) { newlen += 2; + } + } } else { - for (cur=*list; cur; cur=cur->next) - if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) + for (cur = *list; cur; cur = cur->next) { + if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) { newlen += 2; + } + } } /* Rebuild the additional data */ - if (newlen>0) { + if (newlen > 0) { guint8 *newdata; - if (!(newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8)))) + if (!(newdata = (guint8 *) g_malloc((newlen) * sizeof(guint8)))) { return -ENOMEM; + } newlen = 0; if (parentgroup->gid == 0x0000) { - for (cur=*list; cur; cur=cur->next) - if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) - newlen += aimutil_put16(newdata+newlen, cur->gid); + for (cur = *list; cur; cur = cur->next) { + if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) { + newlen += aimutil_put16(newdata + newlen, cur->gid); + } + } } else { - for (cur=*list; cur; cur=cur->next) - if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) - newlen += aimutil_put16(newdata+newlen, cur->bid); + for (cur = *list; cur; cur = cur->next) { + if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) { + newlen += aimutil_put16(newdata + newlen, cur->bid); + } + } } - aim_addtlvtochain_raw((aim_tlvlist_t **)&(parentgroup->data), 0x00c8, newlen, newdata); + aim_addtlvtochain_raw((aim_tlvlist_t **) &(parentgroup->data), 0x00c8, newlen, newdata); g_free(newdata); } @@ -151,8 +169,12 @@ static int aim_ssi_freelist(aim_session_t *sess) cur = sess->ssi.items; while (cur) { - if (cur->name) g_free(cur->name); - if (cur->data) aim_freetlvchain((aim_tlvlist_t **)&cur->data); + if (cur->name) { + g_free(cur->name); + } + if (cur->data) { + aim_freetlvchain((aim_tlvlist_t **) &cur->data); + } delitem = cur; cur = cur->next; g_free(delitem); @@ -160,7 +182,7 @@ static int aim_ssi_freelist(aim_session_t *sess) sess->ssi.items = NULL; sess->ssi.revision = 0; - sess->ssi.timestamp = (time_t)0; + sess->ssi.timestamp = (time_t) 0; return 0; } @@ -176,14 +198,17 @@ static int aim_ssi_freelist(aim_session_t *sess) struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid) { struct aim_ssi_item *cur; - for (cur=list; cur; cur=cur->next) - if ((cur->gid == gid) && (cur->bid == bid)) + + for (cur = list; cur; cur = cur->next) { + if ((cur->gid == gid) && (cur->bid == bid)) { return cur; + } + } return NULL; } /** - * Locally find an item given a group name, screen name, and type. If group name + * Locally find an item given a group name, screen name, and type. If group name * and screen name are null, then just return the first item of the given type. * * @param list A pointer to the current list of items. @@ -195,27 +220,37 @@ struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gi struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, char *gn, char *sn, guint16 type) { struct aim_ssi_item *cur; - if (!list) + + if (!list) { return NULL; + } if (gn && sn) { /* For finding buddies in groups */ - for (cur=list; cur; cur=cur->next) + for (cur = list; cur; cur = cur->next) { if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) { struct aim_ssi_item *curg; - for (curg=list; curg; curg=curg->next) - if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn))) + for (curg = list; curg; curg = curg->next) { + if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && + (curg->name) && !(aim_sncmp(curg->name, gn))) { return cur; + } + } } + } } else if (sn) { /* For finding groups, permits, denies, and ignores */ - for (cur=list; cur; cur=cur->next) - if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) + for (cur = list; cur; cur = cur->next) { + if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) { return cur; + } + } - /* For stuff without names--permit deny setting, visibility mask, etc. */ - } else for (cur=list; cur; cur=cur->next) { - if (cur->type == type) - return cur; + /* For stuff without names--permit deny setting, visibility mask, etc. */ + } else { for (cur = list; cur; cur = cur->next) { + if (cur->type == type) { + return cur; + } + } } return NULL; @@ -231,13 +266,18 @@ struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, char * struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char *sn) { struct aim_ssi_item *cur, *curg; - if (!list || !sn) + + if (!list || !sn) { return NULL; - if (!(cur = aim_ssi_itemlist_finditem(list, NULL, sn, AIM_SSI_TYPE_BUDDY))) + } + if (!(cur = aim_ssi_itemlist_finditem(list, NULL, sn, AIM_SSI_TYPE_BUDDY))) { return NULL; - for (curg=list; curg; curg=curg->next) - if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid)) + } + for (curg = list; curg; curg = curg->next) { + if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid)) { return curg; + } + } return NULL; } @@ -250,20 +290,22 @@ struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char int aim_ssi_getpermdeny(struct aim_ssi_item *list) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO); + if (cur) { aim_tlvlist_t *tlvlist = cur->data; if (tlvlist) { aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00ca, 1); - if (tlv && tlv->value) + if (tlv && tlv->value) { return aimutil_get8(tlv->value); + } } } return 0; } /** - * Add the given packet to the holding queue. We totally need to send SSI SNACs one at - * a time, so we have a local queue where packets get put before they are sent, and + * Add the given packet to the holding queue. We totally need to send SSI SNACs one at + * a time, so we have a local queue where packets get put before they are sent, and * then we send stuff one at a time, nice and orderly-like. * * @param sess The oscar session. @@ -275,16 +317,20 @@ static int aim_ssi_enqueue(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *f { aim_frame_t *cur; - if (!sess || !conn || !fr) + if (!sess || !conn || !fr) { return -EINVAL; + } fr->next = NULL; if (sess->ssi.holding_queue == NULL) { sess->ssi.holding_queue = fr; - if (!sess->ssi.waiting_for_ack) + if (!sess->ssi.waiting_for_ack) { aim_ssi_modbegin(sess, conn); + } } else { - for (cur = sess->ssi.holding_queue; cur->next; cur = cur->next) ; + for (cur = sess->ssi.holding_queue; cur->next; cur = cur->next) { + ; + } cur->next = fr; } @@ -292,8 +338,8 @@ static int aim_ssi_enqueue(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *f } /** - * Send the next SNAC from the holding queue. This is called - * automatically when an ack from an add, mod, or del is received. + * Send the next SNAC from the holding queue. This is called + * automatically when an ack from an add, mod, or del is received. * If the queue is empty, it sends the modend SNAC. * * @param sess The oscar session. @@ -304,8 +350,9 @@ static int aim_ssi_dispatch(aim_session_t *sess, aim_conn_t *conn) { aim_frame_t *cur; - if (!sess || !conn) + if (!sess || !conn) { return -EINVAL; + } if (!sess->ssi.waiting_for_ack) { if (sess->ssi.holding_queue) { @@ -314,8 +361,9 @@ static int aim_ssi_dispatch(aim_session_t *sess, aim_conn_t *conn) sess->ssi.holding_queue->next = NULL; aim_tx_enqueue(sess, sess->ssi.holding_queue); sess->ssi.holding_queue = cur; - } else + } else { aim_ssi_modend(sess, conn); + } } return 0; @@ -337,22 +385,25 @@ int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s struct aim_ssi_item *parentgroup, **newitems; guint16 i; - if (!sess || !conn || !gn || !sn || !num) + if (!sess || !conn || !gn || !sn || !num) { return -EINVAL; + } /* Look up the parent group */ if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) { aim_ssi_addgroups(sess, conn, &gn, 1); - if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) + if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) { return -ENOMEM; + } } /* Allocate an array of pointers to each of the new items */ - if (!(newitems = g_new0(struct aim_ssi_item *, num))) + if (!(newitems = g_new0(struct aim_ssi_item *, num))) { return -ENOMEM; + } /* Add items to the local list, and index them in the array */ - for (i=0; i<num; i++) + for (i = 0; i < num; i++) { if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, parentgroup, sn[i], AIM_SSI_TYPE_BUDDY))) { g_free(newitems); return -ENOMEM; @@ -361,6 +412,7 @@ int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s aim_addtlvtochain_noval(&tl, 0x66); newitems[i]->data = tl; } + } /* Send the add item SNAC */ if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) { @@ -372,22 +424,25 @@ int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s g_free(newitems); /* Rebuild the additional data in the parent group */ - if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) + if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) { return i; + } /* Send the mod item SNAC */ - if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD ))) + if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD))) { return i; + } /* Begin sending SSI SNACs */ - if (!(i = aim_ssi_dispatch(sess, conn))) + if (!(i = aim_ssi_dispatch(sess, conn))) { return i; + } return 0; } /** - * Add the master group (the group containing all groups). This is called by + * Add the master group (the group containing all groups). This is called by * aim_ssi_addgroups, if necessary. * * @param sess The oscar session. @@ -398,12 +453,14 @@ int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn) { struct aim_ssi_item *newitem; - if (!sess || !conn) + if (!sess || !conn) { return -EINVAL; + } /* Add the item to the local list, and keep a pointer to it */ - if (!(newitem = aim_ssi_itemlist_add(&sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_GROUP))) + if (!(newitem = aim_ssi_itemlist_add(&sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_GROUP))) { return -ENOMEM; + } /* If there are any existing groups (technically there shouldn't be, but */ /* just in case) then add their group ID#'s to the additional data */ @@ -432,26 +489,30 @@ int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned struct aim_ssi_item *parentgroup, **newitems; guint16 i; - if (!sess || !conn || !gn || !num) + if (!sess || !conn || !gn || !num) { return -EINVAL; + } /* Look up the parent group */ if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) { aim_ssi_addmastergroup(sess, conn); - if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) + if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) { return -ENOMEM; + } } /* Allocate an array of pointers to each of the new items */ - if (!(newitems = g_new0(struct aim_ssi_item *, num))) + if (!(newitems = g_new0(struct aim_ssi_item *, num))) { return -ENOMEM; + } /* Add items to the local list, and index them in the array */ - for (i=0; i<num; i++) + for (i = 0; i < num; i++) { if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, parentgroup, gn[i], AIM_SSI_TYPE_GROUP))) { g_free(newitems); return -ENOMEM; } + } /* Send the add item SNAC */ if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) { @@ -463,30 +524,33 @@ int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned g_free(newitems); /* Rebuild the additional data in the parent group */ - if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) + if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) { return i; + } /* Send the mod item SNAC */ - if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD))) + if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD))) { return i; + } /* Begin sending SSI SNACs */ - if (!(i = aim_ssi_dispatch(sess, conn))) + if (!(i = aim_ssi_dispatch(sess, conn))) { return i; + } return 0; } /** - * Add an array of a certain type of item to the list. This can be used for - * permit buddies, deny buddies, ICQ's ignore buddies, and probably other + * Add an array of a certain type of item to the list. This can be used for + * permit buddies, deny buddies, ICQ's ignore buddies, and probably other * types, also. * * @param sess The oscar session. * @param conn The bos connection for this session. * @param sn An array of null terminated strings of the names you want to add. * @param num The number of groups names you are adding (size of the sn array). - * @param type The type of item you want to add. See the AIM_SSI_TYPE_BLEH + * @param type The type of item you want to add. See the AIM_SSI_TYPE_BLEH * #defines in aim.h. * @return Return 0 if no errors, otherwise return the error number. */ @@ -495,19 +559,22 @@ int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned i struct aim_ssi_item **newitems; guint16 i; - if (!sess || !conn || !sn || !num) + if (!sess || !conn || !sn || !num) { return -EINVAL; + } /* Allocate an array of pointers to each of the new items */ - if (!(newitems = g_new0(struct aim_ssi_item *, num))) + if (!(newitems = g_new0(struct aim_ssi_item *, num))) { return -ENOMEM; + } /* Add items to the local list, and index them in the array */ - for (i=0; i<num; i++) + for (i = 0; i < num; i++) { if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, NULL, sn[i], type))) { g_free(newitems); return -ENOMEM; } + } /* Send the add item SNAC */ if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) { @@ -519,14 +586,15 @@ int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned i g_free(newitems); /* Begin sending SSI SNACs */ - if (!(i = aim_ssi_dispatch(sess, conn))) + if (!(i = aim_ssi_dispatch(sess, conn))) { return i; + } return 0; } /** - * Move a buddy from one group to another group. This basically just deletes the + * Move a buddy from one group to another group. This basically just deletes the * buddy and re-adds it. * * @param sess The oscar session. @@ -541,16 +609,19 @@ int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, char *oldgn, char * struct aim_ssi_item **groups, *buddy, *cur; guint16 i; - if (!sess || !conn || !oldgn || !newgn || !sn) + if (!sess || !conn || !oldgn || !newgn || !sn) { return -EINVAL; + } /* Look up the buddy */ - if (!(buddy = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn, AIM_SSI_TYPE_BUDDY))) + if (!(buddy = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn, AIM_SSI_TYPE_BUDDY))) { return -ENOMEM; + } /* Allocate an array of pointers to the two groups */ - if (!(groups = g_new0(struct aim_ssi_item *, 2))) + if (!(groups = g_new0(struct aim_ssi_item *, 2))) { return -ENOMEM; + } /* Look up the old parent group */ if (!(groups[0] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, oldgn, AIM_SSI_TYPE_GROUP))) { @@ -574,9 +645,12 @@ int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, char *oldgn, char * buddy->bid = 0; do { buddy->bid += 0x0001; - for (cur=sess->ssi.items, i=0; ((cur) && (!i)); cur=cur->next) - if ((cur->bid == buddy->bid) && (cur->gid == buddy->gid) && (cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && aim_sncmp(cur->name, buddy->name)) - i=1; + for (cur = sess->ssi.items, i = 0; ((cur) && (!i)); cur = cur->next) { + if ((cur->bid == buddy->bid) && (cur->gid == buddy->gid) && (cur->type == AIM_SSI_TYPE_BUDDY) && + (cur->name) && aim_sncmp(cur->name, buddy->name)) { + i = 1; + } + } } while (i); /* Rebuild the additional data in the two parent groups */ @@ -613,18 +687,20 @@ int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s struct aim_ssi_item *cur, *parentgroup, **delitems; int i; - if (!sess || !conn || !gn || !sn || !num) + if (!sess || !conn || !gn || !sn || !num) { return -EINVAL; + } /* Look up the parent group */ - if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) + if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) { return -EINVAL; + } /* Allocate an array of pointers to each of the items to be deleted */ delitems = g_new0(struct aim_ssi_item *, num); /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn[i], AIM_SSI_TYPE_BUDDY))) { g_free(delitems); return -EINVAL; @@ -634,9 +710,12 @@ int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s if (sess->ssi.items == delitems[i]) { sess->ssi.items = sess->ssi.items->next; } else { - for (cur=sess->ssi.items; (cur->next && (cur->next!=delitems[i])); cur=cur->next); - if (cur->next) + for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) { + ; + } + if (cur->next) { cur->next = cur->next->next; + } } } @@ -644,11 +723,13 @@ int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL); /* Free the items */ - for (i=0; i<num; i++) { - if (delitems[i]->name) + for (i = 0; i < num; i++) { + if (delitems[i]->name) { g_free(delitems[i]->name); - if (delitems[i]->data) - aim_freetlvchain((aim_tlvlist_t **)&delitems[i]->data); + } + if (delitems[i]->data) { + aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data); + } g_free(delitems[i]); } g_free(delitems); @@ -660,8 +741,9 @@ int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **s aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD); /* Delete the group, but only if it's empty */ - if (!parentgroup->data) + if (!parentgroup->data) { aim_ssi_delgroups(sess, conn, &parentgroup->name, 1); + } /* Begin sending SSI SNACs */ aim_ssi_dispatch(sess, conn); @@ -681,30 +763,37 @@ int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn) { struct aim_ssi_item *cur, *delitem; - if (!sess || !conn) + if (!sess || !conn) { return -EINVAL; + } /* Make delitem a pointer to the aim_ssi_item to be deleted */ - if (!(delitem = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) + if (!(delitem = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) { return -EINVAL; + } /* Remove delitem from the item list */ if (sess->ssi.items == delitem) { sess->ssi.items = sess->ssi.items->next; } else { - for (cur=sess->ssi.items; (cur->next && (cur->next!=delitem)); cur=cur->next); - if (cur->next) + for (cur = sess->ssi.items; (cur->next && (cur->next != delitem)); cur = cur->next) { + ; + } + if (cur->next) { cur->next = cur->next->next; + } } /* Send the del item SNAC */ aim_ssi_addmoddel(sess, conn, &delitem, 1, AIM_CB_SSI_DEL); /* Free the item */ - if (delitem->name) + if (delitem->name) { g_free(delitem->name); - if (delitem->data) - aim_freetlvchain((aim_tlvlist_t **)&delitem->data); + } + if (delitem->data) { + aim_freetlvchain((aim_tlvlist_t **) &delitem->data); + } g_free(delitem); /* Begin sending SSI SNACs */ @@ -722,22 +811,25 @@ int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn) * @param num The number of groups you are deleting (size of the gn array). * @return Return 0 if no errors, otherwise return the error number. */ -int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num) { +int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num) +{ struct aim_ssi_item *cur, *parentgroup, **delitems; int i; - if (!sess || !conn || !gn || !num) + if (!sess || !conn || !gn || !num) { return -EINVAL; + } /* Look up the parent group */ - if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) + if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) { return -EINVAL; + } /* Allocate an array of pointers to each of the items to be deleted */ delitems = g_new0(struct aim_ssi_item *, num); /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn[i], AIM_SSI_TYPE_GROUP))) { g_free(delitems); return -EINVAL; @@ -747,9 +839,12 @@ int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned if (sess->ssi.items == delitems[i]) { sess->ssi.items = sess->ssi.items->next; } else { - for (cur=sess->ssi.items; (cur->next && (cur->next!=delitems[i])); cur=cur->next); - if (cur->next) + for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) { + ; + } + if (cur->next) { cur->next = cur->next->next; + } } } @@ -757,11 +852,13 @@ int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL); /* Free the items */ - for (i=0; i<num; i++) { - if (delitems[i]->name) + for (i = 0; i < num; i++) { + if (delitems[i]->name) { g_free(delitems[i]->name); - if (delitems[i]->data) - aim_freetlvchain((aim_tlvlist_t **)&delitems[i]->data); + } + if (delitems[i]->data) { + aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data); + } g_free(delitems[i]); } g_free(delitems); @@ -773,8 +870,9 @@ int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD); /* Delete the group, but only if it's empty */ - if (!parentgroup->data) + if (!parentgroup->data) { aim_ssi_delmastergroup(sess, conn); + } /* Begin sending SSI SNACs */ aim_ssi_dispatch(sess, conn); @@ -783,8 +881,8 @@ int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned } /** - * Delete an array of a certain type of item from the list. This can be - * used for permit buddies, deny buddies, ICQ's ignore buddies, and + * Delete an array of a certain type of item from the list. This can be + * used for permit buddies, deny buddies, ICQ's ignore buddies, and * probably other types, also. * * @param sess The oscar session. @@ -793,18 +891,20 @@ int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned * @param num The number of items you are deleting (size of the sn array). * @return Return 0 if no errors, otherwise return the error number. */ -int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type) { +int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type) +{ struct aim_ssi_item *cur, **delitems; int i; - if (!sess || !conn || !sn || !num || (type!=AIM_SSI_TYPE_PERMIT && type!=AIM_SSI_TYPE_DENY)) + if (!sess || !conn || !sn || !num || (type != AIM_SSI_TYPE_PERMIT && type != AIM_SSI_TYPE_DENY)) { return -EINVAL; + } /* Allocate an array of pointers to each of the items to be deleted */ delitems = g_new0(struct aim_ssi_item *, num); /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn[i], type))) { g_free(delitems); return -EINVAL; @@ -814,9 +914,12 @@ int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned i if (sess->ssi.items == delitems[i]) { sess->ssi.items = sess->ssi.items->next; } else { - for (cur=sess->ssi.items; (cur->next && (cur->next!=delitems[i])); cur=cur->next); - if (cur->next) + for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) { + ; + } + if (cur->next) { cur->next = cur->next->next; + } } } @@ -824,11 +927,13 @@ int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned i aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL); /* Free the items */ - for (i=0; i<num; i++) { - if (delitems[i]->name) + for (i = 0; i < num; i++) { + if (delitems[i]->name) { g_free(delitems[i]->name); - if (delitems[i]->data) - aim_freetlvchain((aim_tlvlist_t **)&delitems[i]->data); + } + if (delitems[i]->data) { + aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data); + } g_free(delitems[i]); } g_free(delitems); @@ -855,8 +960,9 @@ static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, int ret = 0; aim_rxcallback_t userfunc; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx); + } return ret; } @@ -866,11 +972,13 @@ int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn) aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !conn) + if (!sess || !conn) { return -EINVAL; + } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQFULLLIST, 0x0000, NULL, 0); @@ -894,35 +1002,41 @@ static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai guint32 timestamp; /* When you set the version for the SSI family to 2-4, the beginning of this changes. - * Instead of the version and then the revision, there is "0x0006" and then a type - * 0x0001 TLV containing the 2 byte SSI family version that you sent earlier. Also, - * the SNAC flags go from 0x0000 to 0x8000. I guess the 0x0006 is the length of the - * TLV(s) that follow. The rights SNAC does the same thing, with the differing flag + * Instead of the version and then the revision, there is "0x0006" and then a type + * 0x0001 TLV containing the 2 byte SSI family version that you sent earlier. Also, + * the SNAC flags go from 0x0000 to 0x8000. I guess the 0x0006 is the length of the + * TLV(s) that follow. The rights SNAC does the same thing, with the differing flag * and everything. */ fmtver = aimbs_get8(bs); /* Version of ssi data. Should be 0x00 */ revision = aimbs_get16(bs); /* # of times ssi data has been modified */ - if (revision != 0) + if (revision != 0) { sess->ssi.revision = revision; + } - for (cur = sess->ssi.items; cur && cur->next; cur=cur->next) ; + for (cur = sess->ssi.items; cur && cur->next; cur = cur->next) { + ; + } while (aim_bstream_empty(bs) > 4) { /* last four bytes are stamp */ guint16 namelen, tbslen; if (!sess->ssi.items) { - if (!(sess->ssi.items = g_new0(struct aim_ssi_item, 1))) + if (!(sess->ssi.items = g_new0(struct aim_ssi_item, 1))) { return -ENOMEM; + } cur = sess->ssi.items; } else { - if (!(cur->next = g_new0(struct aim_ssi_item, 1))) + if (!(cur->next = g_new0(struct aim_ssi_item, 1))) { return -ENOMEM; + } cur = cur->next; } - if ((namelen = aimbs_get16(bs))) + if ((namelen = aimbs_get16(bs))) { cur->name = aimbs_getstr(bs, namelen); + } cur->gid = aimbs_get16(bs); cur->bid = aimbs_get16(bs); cur->type = aimbs_get16(bs); @@ -931,18 +1045,20 @@ static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai aim_bstream_t tbs; aim_bstream_init(&tbs, bs->data + bs->offset /* XXX */, tbslen); - cur->data = (void *)aim_readtlvchain(&tbs); + cur->data = (void *) aim_readtlvchain(&tbs); aim_bstream_advance(bs, tbslen); } } timestamp = aimbs_get32(bs); - if (timestamp != 0) + if (timestamp != 0) { sess->ssi.timestamp = timestamp; + } sess->ssi.received_data = 1; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, fmtver, sess->ssi.revision, sess->ssi.timestamp, sess->ssi.items); + } return ret; } @@ -954,7 +1070,7 @@ static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, ai * are ready to begin using the list. It will promptly give you the * presence information for everyone in your list and put your permit/deny * settings into effect. - * + * */ int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn) { @@ -976,29 +1092,30 @@ int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn) * @param reason The reason string to send with the request. * @return Return 0 if no errors, otherwise return the error number. */ -int aim_ssi_auth_request( aim_session_t *sess, aim_conn_t *conn, char *uin, char *reason ) +int aim_ssi_auth_request(aim_session_t *sess, aim_conn_t *conn, char *uin, char *reason) { aim_frame_t *fr; aim_snacid_t snacid; int snaclen; - - snaclen = 10 + 1 + strlen( uin ) + 2 + strlen( reason ) + 2; - - if( !( fr = aim_tx_new( sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen ) ) ) + + snaclen = 10 + 1 + strlen(uin) + 2 + strlen(reason) + 2; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) { return -ENOMEM; + } + + snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0); + aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid); - snacid = aim_cachesnac( sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0 ); - aim_putsnac( &fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid ); - - aimbs_put8( &fr->data, strlen( uin ) ); - aimbs_putraw( &fr->data, (guint8 *)uin, strlen( uin ) ); - aimbs_put16( &fr->data, strlen( reason ) ); - aimbs_putraw( &fr->data, (guint8 *)reason, strlen( reason ) ); - aimbs_put16( &fr->data, 0 ); - - aim_tx_enqueue( sess, fr ); - - return( 0 ); + aimbs_put8(&fr->data, strlen(uin)); + aimbs_putraw(&fr->data, (guint8 *) uin, strlen(uin)); + aimbs_put16(&fr->data, strlen(reason)); + aimbs_putraw(&fr->data, (guint8 *) reason, strlen(reason)); + aimbs_put16(&fr->data, 0); + + aim_tx_enqueue(sess, fr); + + return(0); } /** @@ -1011,29 +1128,30 @@ int aim_ssi_auth_request( aim_session_t *sess, aim_conn_t *conn, char *uin, char * @param reason The reason string to send with the request. * @return Return 0 if no errors, otherwise return the error number. */ -int aim_ssi_auth_reply( aim_session_t *sess, aim_conn_t *conn, char *uin, int yesno, char *reason ) +int aim_ssi_auth_reply(aim_session_t *sess, aim_conn_t *conn, char *uin, int yesno, char *reason) { aim_frame_t *fr; aim_snacid_t snacid; int snaclen; - - snaclen = 10 + 1 + strlen( uin ) + 3 + strlen( reason ); - - if( !( fr = aim_tx_new( sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen ) ) ) + + snaclen = 10 + 1 + strlen(uin) + 3 + strlen(reason); + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) { return -ENOMEM; - - snacid = aim_cachesnac( sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0 ); - aim_putsnac( &fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid ); - - aimbs_put8( &fr->data, strlen( uin ) ); - aimbs_putraw( &fr->data, (guint8 *)uin, strlen( uin ) ); - aimbs_put8( &fr->data, yesno ); - aimbs_put16( &fr->data, strlen( reason ) ); - aimbs_putraw( &fr->data, (guint8 *)reason, strlen( reason ) ); - - aim_tx_enqueue( sess, fr ); - - return( 0 ); + } + + snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0); + aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid); + + aimbs_put8(&fr->data, strlen(uin)); + aimbs_putraw(&fr->data, (guint8 *) uin, strlen(uin)); + aimbs_put8(&fr->data, yesno); + aimbs_put16(&fr->data, strlen(reason)); + aimbs_putraw(&fr->data, (guint8 *) reason, strlen(reason)); + + aim_tx_enqueue(sess, fr); + + return(0); } @@ -1043,25 +1161,27 @@ int aim_ssi_auth_reply( aim_session_t *sess, aim_conn_t *conn, char *uin, int ye * Sends the SNAC to add, modify, or delete an item from the server-stored * information. These 3 SNACs all have an identical structure. The only * difference is the subtype that is set for the SNAC. - * + * */ -int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, guint16 subtype) +int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, + guint16 subtype) { aim_frame_t *fr; aim_snacid_t snacid; int i, snaclen, listlen; char *list = NULL; - if (!sess || !conn || !items || !num) + if (!sess || !conn || !items || !num) { return -EINVAL; + } snaclen = 10; /* For family, subtype, flags, and SNAC ID */ listlen = 0; - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { snaclen += 10; /* For length, GID, BID, type, and length */ if (items[i]->name) { snaclen += strlen(items[i]->name); - + if (subtype == AIM_CB_SSI_ADD) { list = g_realloc(list, listlen + strlen(items[i]->name) + 1); strcpy(list + listlen, items[i]->name); @@ -1071,31 +1191,35 @@ int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item if (subtype == AIM_CB_SSI_ADD) { list = g_realloc(list, listlen + 1); list[listlen] = '\0'; - listlen ++; + listlen++; } } - if (items[i]->data) - snaclen += aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data); + if (items[i]->data) { + snaclen += aim_sizetlvchain((aim_tlvlist_t **) &items[i]->data); + } } - - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) { return -ENOMEM; + } snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, subtype, 0x0000, list, list ? listlen : 0); aim_putsnac(&fr->data, AIM_CB_FAM_SSI, subtype, 0x0000, snacid); - + g_free(list); - for (i=0; i<num; i++) { + for (i = 0; i < num; i++) { aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0); - if (items[i]->name) - aimbs_putraw(&fr->data, (guint8 *)items[i]->name, strlen(items[i]->name)); + if (items[i]->name) { + aimbs_putraw(&fr->data, (guint8 *) items[i]->name, strlen(items[i]->name)); + } aimbs_put16(&fr->data, items[i]->gid); aimbs_put16(&fr->data, items[i]->bid); aimbs_put16(&fr->data, items[i]->type); - aimbs_put16(&fr->data, items[i]->data ? aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data) : 0); - if (items[i]->data) - aim_writetlvchain(&fr->data, (aim_tlvlist_t **)&items[i]->data); + aimbs_put16(&fr->data, items[i]->data ? aim_sizetlvchain((aim_tlvlist_t **) &items[i]->data) : 0); + if (items[i]->data) { + aim_writetlvchain(&fr->data, (aim_tlvlist_t **) &items[i]->data); + } } aim_ssi_enqueue(sess, conn, fr); @@ -1117,17 +1241,18 @@ static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim sess->ssi.waiting_for_ack = 0; aim_ssi_dispatch(sess, rx->conn); - + origsnac = aim_remsnac(sess, snac->id); - - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx, origsnac); - + } + if (origsnac) { g_free(origsnac->data); g_free(origsnac); } - + return ret; } @@ -1135,7 +1260,7 @@ static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim * SSI Begin Data Modification. * * Tells the server you're going to start modifying data. - * + * */ int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn) { @@ -1160,15 +1285,17 @@ int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn) * posted local stamp/revision. * */ -static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs) { int ret = 0; aim_rxcallback_t userfunc; sess->ssi.received_data = 1; - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { ret = userfunc(sess, rx); + } return ret; } @@ -1176,14 +1303,15 @@ static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_ static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) + if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) { return parserights(sess, mod, rx, snac, bs); - else if (snac->subtype == AIM_CB_SSI_LIST) + } else if (snac->subtype == AIM_CB_SSI_LIST) { return parsedata(sess, mod, rx, snac, bs); - else if (snac->subtype == AIM_CB_SSI_SRVACK) + } else if (snac->subtype == AIM_CB_SSI_SRVACK) { return parseack(sess, mod, rx, snac, bs); - else if (snac->subtype == AIM_CB_SSI_NOLIST) + } else if (snac->subtype == AIM_CB_SSI_NOLIST) { return parsedataunchanged(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/ssi.h b/protocols/oscar/ssi.h index 60d9faa5..7ee4df50 100644 --- a/protocols/oscar/ssi.h +++ b/protocols/oscar/ssi.h @@ -46,7 +46,8 @@ struct aim_ssi_item { int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn); -int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, guint16 subtype); +int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, + guint16 subtype); int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn); @@ -57,7 +58,8 @@ struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char int aim_ssi_getpermdeny(struct aim_ssi_item *list); /* Send packets */ -int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num, unsigned int flags); +int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num, + unsigned int flags); int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn); int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num); int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type); diff --git a/protocols/oscar/stats.c b/protocols/oscar/stats.c index affd82fe..fb438412 100644 --- a/protocols/oscar/stats.c +++ b/protocols/oscar/stats.c @@ -1,15 +1,17 @@ #include <aim.h> -static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) +static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, + aim_bstream_t *bs) { guint16 interval; aim_rxcallback_t userfunc; interval = aimbs_get16(bs); - if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) + if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { return userfunc(sess, rx, interval); + } return 0; } @@ -17,8 +19,9 @@ static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *r static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) { - if (snac->subtype == 0x0002) + if (snac->subtype == 0x0002) { return reportinterval(sess, mod, rx, snac, bs); + } return 0; } diff --git a/protocols/oscar/tlv.c b/protocols/oscar/tlv.c index e7e3a7be..e01f728a 100644 --- a/protocols/oscar/tlv.c +++ b/protocols/oscar/tlv.c @@ -2,9 +2,10 @@ static void freetlv(aim_tlv_t **oldtlv) { - if (!oldtlv || !*oldtlv) + if (!oldtlv || !*oldtlv) { return; - + } + g_free((*oldtlv)->value); g_free(*oldtlv); *oldtlv = NULL; @@ -21,7 +22,7 @@ static void freetlv(aim_tlv_t **oldtlv) * be called to free the dynamic substructures. * * XXX There should be a flag setable here to have the tlvlist contain - * bstream references, so that at least the ->value portion of each + * bstream references, so that at least the ->value portion of each * element doesn't need to be malloc/memcpy'd. This could prove to be * just as effecient as the in-place TLV parsing used in a couple places * in libfaim. @@ -41,8 +42,9 @@ aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs) cur->tlv = g_new0(aim_tlv_t, 1); cur->tlv->type = type; - if ((cur->tlv->length = length)) - cur->tlv->value = aimbs_getraw(bs, length); + if ((cur->tlv->length = length)) { + cur->tlv->value = aimbs_getraw(bs, length); + } cur->next = list; list = cur; @@ -64,12 +66,13 @@ void aim_freetlvchain(aim_tlvlist_t **list) { aim_tlvlist_t *cur; - if (!list || !*list) + if (!list || !*list) { return; + } for (cur = *list; cur; ) { aim_tlvlist_t *tmp; - + freetlv(&cur->tlv); tmp = cur->next; @@ -94,11 +97,13 @@ int aim_counttlvchain(aim_tlvlist_t **list) aim_tlvlist_t *cur; int count; - if (!list || !*list) + if (!list || !*list) { return 0; + } - for (cur = *list, count = 0; cur; cur = cur->next) + for (cur = *list, count = 0; cur; cur = cur->next) { count++; + } return count; } @@ -107,7 +112,7 @@ int aim_counttlvchain(aim_tlvlist_t **list) * aim_sizetlvchain - Count the number of bytes in a TLV chain * @list: Chain to be sized * - * Returns the number of bytes that would be needed to + * Returns the number of bytes that would be needed to * write the passed TLV chain to a data buffer. * */ @@ -116,11 +121,13 @@ int aim_sizetlvchain(aim_tlvlist_t **list) aim_tlvlist_t *cur; int size; - if (!list || !*list) + if (!list || !*list) { return 0; + } - for (cur = *list, size = 0; cur; cur = cur->next) + for (cur = *list, size = 0; cur; cur = cur->next) { size += (4 + cur->tlv->length); + } return size; } @@ -140,11 +147,13 @@ int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l { aim_tlvlist_t *newtlv, *cur; - if (!list) + if (!list) { return 0; + } - if (!(newtlv = g_new0(aim_tlvlist_t, 1))) + if (!(newtlv = g_new0(aim_tlvlist_t, 1))) { return 0; + } if (!(newtlv->tlv = g_new0(aim_tlv_t, 1))) { g_free(newtlv); @@ -152,15 +161,16 @@ int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l } newtlv->tlv->type = t; if ((newtlv->tlv->length = l)) { - newtlv->tlv->value = (guint8 *)g_malloc(newtlv->tlv->length); + newtlv->tlv->value = (guint8 *) g_malloc(newtlv->tlv->length); memcpy(newtlv->tlv->value, v, newtlv->tlv->length); } - if (!*list) + if (!*list) { *list = newtlv; - else { - for(cur = *list; cur->next; cur = cur->next) + } else { + for (cur = *list; cur->next; cur = cur->next) { ; + } cur->next = newtlv; } @@ -233,12 +243,13 @@ int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 t, const guint32 v) */ int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 caps) { - guint8 buf[16*16]; /* XXX icky fixed length buffer */ + guint8 buf[16 * 16]; /* XXX icky fixed length buffer */ aim_bstream_t bs; - if (!caps) + if (!caps) { return 0; /* nothing there anyway */ + } aim_bstream_init(&bs, buf, sizeof(buf)); aim_putcap(&bs, caps); @@ -265,7 +276,7 @@ int aim_addtlvtochain_noval(aim_tlvlist_t **list, const guint16 t) * made to this. * * XXX should probably support sublists for real. - * + * * This is so neat. * */ @@ -277,11 +288,13 @@ int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvl buflen = aim_sizetlvchain(tl); - if (buflen <= 0) + if (buflen <= 0) { return 0; + } - if (!(buf = g_malloc(buflen))) + if (!(buf = g_malloc(buflen))) { return 0; + } aim_bstream_init(&bs, buf, buflen); @@ -294,22 +307,24 @@ int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvl return buflen; } -int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance) +int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, + guint16 instance) { guint8 *buf; int buflen; aim_bstream_t bs; buflen = 2 + 1 + strlen(roomname) + 2; - - if (!(buf = g_malloc(buflen))) + + if (!(buf = g_malloc(buflen))) { return 0; + } aim_bstream_init(&bs, buf, buflen); aimbs_put16(&bs, exchange); aimbs_put8(&bs, strlen(roomname)); - aimbs_putraw(&bs, (guint8 *)roomname, strlen(roomname)); + aimbs_putraw(&bs, (guint8 *) roomname, strlen(roomname)); aimbs_put16(&bs, instance); aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf); @@ -326,11 +341,11 @@ int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 excha * @list: Source TLV chain * * Copies a TLV chain into a raw data buffer, writing only the number - * of bytes specified. This operation does not free the chain; + * of bytes specified. This operation does not free the chain; * aim_freetlvchain() must still be called to free up the memory used * by the chain structures. * - * XXX clean this up, make better use of bstreams + * XXX clean this up, make better use of bstreams */ int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list) { @@ -343,15 +358,17 @@ int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list) goodbuflen += cur->tlv->length; } - if (goodbuflen > aim_bstream_empty(bs)) + if (goodbuflen > aim_bstream_empty(bs)) { return 0; /* not enough buffer */ + } /* do the real write-out */ for (cur = *list; cur; cur = cur->next) { aimbs_put16(bs, cur->tlv->type); aimbs_put16(bs, cur->tlv->length); - if (cur->tlv->length) + if (cur->tlv->length) { aimbs_putraw(bs, cur->tlv->value, cur->tlv->length); + } } return 1; /* XXX this is a nonsensical return */ @@ -364,7 +381,7 @@ int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list) * @type: Requested TLV type * @nth: Index of TLV of type to get * - * Returns a pointer to an aim_tlv_t of the specified type; + * Returns a pointer to an aim_tlv_t of the specified type; * %NULL on error. The @nth parameter is specified starting at %1. * In most cases, there will be no more than one TLV of any type * in a chain. @@ -377,10 +394,12 @@ aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const guint16 t, const int n) for (cur = list, i = 0; cur; cur = cur->next) { if (cur && cur->tlv) { - if (cur->tlv->type == t) + if (cur->tlv->type == t) { i++; - if (i >= n) + } + if (i >= n) { return cur->tlv; + } } } @@ -394,7 +413,7 @@ aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const guint16 t, const int n) * @nth: Index of TLV to return * * Same as aim_gettlv(), except that the return value is a %NULL- - * terminated string instead of an aim_tlv_t. This is a + * terminated string instead of an aim_tlv_t. This is a * dynamic buffer and must be freed by the caller. * */ @@ -403,8 +422,9 @@ char *aim_gettlv_str(aim_tlvlist_t *list, const guint16 t, const int n) aim_tlv_t *tlv; char *newstr; - if (!(tlv = aim_gettlv(list, t, n))) + if (!(tlv = aim_gettlv(list, t, n))) { return NULL; + } newstr = (char *) g_malloc(tlv->length + 1); memcpy(newstr, tlv->value, tlv->length); @@ -419,16 +439,17 @@ char *aim_gettlv_str(aim_tlvlist_t *list, const guint16 t, const int n) * @type: TLV type to search for * @nth: Index of TLV to return * - * Same as aim_gettlv(), except that the return value is a - * 8bit integer instead of an aim_tlv_t. + * Same as aim_gettlv(), except that the return value is a + * 8bit integer instead of an aim_tlv_t. * */ guint8 aim_gettlv8(aim_tlvlist_t *list, const guint16 t, const int n) { aim_tlv_t *tlv; - if (!(tlv = aim_gettlv(list, t, n))) + if (!(tlv = aim_gettlv(list, t, n))) { return 0; /* erm */ + } return aimutil_get8(tlv->value); } @@ -438,16 +459,17 @@ guint8 aim_gettlv8(aim_tlvlist_t *list, const guint16 t, const int n) * @type: TLV type to search for * @nth: Index of TLV to return * - * Same as aim_gettlv(), except that the return value is a - * 16bit integer instead of an aim_tlv_t. + * Same as aim_gettlv(), except that the return value is a + * 16bit integer instead of an aim_tlv_t. * */ guint16 aim_gettlv16(aim_tlvlist_t *list, const guint16 t, const int n) { aim_tlv_t *tlv; - if (!(tlv = aim_gettlv(list, t, n))) + if (!(tlv = aim_gettlv(list, t, n))) { return 0; /* erm */ + } return aimutil_get16(tlv->value); } @@ -457,16 +479,17 @@ guint16 aim_gettlv16(aim_tlvlist_t *list, const guint16 t, const int n) * @type: TLV type to search for * @nth: Index of TLV to return * - * Same as aim_gettlv(), except that the return value is a - * 32bit integer instead of an aim_tlv_t. + * Same as aim_gettlv(), except that the return value is a + * 32bit integer instead of an aim_tlv_t. * */ guint32 aim_gettlv32(aim_tlvlist_t *list, const guint16 t, const int n) { aim_tlv_t *tlv; - if (!(tlv = aim_gettlv(list, t, n))) + if (!(tlv = aim_gettlv(list, t, n))) { return 0; /* erm */ + } return aimutil_get32(tlv->value); } @@ -543,9 +566,10 @@ int aim_puttlv_raw(guint8 *buf, const guint16 t, const guint16 l, const guint8 * int i; i = aimutil_put16(buf, t); - i += aimutil_put16(buf+i, l); - if (l) - memcpy(buf+i, v, l); + i += aimutil_put16(buf + i, l); + if (l) { + memcpy(buf + i, v, l); + } i += l; return i; diff --git a/protocols/oscar/txqueue.c b/protocols/oscar/txqueue.c index e48511fa..7ad2a3dd 100644 --- a/protocols/oscar/txqueue.c +++ b/protocols/oscar/txqueue.c @@ -31,10 +31,11 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g return NULL; } - if (!(fr = (aim_frame_t *)g_new0(aim_frame_t,1))) + if (!(fr = (aim_frame_t *) g_new0(aim_frame_t, 1))) { return NULL; + } - fr->conn = conn; + fr->conn = conn; fr->hdrtype = framing; @@ -42,13 +43,14 @@ aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, g fr->hdr.flap.type = chan; - } else + } else { imcb_error(sess->aux_data, "unknown framing"); + } if (datalen > 0) { guint8 *data; - if (!(data = (unsigned char *)g_malloc(datalen))) { + if (!(data = (unsigned char *) g_malloc(datalen))) { aim_frame_destroy(fr); return NULL; } @@ -89,13 +91,14 @@ static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr) fr->handled = 0; /* not sent yet */ /* see overhead note in aim_rxqueue counterpart */ - if (!sess->queue_outgoing) + if (!sess->queue_outgoing) { sess->queue_outgoing = fr; - else { + } else { aim_frame_t *cur; - for (cur = sess->queue_outgoing; cur->next; cur = cur->next) + for (cur = sess->queue_outgoing; cur->next; cur = cur->next) { ; + } cur->next = fr; } @@ -110,8 +113,8 @@ static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr) * * Basically the same as its __queuebased couterpart, however * instead of doing a list append, it just calls aim_tx_sendframe() - * right here. - * + * right here. + * */ static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr) { @@ -122,8 +125,9 @@ static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr) return 0; } - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) + if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); + } fr->handled = 0; /* not sent yet */ @@ -136,38 +140,40 @@ static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr) int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *)) { - - if (what == AIM_TX_QUEUED) + + if (what == AIM_TX_QUEUED) { sess->tx_enqueue = &aim_tx_enqueue__queuebased; - else if (what == AIM_TX_IMMEDIATE) + } else if (what == AIM_TX_IMMEDIATE) { sess->tx_enqueue = &aim_tx_enqueue__immediate; - else if (what == AIM_TX_USER) { - if (!func) + } else if (what == AIM_TX_USER) { + if (!func) { return -EINVAL; + } sess->tx_enqueue = func; - } else + } else { return -EINVAL; /* unknown action */ + } return 0; } int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr) { - + /* * If we want to send a connection thats inprogress, we have to force * them to use the queue based version. Otherwise, use whatever they * want. */ - if (fr && fr->conn && - (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { + if (fr && fr->conn && + (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { return aim_tx_enqueue__queuebased(sess, fr); } return (*sess->tx_enqueue)(sess, fr); } -/* +/* * aim_get_next_txseqnum() * * This increments the tx command count, and returns the seqnum @@ -179,7 +185,7 @@ int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr) flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn) { flap_seqnum_t ret; - + ret = ++conn->seqnum; return ret; @@ -192,11 +198,12 @@ static int aim_send(int fd, const void *buf, size_t count) for (cur = 0, left = count; left; ) { int ret; - ret = send(fd, ((unsigned char *)buf)+cur, left, 0); - if (ret == -1) + ret = send(fd, ((unsigned char *) buf) + cur, left, 0); + if (ret == -1) { return -1; - else if (ret == 0) + } else if (ret == 0) { return cur; + } cur += ret; left -= ret; @@ -208,22 +215,25 @@ static int aim_send(int fd, const void *buf, size_t count) static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count) { int wrote = 0; - if (!bs || !conn || (count < 0)) + + if (!bs || !conn || (count < 0)) { return -EINVAL; + } - if (count > aim_bstream_empty(bs)) + if (count > aim_bstream_empty(bs)) { count = aim_bstream_empty(bs); /* truncate to remaining space */ + } if (count) { if (count - wrote) { wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote); } - + } - + bs->offset += wrote; - return wrote; + return wrote; } static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) @@ -234,8 +244,9 @@ static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) payloadlen = aim_bstream_curpos(&fr->data); - if (!(obs_raw = g_malloc(6 + payloadlen))) + if (!(obs_raw = g_malloc(6 + payloadlen))) { return -ENOMEM; + } aim_bstream_init(&obs, obs_raw, 6 + payloadlen); @@ -251,9 +262,10 @@ static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) obslen = aim_bstream_curpos(&obs); aim_bstream_rewind(&obs); - if (aim_bstream_send(&obs, fr->conn, obslen) != obslen) + if (aim_bstream_send(&obs, fr->conn, obslen) != obslen) { err = -errno; - + } + g_free(obs_raw); /* XXX aim_bstream_free */ fr->handled = 1; @@ -264,8 +276,9 @@ static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *fr) { - if (fr->hdrtype == AIM_FRAMETYPE_FLAP) + if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { return sendframe_flap(sess, fr); + } return -1; } @@ -275,19 +288,21 @@ int aim_tx_flushqueue(aim_session_t *sess) for (cur = sess->queue_outgoing; cur; cur = cur->next) { - if (cur->handled) - continue; /* already been sent */ + if (cur->handled) { + continue; /* already been sent */ - if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS)) + } + if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS)) { continue; + } /* * And now for the meager attempt to force transmit * latency and avoid missed messages. */ if ((cur->conn->lastactivity + cur->conn->forcedlatency) >= time(NULL)) { - /* - * XXX should be a break! we dont want to block the + /* + * XXX should be a break! we dont want to block the * upper layers * * XXX or better, just do this right. @@ -308,10 +323,10 @@ int aim_tx_flushqueue(aim_session_t *sess) /* * aim_tx_purgequeue() - * - * This is responsable for removing sent commands from the transmit + * + * This is responsable for removing sent commands from the transmit * queue. This is not a required operation, but it of course helps - * reduce memory footprint at run time! + * reduce memory footprint at run time! * */ void aim_tx_purgequeue(aim_session_t *sess) @@ -325,8 +340,9 @@ void aim_tx_purgequeue(aim_session_t *sess) aim_frame_destroy(cur); - } else + } else { prev = &cur->next; + } } return; @@ -346,8 +362,9 @@ void aim_tx_cleanqueue(aim_session_t *sess, aim_conn_t *conn) aim_frame_t *cur; for (cur = sess->queue_outgoing; cur; cur = cur->next) { - if (cur->conn == conn) + if (cur->conn == conn) { cur->handled = 1; + } } return; diff --git a/protocols/purple/ft-direct.c b/protocols/purple/ft-direct.c index 98a16d75..05201ac3 100644 --- a/protocols/purple/ft-direct.c +++ b/protocols/purple/ft-direct.c @@ -33,8 +33,7 @@ #include <glib.h> #include <purple.h> -struct prpl_xfer_data -{ +struct prpl_xfer_data { PurpleXfer *xfer; file_transfer_t *ft; gint ready_timer; @@ -44,149 +43,149 @@ struct prpl_xfer_data static file_transfer_t *next_ft; -struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); +struct im_connection *purple_ic_by_pa(PurpleAccount *pa); /* Glorious hack: We seem to have to remind at least some libpurple plugins that we're ready because this info may get lost if we give it too early. So just do it ten times a second. :-/ */ -static gboolean prplcb_xfer_write_request_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean prplcb_xfer_write_request_cb(gpointer data, gint fd, b_input_condition cond) { struct prpl_xfer_data *px = data; - - purple_xfer_ui_ready( px->xfer ); - - return purple_xfer_get_type( px->xfer ) == PURPLE_XFER_RECEIVE; + + purple_xfer_ui_ready(px->xfer); + + return purple_xfer_get_type(px->xfer) == PURPLE_XFER_RECEIVE; } -static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +static gboolean prpl_xfer_write_request(struct file_transfer *ft) { struct prpl_xfer_data *px = ft->data; - px->ready_timer = b_timeout_add( 100, prplcb_xfer_write_request_cb, px ); + + px->ready_timer = b_timeout_add(100, prplcb_xfer_write_request_cb, px); return TRUE; } -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len) { struct prpl_xfer_data *px = ft->data; - - px->buf = g_memdup( buffer, len ); + + px->buf = g_memdup(buffer, len); px->buf_len = len; //purple_xfer_ui_ready( px->xfer ); - px->ready_timer = b_timeout_add( 0, prplcb_xfer_write_request_cb, px ); - + px->ready_timer = b_timeout_add(0, prplcb_xfer_write_request_cb, px); + return TRUE; } -static void prpl_xfer_accept( struct file_transfer *ft ) +static void prpl_xfer_accept(struct file_transfer *ft) { struct prpl_xfer_data *px = ft->data; - purple_xfer_request_accepted( px->xfer, NULL ); - prpl_xfer_write_request( ft ); + + purple_xfer_request_accepted(px->xfer, NULL); + prpl_xfer_write_request(ft); } -static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) +static void prpl_xfer_canceled(struct file_transfer *ft, char *reason) { struct prpl_xfer_data *px = ft->data; - purple_xfer_request_denied( px->xfer ); + + purple_xfer_request_denied(px->xfer); } -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond) { PurpleXfer *xfer = data; - struct im_connection *ic = purple_ic_by_pa( xfer->account ); - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + struct im_connection *ic = purple_ic_by_pa(xfer->account); + struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); PurpleBuddy *buddy; const char *who; - - buddy = purple_find_buddy( xfer->account, xfer->who ); - who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - + + buddy = purple_find_buddy(xfer->account, xfer->who); + who = buddy ? purple_buddy_get_name(buddy) : xfer->who; + /* TODO(wilmer): After spreading some more const goodness in BitlBee, remove the evil cast below. */ - px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size); px->ft->data = px; px->xfer = data; px->xfer->ui_data = px; - + px->ft->accept = prpl_xfer_accept; px->ft->canceled = prpl_xfer_canceled; px->ft->write_request = prpl_xfer_write_request; - + return FALSE; } -static void prplcb_xfer_new( PurpleXfer *xfer ) +static void prplcb_xfer_new(PurpleXfer *xfer) { - if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) - { + if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { /* This should suppress the stupid file dialog. */ - purple_xfer_set_local_filename( xfer, "/tmp/wtf123" ); - + purple_xfer_set_local_filename(xfer, "/tmp/wtf123"); + /* Sadly the xfer struct is still empty ATM so come back after the caller is done. */ - b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); - } - else - { - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); - + b_timeout_add(0, prplcb_xfer_new_send_cb, xfer); + } else { + struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); + px->ft = next_ft; px->ft->data = px; px->xfer = xfer; px->xfer->ui_data = px; - - purple_xfer_set_filename( xfer, px->ft->file_name ); - purple_xfer_set_size( xfer, px->ft->file_size ); - + + purple_xfer_set_filename(xfer, px->ft->file_name); + purple_xfer_set_size(xfer, px->ft->file_size); + next_ft = NULL; } } -static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) +static void prplcb_xfer_progress(PurpleXfer *xfer, double percent) { - fprintf( stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent ); + fprintf(stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent); } -static void prplcb_xfer_dbg( PurpleXfer *xfer ) +static void prplcb_xfer_dbg(PurpleXfer *xfer) { - fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); + fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer); } -static gssize prplcb_xfer_write( PurpleXfer *xfer, const guchar *buffer, gssize size ) +static gssize prplcb_xfer_write(PurpleXfer *xfer, const guchar *buffer, gssize size) { struct prpl_xfer_data *px = xfer->ui_data; gboolean st; - - fprintf( stderr, "xfer_write %d %d\n", size, px->buf_len ); - - b_event_remove( px->ready_timer ); + + fprintf(stderr, "xfer_write %d %d\n", size, px->buf_len); + + b_event_remove(px->ready_timer); px->ready_timer = 0; - - st = px->ft->write( px->ft, (char*) buffer, size ); - - if( st && xfer->bytes_remaining == size ) - imcb_file_finished( px->ft ); - + + st = px->ft->write(px->ft, (char *) buffer, size); + + if (st && xfer->bytes_remaining == size) { + imcb_file_finished(px->ft); + } + return st ? size : 0; } -gssize prplcb_xfer_read( PurpleXfer *xfer, guchar **buffer, gssize size ) +gssize prplcb_xfer_read(PurpleXfer *xfer, guchar **buffer, gssize size) { struct prpl_xfer_data *px = xfer->ui_data; - - fprintf( stderr, "xfer_read %d %d\n", size, px->buf_len ); - if( px->buf ) - { + fprintf(stderr, "xfer_read %d %d\n", size, px->buf_len); + + if (px->buf) { *buffer = px->buf; px->buf = NULL; - - px->ft->write_request( px->ft ); - + + px->ft->write_request(px->ft); + return px->buf_len; } - + return 0; } @@ -203,37 +202,36 @@ PurpleXferUiOps bee_xfer_uiops = prplcb_xfer_dbg, }; -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ); +static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond); -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle) { PurpleAccount *pa = ic->proto_data; struct prpl_xfer_data *px; - + /* xfer_new() will pick up this variable. It's a hack but we're not multi-threaded anyway. */ next_ft = ft; - serv_send_file( purple_account_get_connection( pa ), handle, ft->file_name ); - + serv_send_file(purple_account_get_connection(pa), handle, ft->file_name); + ft->write = prpl_xfer_write; - + px = ft->data; - imcb_file_recv_start( ft ); - - px->ready_timer = b_timeout_add( 100, prplcb_xfer_send_cb, px ); + imcb_file_recv_start(ft); + + px->ready_timer = b_timeout_add(100, prplcb_xfer_send_cb, px); } -static gboolean prplcb_xfer_send_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond) { struct prpl_xfer_data *px = data; - - if( px->ft->status & FT_STATUS_TRANSFERRING ) - { - fprintf( stderr, "The ft, it is ready...\n" ); - px->ft->write_request( px->ft ); - + + if (px->ft->status & FT_STATUS_TRANSFERRING) { + fprintf(stderr, "The ft, it is ready...\n"); + px->ft->write_request(px->ft); + return FALSE; } - + return TRUE; } diff --git a/protocols/purple/ft.c b/protocols/purple/ft.c index c4efc657..28f5d228 100644 --- a/protocols/purple/ft.c +++ b/protocols/purple/ft.c @@ -33,8 +33,7 @@ #include <glib.h> #include <purple.h> -struct prpl_xfer_data -{ +struct prpl_xfer_data { PurpleXfer *xfer; file_transfer_t *ft; struct im_connection *ic; @@ -45,297 +44,289 @@ struct prpl_xfer_data static file_transfer_t *next_ft; -struct im_connection *purple_ic_by_pa( PurpleAccount *pa ); -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ); -static gboolean prpl_xfer_write_request( struct file_transfer *ft ); +struct im_connection *purple_ic_by_pa(PurpleAccount *pa); +static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond); +static gboolean prpl_xfer_write_request(struct file_transfer *ft); /* Receiving files (IM->UI): */ -static void prpl_xfer_accept( struct file_transfer *ft ) +static void prpl_xfer_accept(struct file_transfer *ft) { struct prpl_xfer_data *px = ft->data; - purple_xfer_request_accepted( px->xfer, NULL ); - prpl_xfer_write_request( ft ); + + purple_xfer_request_accepted(px->xfer, NULL); + prpl_xfer_write_request(ft); } -static void prpl_xfer_canceled( struct file_transfer *ft, char *reason ) +static void prpl_xfer_canceled(struct file_transfer *ft, char *reason) { struct prpl_xfer_data *px = ft->data; - purple_xfer_request_denied( px->xfer ); + + purple_xfer_request_denied(px->xfer); } -static void prplcb_xfer_new( PurpleXfer *xfer ) +static void prplcb_xfer_new(PurpleXfer *xfer) { - if( purple_xfer_get_type( xfer ) == PURPLE_XFER_RECEIVE ) - { - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); - + if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { + struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); + xfer->ui_data = px; px->xfer = xfer; - px->fn = mktemp( g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ) ); + px->fn = mktemp(g_strdup("/tmp/bitlbee-purple-ft.XXXXXX")); px->fd = -1; - px->ic = purple_ic_by_pa( xfer->account ); - - purple_xfer_set_local_filename( xfer, px->fn ); - + px->ic = purple_ic_by_pa(xfer->account); + + purple_xfer_set_local_filename(xfer, px->fn); + /* Sadly the xfer struct is still empty ATM so come back after the caller is done. */ - b_timeout_add( 0, prplcb_xfer_new_send_cb, xfer ); - } - else - { + b_timeout_add(0, prplcb_xfer_new_send_cb, xfer); + } else { struct file_transfer *ft = next_ft; struct prpl_xfer_data *px = ft->data; - + xfer->ui_data = px; px->xfer = xfer; - + next_ft = NULL; } } -static gboolean prplcb_xfer_new_send_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond) { PurpleXfer *xfer = data; - struct im_connection *ic = purple_ic_by_pa( xfer->account ); + struct im_connection *ic = purple_ic_by_pa(xfer->account); struct prpl_xfer_data *px = xfer->ui_data; PurpleBuddy *buddy; const char *who; - - buddy = purple_find_buddy( xfer->account, xfer->who ); - who = buddy ? purple_buddy_get_name( buddy ) : xfer->who; - + + buddy = purple_find_buddy(xfer->account, xfer->who); + who = buddy ? purple_buddy_get_name(buddy) : xfer->who; + /* TODO(wilmer): After spreading some more const goodness in BitlBee, remove the evil cast below. */ - px->ft = imcb_file_send_start( ic, (char*) who, xfer->filename, xfer->size ); + px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size); px->ft->data = px; - + px->ft->accept = prpl_xfer_accept; px->ft->canceled = prpl_xfer_canceled; px->ft->write_request = prpl_xfer_write_request; - + return FALSE; } -gboolean try_write_to_ui( gpointer data, gint fd, b_input_condition cond ) +gboolean try_write_to_ui(gpointer data, gint fd, b_input_condition cond) { struct file_transfer *ft = data; struct prpl_xfer_data *px = ft->data; struct stat fs; off_t tx_bytes; - + /* If we don't have the file opened yet, there's no data so wait. */ - if( px->fd < 0 || !px->ui_wants_data ) + if (px->fd < 0 || !px->ui_wants_data) { return FALSE; - - tx_bytes = lseek( px->fd, 0, SEEK_CUR ); - fstat( px->fd, &fs ); - - if( fs.st_size > tx_bytes ) - { + } + + tx_bytes = lseek(px->fd, 0, SEEK_CUR); + fstat(px->fd, &fs); + + if (fs.st_size > tx_bytes) { char buf[1024]; - size_t n = MIN( fs.st_size - tx_bytes, sizeof( buf ) ); - - if( read( px->fd, buf, n ) == n && ft->write( ft, buf, n ) ) - { + size_t n = MIN(fs.st_size - tx_bytes, sizeof(buf)); + + if (read(px->fd, buf, n) == n && ft->write(ft, buf, n)) { px->ui_wants_data = FALSE; - } - else - { - purple_xfer_cancel_local( px->xfer ); - imcb_file_canceled( px->ic, ft, "Read error" ); + } else { + purple_xfer_cancel_local(px->xfer); + imcb_file_canceled(px->ic, ft, "Read error"); } } - - if( lseek( px->fd, 0, SEEK_CUR ) == px->xfer->size ) - { + + if (lseek(px->fd, 0, SEEK_CUR) == px->xfer->size) { /*purple_xfer_end( px->xfer );*/ - imcb_file_finished( px->ic, ft ); + imcb_file_finished(px->ic, ft); } - + return FALSE; } /* UI calls this when its buffer is empty and wants more data to send to the user. */ -static gboolean prpl_xfer_write_request( struct file_transfer *ft ) +static gboolean prpl_xfer_write_request(struct file_transfer *ft) { struct prpl_xfer_data *px = ft->data; - + px->ui_wants_data = TRUE; - try_write_to_ui( ft, 0, 0 ); - + try_write_to_ui(ft, 0, 0); + return FALSE; } /* Generic (IM<>UI): */ -static void prplcb_xfer_destroy( PurpleXfer *xfer ) +static void prplcb_xfer_destroy(PurpleXfer *xfer) { struct prpl_xfer_data *px = xfer->ui_data; - - g_free( px->fn ); - g_free( px->handle ); - if( px->fd >= 0 ) - close( px->fd ); - g_free( px ); + + g_free(px->fn); + g_free(px->handle); + if (px->fd >= 0) { + close(px->fd); + } + g_free(px); } -static void prplcb_xfer_progress( PurpleXfer *xfer, double percent ) +static void prplcb_xfer_progress(PurpleXfer *xfer, double percent) { struct prpl_xfer_data *px = xfer->ui_data; - - if( px == NULL ) + + if (px == NULL) { return; - - if( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) - { - if( *px->fn ) - { + } + + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { + if (*px->fn) { char *slash; - - unlink( px->fn ); - if( ( slash = strrchr( px->fn, '/' ) ) ) - { + + unlink(px->fn); + if ((slash = strrchr(px->fn, '/'))) { *slash = '\0'; - rmdir( px->fn ); + rmdir(px->fn); } *px->fn = '\0'; } - + return; } - - if( px->fd == -1 && percent > 0 ) - { + + if (px->fd == -1 && percent > 0) { /* Weeeeeeeee, we're getting data! That means the file exists by now so open it and start sending to the UI. */ - px->fd = open( px->fn, O_RDONLY ); - + px->fd = open(px->fn, O_RDONLY); + /* Unlink it now, because we don't need it after this. */ - unlink( px->fn ); + unlink(px->fn); } - - if( percent < 1 ) - try_write_to_ui( px->ft, 0, 0 ); - else + + if (percent < 1) { + try_write_to_ui(px->ft, 0, 0); + } else { /* Another nice problem: If we have the whole file, it only gets closed when we return. Problem: There may still be stuff buffered and not written, we'll only see it after the caller close()s the file. So poll the file after that. */ - b_timeout_add( 0, try_write_to_ui, px->ft ); + b_timeout_add(0, try_write_to_ui, px->ft); + } } -static void prplcb_xfer_cancel_remote( PurpleXfer *xfer ) +static void prplcb_xfer_cancel_remote(PurpleXfer *xfer) { struct prpl_xfer_data *px = xfer->ui_data; - - if( px->ft ) - imcb_file_canceled( px->ic, px->ft, "Canceled by remote end" ); - else + + if (px->ft) { + imcb_file_canceled(px->ic, px->ft, "Canceled by remote end"); + } else { /* px->ft == NULL for sends, because of the two stages. :-/ */ - imcb_error( px->ic, "File transfer cancelled by remote end" ); + imcb_error(px->ic, "File transfer cancelled by remote end"); + } } -static void prplcb_xfer_dbg( PurpleXfer *xfer ) +static void prplcb_xfer_dbg(PurpleXfer *xfer) { - fprintf( stderr, "prplcb_xfer_dbg 0x%p\n", xfer ); + fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer); } /* Sending files (UI->IM): */ -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ); -static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ); +static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len); +static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condition cond); -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ) +void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle) { - struct prpl_xfer_data *px = g_new0( struct prpl_xfer_data, 1 ); + struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1); char *dir, *basename; - + ft->data = px; px->ft = ft; - - dir = g_strdup( "/tmp/bitlbee-purple-ft.XXXXXX" ); - if( !mkdtemp( dir ) ) - { - imcb_error( ic, "Could not create temporary file for file transfer" ); - g_free( px ); - g_free( dir ); + + dir = g_strdup("/tmp/bitlbee-purple-ft.XXXXXX"); + if (!mkdtemp(dir)) { + imcb_error(ic, "Could not create temporary file for file transfer"); + g_free(px); + g_free(dir); return; } - - if( ( basename = strrchr( ft->file_name, '/' ) ) ) + + if ((basename = strrchr(ft->file_name, '/'))) { basename++; - else + } else { basename = ft->file_name; - px->fn = g_strdup_printf( "%s/%s", dir, basename ); - px->fd = open( px->fn, O_WRONLY | O_CREAT, 0600 ); - g_free( dir ); - - if( px->fd < 0 ) - { - imcb_error( ic, "Could not create temporary file for file transfer" ); - g_free( px ); - g_free( px->fn ); + } + px->fn = g_strdup_printf("%s/%s", dir, basename); + px->fd = open(px->fn, O_WRONLY | O_CREAT, 0600); + g_free(dir); + + if (px->fd < 0) { + imcb_error(ic, "Could not create temporary file for file transfer"); + g_free(px); + g_free(px->fn); return; } - + px->ic = ic; - px->handle = g_strdup( handle ); - - imcb_log( ic, "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..." ); - - b_timeout_add( 0, purple_transfer_request_cb, ft ); + px->handle = g_strdup(handle); + + imcb_log(ic, + "Due to libpurple limitations, the file has to be cached locally before proceeding with the actual file transfer. Please wait..."); + + b_timeout_add(0, purple_transfer_request_cb, ft); } -static void purple_transfer_forward( struct file_transfer *ft ) +static void purple_transfer_forward(struct file_transfer *ft) { struct prpl_xfer_data *px = ft->data; PurpleAccount *pa = px->ic->proto_data; - + /* xfer_new() will pick up this variable. It's a hack but we're not multi-threaded anyway. */ next_ft = ft; - serv_send_file( purple_account_get_connection( pa ), px->handle, px->fn ); + serv_send_file(purple_account_get_connection(pa), px->handle, px->fn); } -static gboolean purple_transfer_request_cb( gpointer data, gint fd, b_input_condition cond ) +static gboolean purple_transfer_request_cb(gpointer data, gint fd, b_input_condition cond) { file_transfer_t *ft = data; struct prpl_xfer_data *px = ft->data; - - if( ft->write == NULL ) - { + + if (ft->write == NULL) { ft->write = prpl_xfer_write; - imcb_file_recv_start( px->ic, ft ); + imcb_file_recv_start(px->ic, ft); } - - ft->write_request( ft ); - + + ft->write_request(ft); + return FALSE; } -static gboolean prpl_xfer_write( struct file_transfer *ft, char *buffer, unsigned int len ) +static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len) { struct prpl_xfer_data *px = ft->data; - - if( write( px->fd, buffer, len ) != len ) - { - imcb_file_canceled( px->ic, ft, "Error while writing temporary file" ); + + if (write(px->fd, buffer, len) != len) { + imcb_file_canceled(px->ic, ft, "Error while writing temporary file"); return FALSE; } - - if( lseek( px->fd, 0, SEEK_CUR ) >= ft->file_size ) - { - close( px->fd ); + + if (lseek(px->fd, 0, SEEK_CUR) >= ft->file_size) { + close(px->fd); px->fd = -1; - - purple_transfer_forward( ft ); - imcb_file_finished( px->ic, ft ); + + purple_transfer_forward(ft); + imcb_file_finished(px->ic, ft); px->ft = NULL; + } else { + b_timeout_add(0, purple_transfer_request_cb, ft); } - else - b_timeout_add( 0, purple_transfer_request_cb, ft ); - + return TRUE; } diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index e1f2c2be..aefd353b 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -36,43 +36,49 @@ GSList *purple_connections; libpurple in daemon mode anyway. */ static bee_t *local_bee; -static char *set_eval_display_name( set_t *set, char *value ); +static char *set_eval_display_name(set_t *set, char *value); -struct im_connection *purple_ic_by_pa( PurpleAccount *pa ) +struct im_connection *purple_ic_by_pa(PurpleAccount *pa) { GSList *i; - - for( i = purple_connections; i; i = i->next ) - if( ((struct im_connection *)i->data)->proto_data == pa ) + + for (i = purple_connections; i; i = i->next) { + if (((struct im_connection *) i->data)->proto_data == pa) { return i->data; - + } + } + return NULL; } -static struct im_connection *purple_ic_by_gc( PurpleConnection *gc ) +static struct im_connection *purple_ic_by_gc(PurpleConnection *gc) { - return purple_ic_by_pa( purple_connection_get_account( gc ) ); + return purple_ic_by_pa(purple_connection_get_account(gc)); } -static gboolean purple_menu_cmp( const char *a, const char *b ) +static gboolean purple_menu_cmp(const char *a, const char *b) { - while( *a && *b ) - { - while( *a == '_' ) a ++; - while( *b == '_' ) b ++; - if( g_ascii_tolower( *a ) != g_ascii_tolower( *b ) ) + while (*a && *b) { + while (*a == '_') { + a++; + } + while (*b == '_') { + b++; + } + if (g_ascii_tolower(*a) != g_ascii_tolower(*b)) { return FALSE; - - a ++; - b ++; + } + + a++; + b++; } - - return ( *a == '\0' && *b == '\0' ); + + return (*a == '\0' && *b == '\0'); } -static void purple_init( account_t *acc ) +static void purple_init(account_t *acc) { - PurplePlugin *prpl = purple_plugins_find_with_id( (char*) acc->prpl->data ); + PurplePlugin *prpl = purple_plugins_find_with_id((char *) acc->prpl->data); PurplePluginProtocolInfo *pi = prpl->info->extra_info; PurpleAccount *pa; GList *i, *st; @@ -80,45 +86,43 @@ static void purple_init( account_t *acc ) char help_title[64]; GString *help; static gboolean dir_fixed = FALSE; - + /* Layer violation coming up: Making an exception for libpurple here. Dig in the IRC state a bit to get a username. Ideally we should check if s/he identified but this info doesn't seem *that* important. It's just that fecking libpurple can't *not* store this shit. - + Remember that libpurple is not really meant to be used on public servers anyway! */ - if( !dir_fixed ) - { + if (!dir_fixed) { irc_t *irc = acc->bee->ui_data; char *dir; - - dir = g_strdup_printf( "%s/purple/%s", global.conf->configdir, irc->user->nick ); - purple_util_set_user_dir( dir ); - g_free( dir ); - + + dir = g_strdup_printf("%s/purple/%s", global.conf->configdir, irc->user->nick); + purple_util_set_user_dir(dir); + g_free(dir); + purple_blist_load(); purple_prefs_load(); dir_fixed = TRUE; } - - help = g_string_new( "" ); - g_string_printf( help, "BitlBee libpurple module %s (%s).\n\nSupported settings:", - (char*) acc->prpl->name, prpl->info->name ); - - if( pi->user_splits ) - { + + help = g_string_new(""); + g_string_printf(help, "BitlBee libpurple module %s (%s).\n\nSupported settings:", + (char *) acc->prpl->name, prpl->info->name); + + if (pi->user_splits) { GList *l; - g_string_append_printf( help, "\n* username: Username" ); - for( l = pi->user_splits; l; l = l->next ) - g_string_append_printf( help, "%c%s", - purple_account_user_split_get_separator( l->data ), - purple_account_user_split_get_text( l->data ) ); + g_string_append_printf(help, "\n* username: Username"); + for (l = pi->user_splits; l; l = l->next) { + g_string_append_printf(help, "%c%s", + purple_account_user_split_get_separator(l->data), + purple_account_user_split_get_text(l->data)); + } } - + /* Convert all protocol_options into per-account setting variables. */ - for( i = pi->protocol_options; i; i = i->next ) - { + for (i = pi->protocol_options; i; i = i->next) { PurpleAccountOption *o = i->data; const char *name; char *def = NULL; @@ -126,422 +130,413 @@ static void purple_init( account_t *acc ) void *eval_data = NULL; GList *io = NULL; GSList *opts = NULL; - - name = purple_account_option_get_setting( o ); - - switch( purple_account_option_get_type( o ) ) - { + + name = purple_account_option_get_setting(o); + + switch (purple_account_option_get_type(o)) { case PURPLE_PREF_STRING: - def = g_strdup( purple_account_option_get_default_string( o ) ); - - g_string_append_printf( help, "\n* %s (%s), %s, default: %s", - name, purple_account_option_get_text( o ), - "string", def ); - + def = g_strdup(purple_account_option_get_default_string(o)); + + g_string_append_printf(help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text(o), + "string", def); + break; - + case PURPLE_PREF_INT: - def = g_strdup_printf( "%d", purple_account_option_get_default_int( o ) ); + def = g_strdup_printf("%d", purple_account_option_get_default_int(o)); eval = set_eval_int; - - g_string_append_printf( help, "\n* %s (%s), %s, default: %s", - name, purple_account_option_get_text( o ), - "integer", def ); - + + g_string_append_printf(help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text(o), + "integer", def); + break; - + case PURPLE_PREF_BOOLEAN: - if( purple_account_option_get_default_bool( o ) ) - def = g_strdup( "true" ); - else - def = g_strdup( "false" ); + if (purple_account_option_get_default_bool(o)) { + def = g_strdup("true"); + } else { + def = g_strdup("false"); + } eval = set_eval_bool; - - g_string_append_printf( help, "\n* %s (%s), %s, default: %s", - name, purple_account_option_get_text( o ), - "boolean", def ); - + + g_string_append_printf(help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text(o), + "boolean", def); + break; - + case PURPLE_PREF_STRING_LIST: - def = g_strdup( purple_account_option_get_default_list_value( o ) ); - - g_string_append_printf( help, "\n* %s (%s), %s, default: %s", - name, purple_account_option_get_text( o ), - "list", def ); - g_string_append( help, "\n Possible values: " ); - - for( io = purple_account_option_get_list( o ); io; io = io->next ) - { + def = g_strdup(purple_account_option_get_default_list_value(o)); + + g_string_append_printf(help, "\n* %s (%s), %s, default: %s", + name, purple_account_option_get_text(o), + "list", def); + g_string_append(help, "\n Possible values: "); + + for (io = purple_account_option_get_list(o); io; io = io->next) { PurpleKeyValuePair *kv = io->data; - opts = g_slist_append( opts, kv->value ); + opts = g_slist_append(opts, kv->value); /* TODO: kv->value is not a char*, WTF? */ - if( strcmp( kv->value, kv->key ) != 0 ) - g_string_append_printf( help, "%s (%s), ", (char*) kv->value, kv->key ); - else - g_string_append_printf( help, "%s, ", (char*) kv->value ); + if (strcmp(kv->value, kv->key) != 0) { + g_string_append_printf(help, "%s (%s), ", (char *) kv->value, kv->key); + } else { + g_string_append_printf(help, "%s, ", (char *) kv->value); + } } - g_string_truncate( help, help->len - 2 ); + g_string_truncate(help, help->len - 2); eval = set_eval_list; eval_data = opts; - + break; - + default: /** No way to talk to the user right now, invent one when this becomes important. irc_rootmsg( acc->irc, "Setting with unknown type: %s (%d) Expect stuff to break..\n", name, purple_account_option_get_type( o ) ); */ - g_string_append_printf( help, "\n* [%s] UNSUPPORTED (type %d)", - name, purple_account_option_get_type( o ) ); + g_string_append_printf(help, "\n* [%s] UNSUPPORTED (type %d)", + name, purple_account_option_get_type(o)); name = NULL; } - - if( name != NULL ) - { - s = set_add( &acc->set, name, def, eval, acc ); + + if (name != NULL) { + s = set_add(&acc->set, name, def, eval, acc); s->flags |= ACC_SET_OFFLINE_ONLY; s->eval_data = eval_data; - g_free( def ); + g_free(def); } } - - g_snprintf( help_title, sizeof( help_title ), "purple %s", (char*) acc->prpl->name ); - help_add_mem( &global.help, help_title, help->str ); - g_string_free( help, TRUE ); - - s = set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc ); + + g_snprintf(help_title, sizeof(help_title), "purple %s", (char *) acc->prpl->name); + help_add_mem(&global.help, help_title, help->str); + g_string_free(help, TRUE); + + s = set_add(&acc->set, "display_name", NULL, set_eval_display_name, acc); s->flags |= ACC_SET_ONLINE_ONLY; - - if( pi->options & OPT_PROTO_MAIL_CHECK ) - { - s = set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); + + if (pi->options & OPT_PROTO_MAIL_CHECK) { + s = set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc); s->flags |= ACC_SET_OFFLINE_ONLY; } - - if( strcmp( prpl->info->name, "Gadu-Gadu" ) == 0 ) - s = set_add( &acc->set, "gg_sync_contacts", "true", set_eval_bool, acc ); - + + if (strcmp(prpl->info->name, "Gadu-Gadu") == 0) { + s = set_add(&acc->set, "gg_sync_contacts", "true", set_eval_bool, acc); + } + /* Go through all away states to figure out if away/status messages are possible. */ - pa = purple_account_new( acc->user, (char*) acc->prpl->data ); - for( st = purple_account_get_status_types( pa ); st; st = st->next ) - { - PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data ); - - if( prim == PURPLE_STATUS_AVAILABLE ) - { - if( purple_status_type_get_attr( st->data, "message" ) ) + pa = purple_account_new(acc->user, (char *) acc->prpl->data); + for (st = purple_account_get_status_types(pa); st; st = st->next) { + PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data); + + if (prim == PURPLE_STATUS_AVAILABLE) { + if (purple_status_type_get_attr(st->data, "message")) { acc->flags |= ACC_FLAG_STATUS_MESSAGE; - } - else if( prim != PURPLE_STATUS_OFFLINE ) - { - if( purple_status_type_get_attr( st->data, "message" ) ) + } + } else if (prim != PURPLE_STATUS_OFFLINE) { + if (purple_status_type_get_attr(st->data, "message")) { acc->flags |= ACC_FLAG_AWAY_MESSAGE; + } } } - purple_accounts_remove( pa ); + purple_accounts_remove(pa); } -static void purple_sync_settings( account_t *acc, PurpleAccount *pa ) +static void purple_sync_settings(account_t *acc, PurpleAccount *pa) { - PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); PurplePluginProtocolInfo *pi = prpl->info->extra_info; GList *i; - - for( i = pi->protocol_options; i; i = i->next ) - { + + for (i = pi->protocol_options; i; i = i->next) { PurpleAccountOption *o = i->data; const char *name; set_t *s; - - name = purple_account_option_get_setting( o ); - s = set_find( &acc->set, name ); - if( s->value == NULL ) + + name = purple_account_option_get_setting(o); + s = set_find(&acc->set, name); + if (s->value == NULL) { continue; - - switch( purple_account_option_get_type( o ) ) - { + } + + switch (purple_account_option_get_type(o)) { case PURPLE_PREF_STRING: case PURPLE_PREF_STRING_LIST: - purple_account_set_string( pa, name, set_getstr( &acc->set, name ) ); + purple_account_set_string(pa, name, set_getstr(&acc->set, name)); break; - + case PURPLE_PREF_INT: - purple_account_set_int( pa, name, set_getint( &acc->set, name ) ); + purple_account_set_int(pa, name, set_getint(&acc->set, name)); break; - + case PURPLE_PREF_BOOLEAN: - purple_account_set_bool( pa, name, set_getbool( &acc->set, name ) ); + purple_account_set_bool(pa, name, set_getbool(&acc->set, name)); break; - + default: break; } } - - if( pi->options & OPT_PROTO_MAIL_CHECK ) - purple_account_set_check_mail( pa, set_getbool( &acc->set, "mail_notifications" ) ); + + if (pi->options & OPT_PROTO_MAIL_CHECK) { + purple_account_set_check_mail(pa, set_getbool(&acc->set, "mail_notifications")); + } } -static void purple_login( account_t *acc ) +static void purple_login(account_t *acc) { - struct im_connection *ic = imcb_new( acc ); + struct im_connection *ic = imcb_new(acc); PurpleAccount *pa; - - if( ( local_bee != NULL && local_bee != acc->bee ) || - ( global.conf->runmode == RUNMODE_DAEMON && !getenv( "BITLBEE_DEBUG" ) ) ) - { - imcb_error( ic, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " - "Please use inetd or ForkDaemon mode instead." ); - imc_logout( ic, FALSE ); + + if ((local_bee != NULL && local_bee != acc->bee) || + (global.conf->runmode == RUNMODE_DAEMON && !getenv("BITLBEE_DEBUG"))) { + imcb_error(ic, "Daemon mode detected. Do *not* try to use libpurple in daemon mode! " + "Please use inetd or ForkDaemon mode instead."); + imc_logout(ic, FALSE); return; } local_bee = acc->bee; - + /* For now this is needed in the _connected() handlers if using GLib event handling, to make sure we're not handling events on dead connections. */ - purple_connections = g_slist_prepend( purple_connections, ic ); - - ic->proto_data = pa = purple_account_new( acc->user, (char*) acc->prpl->data ); - purple_account_set_password( pa, acc->pass ); - purple_sync_settings( acc, pa ); - - purple_account_set_enabled( pa, "BitlBee", TRUE ); + purple_connections = g_slist_prepend(purple_connections, ic); + + ic->proto_data = pa = purple_account_new(acc->user, (char *) acc->prpl->data); + purple_account_set_password(pa, acc->pass); + purple_sync_settings(acc, pa); + + purple_account_set_enabled(pa, "BitlBee", TRUE); } -static void purple_logout( struct im_connection *ic ) +static void purple_logout(struct im_connection *ic) { PurpleAccount *pa = ic->proto_data; - - purple_account_set_enabled( pa, "BitlBee", FALSE ); - purple_connections = g_slist_remove( purple_connections, ic ); - purple_accounts_remove( pa ); + + purple_account_set_enabled(pa, "BitlBee", FALSE); + purple_connections = g_slist_remove(purple_connections, ic); + purple_accounts_remove(pa); } -static int purple_buddy_msg( struct im_connection *ic, char *who, char *message, int flags ) +static int purple_buddy_msg(struct im_connection *ic, char *who, char *message, int flags) { PurpleConversation *conv; - - if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, - who, ic->proto_data ) ) == NULL ) - { - conv = purple_conversation_new( PURPLE_CONV_TYPE_IM, - ic->proto_data, who ); + + if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + who, ic->proto_data)) == NULL) { + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, + ic->proto_data, who); } - - purple_conv_im_send( purple_conversation_get_im_data( conv ), message ); - + + purple_conv_im_send(purple_conversation_get_im_data(conv), message); + return 1; } -static GList *purple_away_states( struct im_connection *ic ) +static GList *purple_away_states(struct im_connection *ic) { PurpleAccount *pa = ic->proto_data; GList *st, *ret = NULL; - - for( st = purple_account_get_status_types( pa ); st; st = st->next ) - { - PurpleStatusPrimitive prim = purple_status_type_get_primitive( st->data ); - if( prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE ) - ret = g_list_append( ret, (void*) purple_status_type_get_name( st->data ) ); + + for (st = purple_account_get_status_types(pa); st; st = st->next) { + PurpleStatusPrimitive prim = purple_status_type_get_primitive(st->data); + if (prim != PURPLE_STATUS_AVAILABLE && prim != PURPLE_STATUS_OFFLINE) { + ret = g_list_append(ret, (void *) purple_status_type_get_name(st->data)); + } } - + return ret; } -static void purple_set_away( struct im_connection *ic, char *state_txt, char *message ) +static void purple_set_away(struct im_connection *ic, char *state_txt, char *message) { PurpleAccount *pa = ic->proto_data; - GList *status_types = purple_account_get_status_types( pa ), *st; + GList *status_types = purple_account_get_status_types(pa), *st; PurpleStatusType *pst = NULL; GList *args = NULL; - - for( st = status_types; st; st = st->next ) - { + + for (st = status_types; st; st = st->next) { pst = st->data; - - if( state_txt == NULL && - purple_status_type_get_primitive( pst ) == PURPLE_STATUS_AVAILABLE ) + + if (state_txt == NULL && + purple_status_type_get_primitive(pst) == PURPLE_STATUS_AVAILABLE) { break; + } - if( state_txt != NULL && - g_strcasecmp( state_txt, purple_status_type_get_name( pst ) ) == 0 ) + if (state_txt != NULL && + g_strcasecmp(state_txt, purple_status_type_get_name(pst)) == 0) { break; + } } - - if( message && purple_status_type_get_attr( pst, "message" ) ) - { - args = g_list_append( args, "message" ); - args = g_list_append( args, message ); + + if (message && purple_status_type_get_attr(pst, "message")) { + args = g_list_append(args, "message"); + args = g_list_append(args, message); } - - purple_account_set_status_list( pa, st ? purple_status_type_get_id( pst ) : "away", - TRUE, args ); - g_list_free( args ); + purple_account_set_status_list(pa, st ? purple_status_type_get_id(pst) : "away", + TRUE, args); + + g_list_free(args); } -static char *set_eval_display_name( set_t *set, char *value ) +static char *set_eval_display_name(set_t *set, char *value) { account_t *acc = set->data; struct im_connection *ic = acc->ic; - - if( ic ) - imcb_log( ic, "Changing display_name not currently supported with libpurple!" ); - + + if (ic) { + imcb_log(ic, "Changing display_name not currently supported with libpurple!"); + } + return NULL; } /* Bad bad gadu-gadu, not saving buddy list by itself */ -static void purple_gg_buddylist_export( PurpleConnection *gc ) +static void purple_gg_buddylist_export(PurpleConnection *gc) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - if( set_getstr( &ic->acc->set, "gg_sync_contacts" ) ) - { - GList *actions = gc->prpl->info->actions( gc->prpl, gc ); + struct im_connection *ic = purple_ic_by_gc(gc); + + if (set_getstr(&ic->acc->set, "gg_sync_contacts")) { + GList *actions = gc->prpl->info->actions(gc->prpl, gc); GList *p; - for( p = g_list_first(actions); p; p = p->next ) - { - if( ((PurplePluginAction*)p->data) && - purple_menu_cmp( ((PurplePluginAction*)p->data)->label, "Upload buddylist to Server" ) == 0) - { + for (p = g_list_first(actions); p; p = p->next) { + if (((PurplePluginAction *) p->data) && + purple_menu_cmp(((PurplePluginAction *) p->data)->label, + "Upload buddylist to Server") == 0) { PurplePluginAction action; action.plugin = gc->prpl; action.context = gc; action.user_data = NULL; - ((PurplePluginAction*)p->data)->callback(&action); + ((PurplePluginAction *) p->data)->callback(&action); break; } } - g_list_free( actions ); + g_list_free(actions); } } -static void purple_gg_buddylist_import( PurpleConnection *gc ) +static void purple_gg_buddylist_import(PurpleConnection *gc) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - if( set_getstr( &ic->acc->set, "gg_sync_contacts" ) ) - { - GList *actions = gc->prpl->info->actions( gc->prpl, gc ); + struct im_connection *ic = purple_ic_by_gc(gc); + + if (set_getstr(&ic->acc->set, "gg_sync_contacts")) { + GList *actions = gc->prpl->info->actions(gc->prpl, gc); GList *p; - for( p = g_list_first(actions); p; p = p->next ) - { - if( ((PurplePluginAction*)p->data) && - purple_menu_cmp( ((PurplePluginAction*)p->data)->label, "Download buddylist from Server" ) == 0 ) - { + for (p = g_list_first(actions); p; p = p->next) { + if (((PurplePluginAction *) p->data) && + purple_menu_cmp(((PurplePluginAction *) p->data)->label, + "Download buddylist from Server") == 0) { PurplePluginAction action; action.plugin = gc->prpl; action.context = gc; action.user_data = NULL; - ((PurplePluginAction*)p->data)->callback(&action); + ((PurplePluginAction *) p->data)->callback(&action); break; } } - g_list_free( actions ); + g_list_free(actions); } } -static void purple_add_buddy( struct im_connection *ic, char *who, char *group ) +static void purple_add_buddy(struct im_connection *ic, char *who, char *group) { PurpleBuddy *pb; PurpleGroup *pg = NULL; - - if( group && !( pg = purple_find_group( group ) ) ) - { - pg = purple_group_new( group ); - purple_blist_add_group( pg, NULL ); + + if (group && !(pg = purple_find_group(group))) { + pg = purple_group_new(group); + purple_blist_add_group(pg, NULL); } - - pb = purple_buddy_new( (PurpleAccount*) ic->proto_data, who, NULL ); - purple_blist_add_buddy( pb, NULL, pg, NULL ); - purple_account_add_buddy( (PurpleAccount*) ic->proto_data, pb ); - purple_gg_buddylist_export( ((PurpleAccount*)ic->proto_data)->gc ); + pb = purple_buddy_new((PurpleAccount *) ic->proto_data, who, NULL); + purple_blist_add_buddy(pb, NULL, pg, NULL); + purple_account_add_buddy((PurpleAccount *) ic->proto_data, pb); + + purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc); } -static void purple_remove_buddy( struct im_connection *ic, char *who, char *group ) +static void purple_remove_buddy(struct im_connection *ic, char *who, char *group) { PurpleBuddy *pb; - - pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who ); - if( pb != NULL ) - { + + pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who); + if (pb != NULL) { PurpleGroup *group; - - group = purple_buddy_get_group( pb ); - purple_account_remove_buddy( (PurpleAccount*) ic->proto_data, pb, group ); - - purple_blist_remove_buddy( pb ); + + group = purple_buddy_get_group(pb); + purple_account_remove_buddy((PurpleAccount *) ic->proto_data, pb, group); + + purple_blist_remove_buddy(pb); } - purple_gg_buddylist_export( ((PurpleAccount*)ic->proto_data)->gc ); + purple_gg_buddylist_export(((PurpleAccount *) ic->proto_data)->gc); } -static void purple_add_permit( struct im_connection *ic, char *who ) +static void purple_add_permit(struct im_connection *ic, char *who) { PurpleAccount *pa = ic->proto_data; - - purple_privacy_permit_add( pa, who, FALSE ); + + purple_privacy_permit_add(pa, who, FALSE); } -static void purple_add_deny( struct im_connection *ic, char *who ) +static void purple_add_deny(struct im_connection *ic, char *who) { PurpleAccount *pa = ic->proto_data; - - purple_privacy_deny_add( pa, who, FALSE ); + + purple_privacy_deny_add(pa, who, FALSE); } -static void purple_rem_permit( struct im_connection *ic, char *who ) +static void purple_rem_permit(struct im_connection *ic, char *who) { PurpleAccount *pa = ic->proto_data; - - purple_privacy_permit_remove( pa, who, FALSE ); + + purple_privacy_permit_remove(pa, who, FALSE); } -static void purple_rem_deny( struct im_connection *ic, char *who ) +static void purple_rem_deny(struct im_connection *ic, char *who) { PurpleAccount *pa = ic->proto_data; - - purple_privacy_deny_remove( pa, who, FALSE ); + + purple_privacy_deny_remove(pa, who, FALSE); } -static void purple_get_info( struct im_connection *ic, char *who ) +static void purple_get_info(struct im_connection *ic, char *who) { - serv_get_info( purple_account_get_connection( ic->proto_data ), who ); + serv_get_info(purple_account_get_connection(ic->proto_data), who); } -static void purple_keepalive( struct im_connection *ic ) +static void purple_keepalive(struct im_connection *ic) { } -static int purple_send_typing( struct im_connection *ic, char *who, int flags ) +static int purple_send_typing(struct im_connection *ic, char *who, int flags) { PurpleTypingState state = PURPLE_NOT_TYPING; PurpleAccount *pa = ic->proto_data; - - if( flags & OPT_TYPING ) + + if (flags & OPT_TYPING) { state = PURPLE_TYPING; - else if( flags & OPT_THINKING ) + } else if (flags & OPT_THINKING) { state = PURPLE_TYPED; - - serv_send_typing( purple_account_get_connection( pa ), who, state ); - + } + + serv_send_typing(purple_account_get_connection(pa), who, state); + return 1; } -static void purple_chat_msg( struct groupchat *gc, char *message, int flags ) +static void purple_chat_msg(struct groupchat *gc, char *message, int flags) { PurpleConversation *pc = gc->data; - - purple_conv_chat_send( purple_conversation_get_chat_data( pc ), message ); + + purple_conv_chat_send(purple_conversation_get_chat_data(pc), message); } -struct groupchat *purple_chat_with( struct im_connection *ic, char *who ) +struct groupchat *purple_chat_with(struct im_connection *ic, char *who) { /* No, "of course" this won't work this way. Or in fact, it almost does, but it only lets you send msgs to it, you won't receive @@ -550,133 +545,137 @@ struct groupchat *purple_chat_with( struct im_connection *ic, char *who ) PurpleConversation *pc; PurpleConvChat *pcc; struct groupchat *gc; - + gc = imcb_chat_new( ic, "BitlBee-libpurple groupchat" ); gc->data = pc = purple_conversation_new( PURPLE_CONV_TYPE_CHAT, pa, "BitlBee-libpurple groupchat" ); pc->ui_data = gc; - + pcc = PURPLE_CONV_CHAT( pc ); purple_conv_chat_add_user( pcc, ic->acc->user, "", 0, TRUE ); purple_conv_chat_invite_user( pcc, who, "Please join my chat", FALSE ); //purple_conv_chat_add_user( pcc, who, "", 0, TRUE ); */ - + /* There went my nice afternoon. :-( */ - + PurpleAccount *pa = ic->proto_data; - PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); PurplePluginProtocolInfo *pi = prpl->info->extra_info; - PurpleBuddy *pb = purple_find_buddy( (PurpleAccount*) ic->proto_data, who ); + PurpleBuddy *pb = purple_find_buddy((PurpleAccount *) ic->proto_data, who); PurpleMenuAction *mi; GList *menu; + void (*callback)(PurpleBlistNode *, gpointer); /* FFFFFFFFFFFFFUUUUUUUUUUUUUU */ - - if( !pb || !pi || !pi->blist_node_menu ) + + if (!pb || !pi || !pi->blist_node_menu) { return NULL; - - menu = pi->blist_node_menu( &pb->node ); - while( menu ) - { + } + + menu = pi->blist_node_menu(&pb->node); + while (menu) { mi = menu->data; - if( purple_menu_cmp( mi->label, "initiate chat" ) || - purple_menu_cmp( mi->label, "initiate conference" ) ) + if (purple_menu_cmp(mi->label, "initiate chat") || + purple_menu_cmp(mi->label, "initiate conference")) { break; + } menu = menu->next; } - - if( menu == NULL ) + + if (menu == NULL) { return NULL; - + } + /* Call the fucker. */ - callback = (void*) mi->callback; - callback( &pb->node, menu->data ); - + callback = (void *) mi->callback; + callback(&pb->node, menu->data); + return NULL; } -void purple_chat_invite( struct groupchat *gc, char *who, char *message ) +void purple_chat_invite(struct groupchat *gc, char *who, char *message) { PurpleConversation *pc = gc->data; - PurpleConvChat *pcc = PURPLE_CONV_CHAT( pc ); - - serv_chat_invite( purple_account_get_connection( gc->ic->proto_data ), - purple_conv_chat_get_id( pcc ), - message && *message ? message : "Please join my chat", - who ); + PurpleConvChat *pcc = PURPLE_CONV_CHAT(pc); + + serv_chat_invite(purple_account_get_connection(gc->ic->proto_data), + purple_conv_chat_get_id(pcc), + message && *message ? message : "Please join my chat", + who); } -void purple_chat_kick( struct groupchat *gc, char *who, const char *message ) +void purple_chat_kick(struct groupchat *gc, char *who, const char *message) { PurpleConversation *pc = gc->data; - char *str = g_strdup_printf( "kick %s %s", who, message ); - purple_conversation_do_command( pc, str, NULL, NULL ); - g_free( str ); + char *str = g_strdup_printf("kick %s %s", who, message); + + purple_conversation_do_command(pc, str, NULL, NULL); + g_free(str); } -void purple_chat_leave( struct groupchat *gc ) +void purple_chat_leave(struct groupchat *gc) { PurpleConversation *pc = gc->data; - - purple_conversation_destroy( pc ); + + purple_conversation_destroy(pc); } -struct groupchat *purple_chat_join( struct im_connection *ic, const char *room, const char *nick, const char *password, set_t **sets ) +struct groupchat *purple_chat_join(struct im_connection *ic, const char *room, const char *nick, const char *password, + set_t **sets) { PurpleAccount *pa = ic->proto_data; - PurplePlugin *prpl = purple_plugins_find_with_id( pa->protocol_id ); + PurplePlugin *prpl = purple_plugins_find_with_id(pa->protocol_id); PurplePluginProtocolInfo *pi = prpl->info->extra_info; GHashTable *chat_hash; PurpleConversation *conv; GList *info, *l; - - if( !pi->chat_info || !pi->chat_info_defaults || - !( info = pi->chat_info( purple_account_get_connection( pa ) ) ) ) - { - imcb_error( ic, "Joining chatrooms not supported by this protocol" ); + + if (!pi->chat_info || !pi->chat_info_defaults || + !(info = pi->chat_info(purple_account_get_connection(pa)))) { + imcb_error(ic, "Joining chatrooms not supported by this protocol"); return NULL; } - - if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_CHAT, room, pa ) ) ) - purple_conversation_destroy( conv ); - - chat_hash = pi->chat_info_defaults( purple_account_get_connection( pa ), room ); - - for( l = info; l; l = l->next ) - { + + if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, room, pa))) { + purple_conversation_destroy(conv); + } + + chat_hash = pi->chat_info_defaults(purple_account_get_connection(pa), room); + + for (l = info; l; l = l->next) { struct proto_chat_entry *pce = l->data; - - if( strcmp( pce->identifier, "handle" ) == 0 ) - g_hash_table_replace( chat_hash, "handle", g_strdup( nick ) ); - else if( strcmp( pce->identifier, "password" ) == 0 ) - g_hash_table_replace( chat_hash, "password", g_strdup( password ) ); - else if( strcmp( pce->identifier, "passwd" ) == 0 ) - g_hash_table_replace( chat_hash, "passwd", g_strdup( password ) ); + + if (strcmp(pce->identifier, "handle") == 0) { + g_hash_table_replace(chat_hash, "handle", g_strdup(nick)); + } else if (strcmp(pce->identifier, "password") == 0) { + g_hash_table_replace(chat_hash, "password", g_strdup(password)); + } else if (strcmp(pce->identifier, "passwd") == 0) { + g_hash_table_replace(chat_hash, "passwd", g_strdup(password)); + } } - - serv_join_chat( purple_account_get_connection( pa ), chat_hash ); - + + serv_join_chat(purple_account_get_connection(pa), chat_hash); + return NULL; } -void purple_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *handle ); +void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle); static void purple_ui_init(); GHashTable *prplcb_ui_info() { static GHashTable *ret; - - if( ret == NULL ) - { + + if (ret == NULL) { ret = g_hash_table_new(g_str_hash, g_str_equal); - g_hash_table_insert( ret, "name", "BitlBee" ); - g_hash_table_insert( ret, "version", BITLBEE_VERSION ); + g_hash_table_insert(ret, "name", "BitlBee"); + g_hash_table_insert(ret, "version", BITLBEE_VERSION); } - + return ret; } -static PurpleCoreUiOps bee_core_uiops = +static PurpleCoreUiOps bee_core_uiops = { NULL, NULL, @@ -685,61 +684,62 @@ static PurpleCoreUiOps bee_core_uiops = prplcb_ui_info, }; -static void prplcb_conn_progress( PurpleConnection *gc, const char *text, size_t step, size_t step_count ) +static void prplcb_conn_progress(PurpleConnection *gc, const char *text, size_t step, size_t step_count) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - imcb_log( ic, "%s", text ); + struct im_connection *ic = purple_ic_by_gc(gc); + + imcb_log(ic, "%s", text); } -static void prplcb_conn_connected( PurpleConnection *gc ) +static void prplcb_conn_connected(PurpleConnection *gc) { - struct im_connection *ic = purple_ic_by_gc( gc ); + struct im_connection *ic = purple_ic_by_gc(gc); const char *dn; set_t *s; - - imcb_connected( ic ); - - if( ( dn = purple_connection_get_display_name( gc ) ) && - ( s = set_find( &ic->acc->set, "display_name" ) ) ) - { - g_free( s->value ); - s->value = g_strdup( dn ); + + imcb_connected(ic); + + if ((dn = purple_connection_get_display_name(gc)) && + (s = set_find(&ic->acc->set, "display_name"))) { + g_free(s->value); + s->value = g_strdup(dn); } // user list needs to be requested for Gadu-Gadu - purple_gg_buddylist_import( gc ); - - if( gc->flags & PURPLE_CONNECTION_HTML ) + purple_gg_buddylist_import(gc); + + if (gc->flags & PURPLE_CONNECTION_HTML) { ic->flags |= OPT_DOES_HTML; + } } -static void prplcb_conn_disconnected( PurpleConnection *gc ) +static void prplcb_conn_disconnected(PurpleConnection *gc) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - if( ic != NULL ) - { - imc_logout( ic, !gc->wants_to_die ); + struct im_connection *ic = purple_ic_by_gc(gc); + + if (ic != NULL) { + imc_logout(ic, !gc->wants_to_die); } } -static void prplcb_conn_notice( PurpleConnection *gc, const char *text ) +static void prplcb_conn_notice(PurpleConnection *gc, const char *text) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - if( ic != NULL ) - imcb_log( ic, "%s", text ); + struct im_connection *ic = purple_ic_by_gc(gc); + + if (ic != NULL) { + imcb_log(ic, "%s", text); + } } -static void prplcb_conn_report_disconnect_reason( PurpleConnection *gc, PurpleConnectionError reason, const char *text ) +static void prplcb_conn_report_disconnect_reason(PurpleConnection *gc, PurpleConnectionError reason, const char *text) { - struct im_connection *ic = purple_ic_by_gc( gc ); - + struct im_connection *ic = purple_ic_by_gc(gc); + /* PURPLE_CONNECTION_ERROR_NAME_IN_USE means concurrent login, should probably handle that. */ - if( ic != NULL ) - imcb_error( ic, "%s", text ); + if (ic != NULL) { + imcb_error(ic, "%s", text); + } } static PurpleConnectionUiOps bee_conn_uiops = @@ -754,71 +754,73 @@ static PurpleConnectionUiOps bee_conn_uiops = prplcb_conn_report_disconnect_reason, }; -static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node ) +static void prplcb_blist_update(PurpleBuddyList *list, PurpleBlistNode *node) { - if( node->type == PURPLE_BLIST_BUDDY_NODE ) - { - PurpleBuddy *bud = (PurpleBuddy*) node; - PurpleGroup *group = purple_buddy_get_group( bud ); - struct im_connection *ic = purple_ic_by_pa( bud->account ); + if (node->type == PURPLE_BLIST_BUDDY_NODE) { + PurpleBuddy *bud = (PurpleBuddy *) node; + PurpleGroup *group = purple_buddy_get_group(bud); + struct im_connection *ic = purple_ic_by_pa(bud->account); PurpleStatus *as; int flags = 0; - - if( ic == NULL ) + + if (ic == NULL) { return; - - if( bud->server_alias ) - imcb_rename_buddy( ic, bud->name, bud->server_alias ); - else if( bud->alias ) - imcb_rename_buddy( ic, bud->name, bud->alias ); - - if( group ) - imcb_add_buddy( ic, bud->name, purple_group_get_name( group ) ); - - flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0; - flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY; - - as = purple_presence_get_active_status( bud->presence ); - - imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ), - purple_status_get_attr_string( as, "message" ) ); - - imcb_buddy_times( ic, bud->name, - purple_presence_get_login_time( bud->presence ), - purple_presence_get_idle_time( bud->presence ) ); + } + + if (bud->server_alias) { + imcb_rename_buddy(ic, bud->name, bud->server_alias); + } else if (bud->alias) { + imcb_rename_buddy(ic, bud->name, bud->alias); + } + + if (group) { + imcb_add_buddy(ic, bud->name, purple_group_get_name(group)); + } + + flags |= purple_presence_is_online(bud->presence) ? OPT_LOGGED_IN : 0; + flags |= purple_presence_is_available(bud->presence) ? 0 : OPT_AWAY; + + as = purple_presence_get_active_status(bud->presence); + + imcb_buddy_status(ic, bud->name, flags, purple_status_get_name(as), + purple_status_get_attr_string(as, "message")); + + imcb_buddy_times(ic, bud->name, + purple_presence_get_login_time(bud->presence), + purple_presence_get_idle_time(bud->presence)); } } -static void prplcb_blist_new( PurpleBlistNode *node ) +static void prplcb_blist_new(PurpleBlistNode *node) { - if( node->type == PURPLE_BLIST_BUDDY_NODE ) - { - PurpleBuddy *bud = (PurpleBuddy*) node; - struct im_connection *ic = purple_ic_by_pa( bud->account ); - - if( ic == NULL ) + if (node->type == PURPLE_BLIST_BUDDY_NODE) { + PurpleBuddy *bud = (PurpleBuddy *) node; + struct im_connection *ic = purple_ic_by_pa(bud->account); + + if (ic == NULL) { return; - - imcb_add_buddy( ic, bud->name, NULL ); - - prplcb_blist_update( NULL, node ); + } + + imcb_add_buddy(ic, bud->name, NULL); + + prplcb_blist_update(NULL, node); } } -static void prplcb_blist_remove( PurpleBuddyList *list, PurpleBlistNode *node ) +static void prplcb_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node) { /* - PurpleBuddy *bud = (PurpleBuddy*) node; - - if( node->type == PURPLE_BLIST_BUDDY_NODE ) - { - struct im_connection *ic = purple_ic_by_pa( bud->account ); - - if( ic == NULL ) - return; - - imcb_remove_buddy( ic, bud->name, NULL ); - } + PurpleBuddy *bud = (PurpleBuddy*) node; + + if( node->type == PURPLE_BLIST_BUDDY_NODE ) + { + struct im_connection *ic = purple_ic_by_pa( bud->account ); + + if( ic == NULL ) + return; + + imcb_remove_buddy( ic, bud->name, NULL ); + } */ } @@ -831,104 +833,108 @@ static PurpleBlistUiOps bee_blist_uiops = prplcb_blist_remove, }; -void prplcb_conv_new( PurpleConversation *conv ) +void prplcb_conv_new(PurpleConversation *conv) { - if( conv->type == PURPLE_CONV_TYPE_CHAT ) - { - struct im_connection *ic = purple_ic_by_pa( conv->account ); + if (conv->type == PURPLE_CONV_TYPE_CHAT) { + struct im_connection *ic = purple_ic_by_pa(conv->account); struct groupchat *gc; - - gc = imcb_chat_new( ic, conv->name ); - if( conv->title != NULL ) - { - imcb_chat_name_hint( gc, conv->title ); - imcb_chat_topic( gc, NULL, conv->title, 0 ); + + gc = imcb_chat_new(ic, conv->name); + if (conv->title != NULL) { + imcb_chat_name_hint(gc, conv->title); + imcb_chat_topic(gc, NULL, conv->title, 0); } conv->ui_data = gc; gc->data = conv; - + /* libpurple brokenness: Whatever. Show that we join right away, there's no clear "This is you!" signaling in _add_users so don't even try. */ - imcb_chat_add_buddy( gc, gc->ic->acc->user ); + imcb_chat_add_buddy(gc, gc->ic->acc->user); } } -void prplcb_conv_free( PurpleConversation *conv ) +void prplcb_conv_free(PurpleConversation *conv) { struct groupchat *gc = conv->ui_data; - - imcb_chat_free( gc ); + + imcb_chat_free(gc); } -void prplcb_conv_add_users( PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals ) +void prplcb_conv_add_users(PurpleConversation *conv, GList *cbuddies, gboolean new_arrivals) { struct groupchat *gc = conv->ui_data; GList *b; - - for( b = cbuddies; b; b = b->next ) - { + + for (b = cbuddies; b; b = b->next) { PurpleConvChatBuddy *pcb = b->data; - - imcb_chat_add_buddy( gc, pcb->name ); + + imcb_chat_add_buddy(gc, pcb->name); } } -void prplcb_conv_del_users( PurpleConversation *conv, GList *cbuddies ) +void prplcb_conv_del_users(PurpleConversation *conv, GList *cbuddies) { struct groupchat *gc = conv->ui_data; GList *b; - - for( b = cbuddies; b; b = b->next ) - imcb_chat_remove_buddy( gc, b->data, "" ); + + for (b = cbuddies; b; b = b->next) { + imcb_chat_remove_buddy(gc, b->data, ""); + } } -void prplcb_conv_chat_msg( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) +void prplcb_conv_chat_msg(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, + time_t mtime) { struct groupchat *gc = conv->ui_data; PurpleBuddy *buddy; - + /* ..._SEND means it's an outgoing message, no need to echo those. */ - if( flags & PURPLE_MESSAGE_SEND ) + if (flags & PURPLE_MESSAGE_SEND) { return; - - buddy = purple_find_buddy( conv->account, who ); - if( buddy != NULL ) - who = purple_buddy_get_name( buddy ); - - imcb_chat_msg( gc, who, (char*) message, 0, mtime ); + } + + buddy = purple_find_buddy(conv->account, who); + if (buddy != NULL) { + who = purple_buddy_get_name(buddy); + } + + imcb_chat_msg(gc, who, (char *) message, 0, mtime); } -static void prplcb_conv_im( PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime ) +static void prplcb_conv_im(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, + time_t mtime) { - struct im_connection *ic = purple_ic_by_pa( conv->account ); + struct im_connection *ic = purple_ic_by_pa(conv->account); PurpleBuddy *buddy; - + /* ..._SEND means it's an outgoing message, no need to echo those. */ - if( flags & PURPLE_MESSAGE_SEND ) + if (flags & PURPLE_MESSAGE_SEND) { return; - - buddy = purple_find_buddy( conv->account, who ); - if( buddy != NULL ) - who = purple_buddy_get_name( buddy ); - - imcb_buddy_msg( ic, (char*) who, (char*) message, 0, mtime ); + } + + buddy = purple_find_buddy(conv->account, who); + if (buddy != NULL) { + who = purple_buddy_get_name(buddy); + } + + imcb_buddy_msg(ic, (char *) who, (char *) message, 0, mtime); } /* No, this is not a ui_op but a signal. */ -static void prplcb_buddy_typing( PurpleAccount *account, const char *who, gpointer null ) +static void prplcb_buddy_typing(PurpleAccount *account, const char *who, gpointer null) { PurpleConversation *conv; PurpleConvIm *im; int state; - - if( ( conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_IM, who, account ) ) == NULL ) + + if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account)) == NULL) { return; - + } + im = PURPLE_CONV_IM(conv); - switch( purple_conv_im_get_typing_state( im ) ) - { + switch (purple_conv_im_get_typing_state(im)) { case PURPLE_TYPING: state = OPT_TYPING; break; @@ -938,11 +944,11 @@ static void prplcb_buddy_typing( PurpleAccount *account, const char *who, gpoint default: state = 0; } - - imcb_buddy_typing( purple_ic_by_pa( account ), who, state ); + + imcb_buddy_typing(purple_ic_by_pa(account), who, state); } -static PurpleConversationUiOps bee_conv_uiops = +static PurpleConversationUiOps bee_conv_uiops = { prplcb_conv_new, /* create_conversation */ prplcb_conv_free, /* destroy_conversation */ @@ -961,78 +967,75 @@ static PurpleConversationUiOps bee_conv_uiops = NULL, /* send_confirm */ }; -struct prplcb_request_action_data -{ +struct prplcb_request_action_data { void *user_data, *bee_data; PurpleRequestActionCb yes, no; int yes_i, no_i; }; -static void prplcb_request_action_yes( void *data ) +static void prplcb_request_action_yes(void *data) { struct prplcb_request_action_data *pqad = data; - - if( pqad->yes ) - pqad->yes( pqad->user_data, pqad->yes_i ); - g_free( pqad ); + + if (pqad->yes) { + pqad->yes(pqad->user_data, pqad->yes_i); + } + g_free(pqad); } -static void prplcb_request_action_no( void *data ) +static void prplcb_request_action_no(void *data) { struct prplcb_request_action_data *pqad = data; - - if( pqad->no ) - pqad->no( pqad->user_data, pqad->no_i ); - g_free( pqad ); + + if (pqad->no) { + pqad->no(pqad->user_data, pqad->no_i); + } + g_free(pqad); } -static void *prplcb_request_action( const char *title, const char *primary, const char *secondary, - int default_action, PurpleAccount *account, const char *who, - PurpleConversation *conv, void *user_data, size_t action_count, - va_list actions ) +static void *prplcb_request_action(const char *title, const char *primary, const char *secondary, + int default_action, PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data, size_t action_count, + va_list actions) { - struct prplcb_request_action_data *pqad; + struct prplcb_request_action_data *pqad; int i; char *q; - - pqad = g_new0( struct prplcb_request_action_data, 1 ); - - for( i = 0; i < action_count; i ++ ) - { + + pqad = g_new0(struct prplcb_request_action_data, 1); + + for (i = 0; i < action_count; i++) { char *caption; void *fn; - - caption = va_arg( actions, char* ); - fn = va_arg( actions, void* ); - - if( strstr( caption, "Accept" ) || strstr( caption, "OK" ) ) - { + + caption = va_arg(actions, char*); + fn = va_arg(actions, void*); + + if (strstr(caption, "Accept") || strstr(caption, "OK")) { pqad->yes = fn; pqad->yes_i = i; - } - else if( strstr( caption, "Reject" ) || strstr( caption, "Cancel" ) ) - { + } else if (strstr(caption, "Reject") || strstr(caption, "Cancel")) { pqad->no = fn; pqad->no_i = i; } } - + pqad->user_data = user_data; - + /* TODO: IRC stuff here :-( */ - q = g_strdup_printf( "Request: %s\n\n%s\n\n%s", title, primary, secondary ); - pqad->bee_data = query_add( local_bee->ui_data, purple_ic_by_pa( account ), q, - prplcb_request_action_yes, prplcb_request_action_no, g_free, pqad ); - - g_free( q ); - + q = g_strdup_printf("Request: %s\n\n%s\n\n%s", title, primary, secondary); + pqad->bee_data = query_add(local_bee->ui_data, purple_ic_by_pa(account), q, + prplcb_request_action_yes, prplcb_request_action_no, g_free, pqad); + + g_free(q); + return pqad; } /* static void prplcb_request_test() { - fprintf( stderr, "bla\n" ); + fprintf( stderr, "bla\n" ); } */ @@ -1047,38 +1050,40 @@ static PurpleRequestUiOps bee_request_uiops = NULL, }; -static void prplcb_privacy_permit_added( PurpleAccount *account, const char *name ) +static void prplcb_privacy_permit_added(PurpleAccount *account, const char *name) { - struct im_connection *ic = purple_ic_by_pa( account ); - - if( !g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) - ic->permit = g_slist_prepend( ic->permit, g_strdup( name ) ); + struct im_connection *ic = purple_ic_by_pa(account); + + if (!g_slist_find_custom(ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp)) { + ic->permit = g_slist_prepend(ic->permit, g_strdup(name)); + } } -static void prplcb_privacy_permit_removed( PurpleAccount *account, const char *name ) +static void prplcb_privacy_permit_removed(PurpleAccount *account, const char *name) { - struct im_connection *ic = purple_ic_by_pa( account ); + struct im_connection *ic = purple_ic_by_pa(account); void *n; - - n = g_slist_find_custom( ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp ); - ic->permit = g_slist_remove( ic->permit, n ); + + n = g_slist_find_custom(ic->permit, name, (GCompareFunc) ic->acc->prpl->handle_cmp); + ic->permit = g_slist_remove(ic->permit, n); } -static void prplcb_privacy_deny_added( PurpleAccount *account, const char *name ) +static void prplcb_privacy_deny_added(PurpleAccount *account, const char *name) { - struct im_connection *ic = purple_ic_by_pa( account ); - - if( !g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp ) ) - ic->deny = g_slist_prepend( ic->deny, g_strdup( name ) ); + struct im_connection *ic = purple_ic_by_pa(account); + + if (!g_slist_find_custom(ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp)) { + ic->deny = g_slist_prepend(ic->deny, g_strdup(name)); + } } -static void prplcb_privacy_deny_removed( PurpleAccount *account, const char *name ) +static void prplcb_privacy_deny_removed(PurpleAccount *account, const char *name) { - struct im_connection *ic = purple_ic_by_pa( account ); + struct im_connection *ic = purple_ic_by_pa(account); void *n; - - n = g_slist_find_custom( ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp ); - ic->deny = g_slist_remove( ic->deny, n ); + + n = g_slist_find_custom(ic->deny, name, (GCompareFunc) ic->acc->prpl->handle_cmp); + ic->deny = g_slist_remove(ic->deny, n); } static PurplePrivacyUiOps bee_privacy_uiops = @@ -1089,9 +1094,9 @@ static PurplePrivacyUiOps bee_privacy_uiops = prplcb_privacy_deny_removed, }; -static void prplcb_debug_print( PurpleDebugLevel level, const char *category, const char *arg_s ) +static void prplcb_debug_print(PurpleDebugLevel level, const char *category, const char *arg_s) { - fprintf( stderr, "DEBUG %s: %s", category, arg_s ); + fprintf(stderr, "DEBUG %s: %s", category, arg_s); } static PurpleDebugUiOps bee_debug_uiops = @@ -1099,23 +1104,23 @@ static PurpleDebugUiOps bee_debug_uiops = prplcb_debug_print, }; -static guint prplcb_ev_timeout_add( guint interval, GSourceFunc func, gpointer udata ) +static guint prplcb_ev_timeout_add(guint interval, GSourceFunc func, gpointer udata) { - return b_timeout_add( interval, (b_event_handler) func, udata ); + return b_timeout_add(interval, (b_event_handler) func, udata); } -static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata ) +static guint prplcb_ev_input_add(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata) { - return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata ); + return b_input_add(fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata); } -static gboolean prplcb_ev_remove( guint id ) +static gboolean prplcb_ev_remove(guint id) { - b_event_remove( (gint) id ); + b_event_remove((gint) id); return TRUE; } -static PurpleEventLoopUiOps glib_eventloops = +static PurpleEventLoopUiOps glib_eventloops = { prplcb_ev_timeout_add, prplcb_ev_remove, @@ -1123,95 +1128,94 @@ static PurpleEventLoopUiOps glib_eventloops = prplcb_ev_remove, }; -static void *prplcb_notify_email( PurpleConnection *gc, const char *subject, const char *from, - const char *to, const char *url ) +static void *prplcb_notify_email(PurpleConnection *gc, const char *subject, const char *from, + const char *to, const char *url) { - struct im_connection *ic = purple_ic_by_gc( gc ); - - imcb_log( ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url ); - + struct im_connection *ic = purple_ic_by_gc(gc); + + imcb_log(ic, "Received e-mail from %s for %s: %s <%s>", from, to, subject, url); + return NULL; } -static void *prplcb_notify_userinfo( PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info ) +static void *prplcb_notify_userinfo(PurpleConnection *gc, const char *who, PurpleNotifyUserInfo *user_info) { - struct im_connection *ic = purple_ic_by_gc( gc ); - GString *info = g_string_new( "" ); - GList *l = purple_notify_user_info_get_entries( user_info ); + struct im_connection *ic = purple_ic_by_gc(gc); + GString *info = g_string_new(""); + GList *l = purple_notify_user_info_get_entries(user_info); char *key; const char *value; int n; - - while( l ) - { + + while (l) { PurpleNotifyUserInfoEntry *e = l->data; - - switch( purple_notify_user_info_entry_get_type( e ) ) - { + + switch (purple_notify_user_info_entry_get_type(e)) { case PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR: case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER: - key = g_strdup( purple_notify_user_info_entry_get_label( e ) ); - value = purple_notify_user_info_entry_get_value( e ); - - if( key ) - { - strip_html( key ); - g_string_append_printf( info, "%s: ", key ); - - if( value ) - { - n = strlen( value ) - 1; - while( g_ascii_isspace( value[n] ) ) - n --; - g_string_append_len( info, value, n + 1 ); + key = g_strdup(purple_notify_user_info_entry_get_label(e)); + value = purple_notify_user_info_entry_get_value(e); + + if (key) { + strip_html(key); + g_string_append_printf(info, "%s: ", key); + + if (value) { + n = strlen(value) - 1; + while (g_ascii_isspace(value[n])) { + n--; + } + g_string_append_len(info, value, n + 1); } - g_string_append_c( info, '\n' ); - g_free( key ); + g_string_append_c(info, '\n'); + g_free(key); } - + break; case PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK: - g_string_append( info, "------------------------\n" ); + g_string_append(info, "------------------------\n"); break; } - + l = l->next; } - - imcb_log( ic, "User %s info:\n%s", who, info->str ); - g_string_free( info, TRUE ); - + + imcb_log(ic, "User %s info:\n%s", who, info->str); + g_string_free(info, TRUE); + return NULL; } static PurpleNotifyUiOps bee_notify_uiops = { - NULL, - prplcb_notify_email, - NULL, - NULL, - NULL, - NULL, - prplcb_notify_userinfo, + NULL, + prplcb_notify_email, + NULL, + NULL, + NULL, + NULL, + prplcb_notify_userinfo, }; -static void *prplcb_account_request_authorize( PurpleAccount *account, const char *remote_user, - const char *id, const char *alias, const char *message, gboolean on_list, - PurpleAccountRequestAuthorizationCb authorize_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data ) +static void *prplcb_account_request_authorize(PurpleAccount *account, const char *remote_user, + const char *id, const char *alias, const char *message, gboolean on_list, + PurpleAccountRequestAuthorizationCb authorize_cb, + PurpleAccountRequestAuthorizationCb deny_cb, void *user_data) { - struct im_connection *ic = purple_ic_by_pa( account ); + struct im_connection *ic = purple_ic_by_pa(account); char *q; - - if( alias ) - q = g_strdup_printf( "%s (%s) wants to add you to his/her contact " - "list. (%s)", alias, remote_user, message ); - else - q = g_strdup_printf( "%s wants to add you to his/her contact " - "list. (%s)", remote_user, message ); - - imcb_ask_with_free( ic, q, user_data, authorize_cb, deny_cb, NULL ); - g_free( q ); - + + if (alias) { + q = g_strdup_printf("%s (%s) wants to add you to his/her contact " + "list. (%s)", alias, remote_user, message); + } else { + q = g_strdup_printf("%s wants to add you to his/her contact " + "list. (%s)", remote_user, message); + } + + imcb_ask_with_free(ic, q, user_data, authorize_cb, deny_cb, NULL); + g_free(q); + return NULL; } @@ -1228,17 +1232,18 @@ extern PurpleXferUiOps bee_xfer_uiops; static void purple_ui_init() { - purple_connections_set_ui_ops( &bee_conn_uiops ); - purple_blist_set_ui_ops( &bee_blist_uiops ); - purple_conversations_set_ui_ops( &bee_conv_uiops ); - purple_request_set_ui_ops( &bee_request_uiops ); - purple_privacy_set_ui_ops( &bee_privacy_uiops ); - purple_notify_set_ui_ops( &bee_notify_uiops ); - purple_accounts_set_ui_ops( &bee_account_uiops ); - purple_xfers_set_ui_ops( &bee_xfer_uiops ); - - if( getenv( "BITLBEE_DEBUG" ) ) - purple_debug_set_ui_ops( &bee_debug_uiops ); + purple_connections_set_ui_ops(&bee_conn_uiops); + purple_blist_set_ui_ops(&bee_blist_uiops); + purple_conversations_set_ui_ops(&bee_conv_uiops); + purple_request_set_ui_ops(&bee_request_uiops); + purple_privacy_set_ui_ops(&bee_privacy_uiops); + purple_notify_set_ui_ops(&bee_notify_uiops); + purple_accounts_set_ui_ops(&bee_account_uiops); + purple_xfers_set_ui_ops(&bee_xfer_uiops); + + if (getenv("BITLBEE_DEBUG")) { + purple_debug_set_ui_ops(&bee_debug_uiops); + } } void purple_initmodule() @@ -1247,61 +1252,57 @@ void purple_initmodule() GList *prots; GString *help; char *dir; - - if( B_EV_IO_READ != PURPLE_INPUT_READ || - B_EV_IO_WRITE != PURPLE_INPUT_WRITE ) - { + + if (B_EV_IO_READ != PURPLE_INPUT_READ || + B_EV_IO_WRITE != PURPLE_INPUT_WRITE) { /* FIXME FIXME FIXME FIXME FIXME :-) */ - exit( 1 ); + exit(1); } - - dir = g_strdup_printf( "%s/purple", global.conf->configdir ); - purple_util_set_user_dir( dir ); - g_free( dir ); - - purple_debug_set_enabled( FALSE ); - purple_core_set_ui_ops( &bee_core_uiops ); - purple_eventloop_set_ui_ops( &glib_eventloops ); - if( !purple_core_init( "BitlBee") ) - { + + dir = g_strdup_printf("%s/purple", global.conf->configdir); + purple_util_set_user_dir(dir); + g_free(dir); + + purple_debug_set_enabled(FALSE); + purple_core_set_ui_ops(&bee_core_uiops); + purple_eventloop_set_ui_ops(&glib_eventloops); + if (!purple_core_init("BitlBee")) { /* Initializing the core failed. Terminate. */ - fprintf( stderr, "libpurple initialization failed.\n" ); + fprintf(stderr, "libpurple initialization failed.\n"); abort(); } - - if( proxytype != PROXY_NONE ) - { + + if (proxytype != PROXY_NONE) { PurpleProxyInfo *pi = purple_global_proxy_get_info(); - switch( proxytype ) - { + switch (proxytype) { case PROXY_SOCKS4: - purple_proxy_info_set_type( pi, PURPLE_PROXY_SOCKS4 ); + purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS4); break; case PROXY_SOCKS5: - purple_proxy_info_set_type( pi, PURPLE_PROXY_SOCKS5 ); + purple_proxy_info_set_type(pi, PURPLE_PROXY_SOCKS5); break; case PROXY_HTTP: - purple_proxy_info_set_type( pi, PURPLE_PROXY_HTTP ); + purple_proxy_info_set_type(pi, PURPLE_PROXY_HTTP); break; - } - purple_proxy_info_set_host( pi, proxyhost ); - purple_proxy_info_set_port( pi, proxyport ); - purple_proxy_info_set_username( pi, proxyuser ); - purple_proxy_info_set_password( pi, proxypass ); + } + purple_proxy_info_set_host(pi, proxyhost); + purple_proxy_info_set_port(pi, proxyport); + purple_proxy_info_set_username(pi, proxyuser); + purple_proxy_info_set_password(pi, proxypass); } - - purple_set_blist( purple_blist_new() ); - + + purple_set_blist(purple_blist_new()); + /* No, really. So far there were ui_ops for everything, but now suddenly one needs to use signals for typing notification stuff. :-( */ - purple_signal_connect( purple_conversations_get_handle(), "buddy-typing", - &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL ); - purple_signal_connect( purple_conversations_get_handle(), "buddy-typed", - &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL ); - purple_signal_connect( purple_conversations_get_handle(), "buddy-typing-stopped", - &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL ); - - memset( &funcs, 0, sizeof( funcs ) ); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", + &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", + &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); + purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", + &funcs, PURPLE_CALLBACK(prplcb_buddy_typing), NULL); + + memset(&funcs, 0, sizeof(funcs)); funcs.login = purple_login; funcs.init = purple_init; funcs.logout = purple_logout; @@ -1326,46 +1327,46 @@ void purple_initmodule() funcs.chat_leave = purple_chat_leave; funcs.chat_join = purple_chat_join; funcs.transfer_request = purple_transfer_request; - - help = g_string_new( "BitlBee libpurple module supports the following IM protocols:\n" ); - + + help = g_string_new("BitlBee libpurple module supports the following IM protocols:\n"); + /* Add a protocol entry to BitlBee's structures for every protocol - supported by this libpurple instance. */ - for( prots = purple_plugins_get_protocols(); prots; prots = prots->next ) - { + supported by this libpurple instance. */ + for (prots = purple_plugins_get_protocols(); prots; prots = prots->next) { PurplePlugin *prot = prots->data; struct prpl *ret; - + /* If we already have this one (as a native module), don't add a libpurple duplicate. */ - if( find_protocol( prot->info->id ) ) + if (find_protocol(prot->info->id)) { continue; - - ret = g_memdup( &funcs, sizeof( funcs ) ); + } + + ret = g_memdup(&funcs, sizeof(funcs)); ret->name = ret->data = prot->info->id; - if( strncmp( ret->name, "prpl-", 5 ) == 0 ) + if (strncmp(ret->name, "prpl-", 5) == 0) { ret->name += 5; - register_protocol( ret ); - - g_string_append_printf( help, "\n* %s (%s)", ret->name, prot->info->name ); - + } + register_protocol(ret); + + g_string_append_printf(help, "\n* %s (%s)", ret->name, prot->info->name); + /* libpurple doesn't define a protocol called OSCAR, but we need it to be compatible with normal BitlBee. */ - if( g_strcasecmp( prot->info->id, "prpl-aim" ) == 0 ) - { - ret = g_memdup( &funcs, sizeof( funcs ) ); + if (g_strcasecmp(prot->info->id, "prpl-aim") == 0) { + ret = g_memdup(&funcs, sizeof(funcs)); ret->name = "oscar"; ret->data = prot->info->id; - register_protocol( ret ); + register_protocol(ret); } } - - g_string_append( help, "\n\nFor used protocols, more information about available " - "settings can be found using \x02help purple <protocol name>\x02 " - "(create an account using that protocol first!)" ); - + + g_string_append(help, "\n\nFor used protocols, more information about available " + "settings can be found using \x02help purple <protocol name>\x02 " + "(create an account using that protocol first!)"); + /* Add a simple dynamically-generated help item listing all the supported protocols. */ - help_add_mem( &global.help, "purple", help->str ); - g_string_free( help, TRUE ); + help_add_mem(&global.help, "purple", help->str); + g_string_free(help, TRUE); } diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c index 20897d99..1727c4af 100644 --- a/protocols/skype/skype.c +++ b/protocols/skype/skype.c @@ -29,7 +29,7 @@ #define SKYPE_DEFAULT_SERVER "localhost" #define SKYPE_DEFAULT_PORT "2727" #define IRC_LINE_SIZE 16384 -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) /* * Enumerations @@ -150,7 +150,7 @@ const struct skype_away_state skype_away_state_list[] = { { "OFFLINE", "Offline" }, { "SKYPEME", "Skype Me" }, { "ONLINE", "Online" }, - { NULL, NULL} + { NULL, NULL } }; /* @@ -162,8 +162,9 @@ int skype_write(struct im_connection *ic, char *buf, int len) struct skype_data *sd = ic->proto_data; struct pollfd pfd[1]; - if (!sd->ssl) + if (!sd->ssl) { return FALSE; + } pfd[0].fd = sd->fd; pfd[0].events = POLLOUT; @@ -195,8 +196,9 @@ int skype_printf(struct im_connection *ic, char *fmt, ...) static void skype_buddy_ask_yes(void *data) { struct skype_buddy_ask_data *bla = data; + skype_printf(bla->ic, "SET USER %s ISAUTHORIZED TRUE\n", - bla->handle); + bla->handle); g_free(bla->handle); g_free(bla); } @@ -204,8 +206,9 @@ static void skype_buddy_ask_yes(void *data) static void skype_buddy_ask_no(void *data) { struct skype_buddy_ask_data *bla = data; + skype_printf(bla->ic, "SET USER %s ISAUTHORIZED FALSE\n", - bla->handle); + bla->handle); g_free(bla->handle); g_free(bla); } @@ -213,7 +216,7 @@ static void skype_buddy_ask_no(void *data) void skype_buddy_ask(struct im_connection *ic, char *handle, char *message) { struct skype_buddy_ask_data *bla = g_new0(struct skype_buddy_ask_data, - 1); + 1); char *buf; bla->ic = ic; @@ -227,8 +230,9 @@ void skype_buddy_ask(struct im_connection *ic, char *handle, char *message) static void skype_call_ask_yes(void *data) { struct skype_buddy_ask_data *bla = data; + skype_printf(bla->ic, "SET CALL %s STATUS INPROGRESS\n", - bla->handle); + bla->handle); g_free(bla->handle); g_free(bla); } @@ -236,8 +240,9 @@ static void skype_call_ask_yes(void *data) static void skype_call_ask_no(void *data) { struct skype_buddy_ask_data *bla = data; + skype_printf(bla->ic, "SET CALL %s STATUS FINISHED\n", - bla->handle); + bla->handle); g_free(bla->handle); g_free(bla); } @@ -245,7 +250,7 @@ static void skype_call_ask_no(void *data) void skype_call_ask(struct im_connection *ic, char *call_id, char *message) { struct skype_buddy_ask_data *bla = g_new0(struct skype_buddy_ask_data, - 1); + 1); bla->ic = ic; bla->handle = g_strdup(call_id); @@ -296,8 +301,9 @@ static char *skype_group_by_username(struct im_connection *ic, char *username) for (i = 0; i < g_list_length(sd->groups); i++) { struct skype_group *sg = g_list_nth_data(sd->groups, i); for (j = 0; j < g_list_length(sg->users); j++) { - if (!strcmp(g_list_nth_data(sg->users, j), username)) + if (!strcmp(g_list_nth_data(sg->users, j), username)) { return sg->name; + } } } return NULL; @@ -310,8 +316,9 @@ static struct skype_group *skype_group_by_name(struct im_connection *ic, char *n for (i = 0; i < g_list_length(sd->groups); i++) { struct skype_group *sg = g_list_nth_data(sd->groups, i); - if (!strcmp(sg->name, name)) + if (!strcmp(sg->name, name)) { return sg; + } } return NULL; } @@ -338,29 +345,35 @@ static void skype_parse_user(struct im_connection *ic, char *line) status++; ptr = strchr(++user, ' '); - if (!ptr) + if (!ptr) { return; + } *ptr = '\0'; ptr++; if (!strncmp(ptr, "ONLINESTATUS ", 13)) { - if (!strlen(user) || !strcmp(user, sd->username)) + if (!strlen(user) || !strcmp(user, sd->username)) { return; + } if (!set_getbool(&ic->acc->set, "test_join") - && !strcmp(user, "echo123")) + && !strcmp(user, "echo123")) { return; + } ptr = g_strdup_printf("%s@skype.com", user); imcb_add_buddy(ic, ptr, skype_group_by_username(ic, user)); if (strcmp(status, "OFFLINE") && (strcmp(status, "SKYPEOUT") || - !set_getbool(&ic->acc->set, "skypeout_offline"))) + !set_getbool(&ic->acc->set, "skypeout_offline"))) { flags |= OPT_LOGGED_IN; - if (strcmp(status, "ONLINE") && strcmp(status, "SKYPEME")) + } + if (strcmp(status, "ONLINE") && strcmp(status, "SKYPEME")) { flags |= OPT_AWAY; + } imcb_buddy_status(ic, ptr, flags, NULL, NULL); g_free(ptr); } else if (!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20)) { char *message = ptr + 20; - if (strlen(message)) + if (strlen(message)) { skype_buddy_ask(ic, user, message); + } } else if (!strncmp(ptr, "BUDDYSTATUS ", 12)) { char *st = ptr + 12; if (!strcmp(st, "3")) { @@ -373,11 +386,13 @@ static void skype_parse_user(struct im_connection *ic, char *line) bee_user_t *bu = bee_user_by_handle(ic->bee, ic, buf); g_free(buf); buf = ptr + 10; - if (bu) + if (bu) { imcb_buddy_status(ic, bu->handle, bu->flags, NULL, - *buf ? buf : NULL); - if (set_getbool(&ic->acc->set, "show_moods")) + *buf ? buf : NULL); + } + if (set_getbool(&ic->acc->set, "show_moods")) { imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf); + } } else if (!strncmp(ptr, "FULLNAME ", 9)) { char *name = ptr + 9; if (sd->is_info) { @@ -388,35 +403,35 @@ static void skype_parse_user(struct im_connection *ic, char *line) imcb_rename_buddy(ic, buf, name); g_free(buf); } - } else if (!strncmp(ptr, "PHONE_HOME ", 11)) + } else if (!strncmp(ptr, "PHONE_HOME ", 11)) { sd->info_phonehome = g_strdup(ptr + 11); - else if (!strncmp(ptr, "PHONE_OFFICE ", 13)) + } else if (!strncmp(ptr, "PHONE_OFFICE ", 13)) { sd->info_phoneoffice = g_strdup(ptr + 13); - else if (!strncmp(ptr, "PHONE_MOBILE ", 13)) + } else if (!strncmp(ptr, "PHONE_MOBILE ", 13)) { sd->info_phonemobile = g_strdup(ptr + 13); - else if (!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20)) + } else if (!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20)) { sd->info_nrbuddies = g_strdup(ptr + 20); - else if (!strncmp(ptr, "TIMEZONE ", 9)) + } else if (!strncmp(ptr, "TIMEZONE ", 9)) { sd->info_tz = g_strdup(ptr + 9); - else if (!strncmp(ptr, "LASTONLINETIMESTAMP ", 20)) + } else if (!strncmp(ptr, "LASTONLINETIMESTAMP ", 20)) { sd->info_seen = g_strdup(ptr + 20); - else if (!strncmp(ptr, "SEX ", 4)) + } else if (!strncmp(ptr, "SEX ", 4)) { sd->info_sex = g_strdup(ptr + 4); - else if (!strncmp(ptr, "LANGUAGE ", 9)) + } else if (!strncmp(ptr, "LANGUAGE ", 9)) { sd->info_language = g_strdup(ptr + 9); - else if (!strncmp(ptr, "COUNTRY ", 8)) + } else if (!strncmp(ptr, "COUNTRY ", 8)) { sd->info_country = g_strdup(ptr + 8); - else if (!strncmp(ptr, "PROVINCE ", 9)) + } else if (!strncmp(ptr, "PROVINCE ", 9)) { sd->info_province = g_strdup(ptr + 9); - else if (!strncmp(ptr, "CITY ", 5)) + } else if (!strncmp(ptr, "CITY ", 5)) { sd->info_city = g_strdup(ptr + 5); - else if (!strncmp(ptr, "HOMEPAGE ", 9)) + } else if (!strncmp(ptr, "HOMEPAGE ", 9)) { sd->info_homepage = g_strdup(ptr + 9); - else if (!strncmp(ptr, "ABOUT ", 6)) { + } else if (!strncmp(ptr, "ABOUT ", 6)) { /* Support multiple about lines. */ - if (!sd->info_about) + if (!sd->info_about) { sd->info_about = g_strdup(ptr + 6); - else { + } else { GString *st = g_string_new(sd->info_about); g_string_append_printf(st, "\n%s", ptr + 6); g_free(sd->info_about); @@ -429,38 +444,43 @@ static void skype_parse_user(struct im_connection *ic, char *line) GString *st = g_string_new("Contact Information\n"); g_string_append_printf(st, "Skype Name: %s\n", user); if (sd->info_fullname) { - if (strlen(sd->info_fullname)) + if (strlen(sd->info_fullname)) { g_string_append_printf(st, "Full Name: %s\n", - sd->info_fullname); + sd->info_fullname); + } g_free(sd->info_fullname); sd->info_fullname = NULL; } if (sd->info_phonehome) { - if (strlen(sd->info_phonehome)) + if (strlen(sd->info_phonehome)) { g_string_append_printf(st, "Home Phone: %s\n", - sd->info_phonehome); + sd->info_phonehome); + } g_free(sd->info_phonehome); sd->info_phonehome = NULL; } if (sd->info_phoneoffice) { - if (strlen(sd->info_phoneoffice)) + if (strlen(sd->info_phoneoffice)) { g_string_append_printf(st, "Office Phone: %s\n", - sd->info_phoneoffice); + sd->info_phoneoffice); + } g_free(sd->info_phoneoffice); sd->info_phoneoffice = NULL; } if (sd->info_phonemobile) { - if (strlen(sd->info_phonemobile)) + if (strlen(sd->info_phonemobile)) { g_string_append_printf(st, "Mobile Phone: %s\n", - sd->info_phonemobile); + sd->info_phonemobile); + } g_free(sd->info_phonemobile); sd->info_phonemobile = NULL; } g_string_append_printf(st, "Personal Information\n"); if (sd->info_nrbuddies) { - if (strlen(sd->info_nrbuddies)) + if (strlen(sd->info_nrbuddies)) { g_string_append_printf(st, - "Contacts: %s\n", sd->info_nrbuddies); + "Contacts: %s\n", sd->info_nrbuddies); + } g_free(sd->info_nrbuddies); sd->info_nrbuddies = NULL; } @@ -468,11 +488,11 @@ static void skype_parse_user(struct im_connection *ic, char *line) if (strlen(sd->info_tz)) { char ib[256]; time_t t = time(NULL); - t += atoi(sd->info_tz)-(60*60*24); + t += atoi(sd->info_tz) - (60 * 60 * 24); struct tm *gt = gmtime(&t); strftime(ib, 256, "%H:%M:%S", gt); g_string_append_printf(st, - "Local Time: %s\n", ib); + "Local Time: %s\n", ib); } g_free(sd->info_tz); sd->info_tz = NULL; @@ -484,27 +504,27 @@ static void skype_parse_user(struct im_connection *ic, char *line) struct tm *tm = localtime(&it); strftime(ib, 256, ("%Y. %m. %d. %H:%M"), tm); g_string_append_printf(st, - "Last Seen: %s\n", ib); + "Last Seen: %s\n", ib); } g_free(sd->info_seen); sd->info_seen = NULL; } if (sd->info_birthday) { if (strlen(sd->info_birthday) && - strcmp(sd->info_birthday, "0")) { + strcmp(sd->info_birthday, "0")) { char ib[256]; struct tm tm; strptime(sd->info_birthday, "%Y%m%d", &tm); strftime(ib, 256, "%B %d, %Y", &tm); g_string_append_printf(st, - "Birthday: %s\n", ib); + "Birthday: %s\n", ib); strftime(ib, 256, "%Y", &tm); int year = atoi(ib); time_t t = time(NULL); struct tm *lt = localtime(&t); g_string_append_printf(st, - "Age: %d\n", lt->tm_year+1900-year); + "Age: %d\n", lt->tm_year + 1900 - year); } g_free(sd->info_birthday); sd->info_birthday = NULL; @@ -512,10 +532,11 @@ static void skype_parse_user(struct im_connection *ic, char *line) if (sd->info_sex) { if (strlen(sd->info_sex)) { char *iptr = sd->info_sex; - while (*iptr++) + while (*iptr++) { *iptr = g_ascii_tolower(*iptr); + } g_string_append_printf(st, - "Gender: %s\n", sd->info_sex); + "Gender: %s\n", sd->info_sex); } g_free(sd->info_sex); sd->info_sex = NULL; @@ -523,12 +544,13 @@ static void skype_parse_user(struct im_connection *ic, char *line) if (sd->info_language) { if (strlen(sd->info_language)) { char *iptr = strchr(sd->info_language, ' '); - if (iptr) + if (iptr) { iptr++; - else + } else { iptr = sd->info_language; + } g_string_append_printf(st, - "Language: %s\n", iptr); + "Language: %s\n", iptr); } g_free(sd->info_language); sd->info_language = NULL; @@ -536,41 +558,46 @@ static void skype_parse_user(struct im_connection *ic, char *line) if (sd->info_country) { if (strlen(sd->info_country)) { char *iptr = strchr(sd->info_country, ' '); - if (iptr) + if (iptr) { iptr++; - else + } else { iptr = sd->info_country; + } g_string_append_printf(st, - "Country: %s\n", iptr); + "Country: %s\n", iptr); } g_free(sd->info_country); sd->info_country = NULL; } if (sd->info_province) { - if (strlen(sd->info_province)) + if (strlen(sd->info_province)) { g_string_append_printf(st, - "Region: %s\n", sd->info_province); + "Region: %s\n", sd->info_province); + } g_free(sd->info_province); sd->info_province = NULL; } if (sd->info_city) { - if (strlen(sd->info_city)) + if (strlen(sd->info_city)) { g_string_append_printf(st, - "City: %s\n", sd->info_city); + "City: %s\n", sd->info_city); + } g_free(sd->info_city); sd->info_city = NULL; } if (sd->info_homepage) { - if (strlen(sd->info_homepage)) + if (strlen(sd->info_homepage)) { g_string_append_printf(st, - "Homepage: %s\n", sd->info_homepage); + "Homepage: %s\n", sd->info_homepage); + } g_free(sd->info_homepage); sd->info_homepage = NULL; } if (sd->info_about) { - if (strlen(sd->info_about)) + if (strlen(sd->info_about)) { g_string_append_printf(st, "%s\n", - sd->info_about); + sd->info_about); + } g_free(sd->info_about); sd->info_about = NULL; } @@ -583,21 +610,24 @@ static void skype_parse_chatmessage_said_emoted(struct im_connection *ic, struct { struct skype_data *sd = ic->proto_data; char buf[IRC_LINE_SIZE]; + if (!strcmp(sd->type, "SAID")) { - if (!sd->is_edit) + if (!sd->is_edit) { g_snprintf(buf, IRC_LINE_SIZE, "%s", body); - else { + } else { g_snprintf(buf, IRC_LINE_SIZE, "%s %s", set_getstr(&ic->acc->set, "edit_prefix"), body); sd->is_edit = 0; } - } else + } else { g_snprintf(buf, IRC_LINE_SIZE, "/me %s", body); - if (!gc) + } + if (!gc) { /* Private message */ imcb_buddy_msg(ic, sd->handle, buf, 0, 0); - else + } else { /* Groupchat message */ imcb_chat_msg(gc, sd->handle, buf, 0, 0); + } } static void skype_parse_chatmessage(struct im_connection *ic, char *line) @@ -605,12 +635,14 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line) struct skype_data *sd = ic->proto_data; char *id = strchr(line, ' '); - if (!++id) + if (!++id) { return; + } char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; if (!strcmp(info, "STATUS RECEIVED") || !strncmp(info, "EDITED_TIMESTAMP", 16)) { @@ -621,10 +653,11 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line) * (4) Query chatname */ skype_printf(ic, "GET CHATMESSAGE %s FROM_HANDLE\n", id); - if (!strcmp(info, "STATUS RECEIVED")) + if (!strcmp(info, "STATUS RECEIVED")) { skype_printf(ic, "GET CHATMESSAGE %s BODY\n", id); - else + } else { sd->is_edit = 1; + } skype_printf(ic, "GET CHATMESSAGE %s TYPE\n", id); skype_printf(ic, "GET CHATMESSAGE %s CHATNAME\n", id); } else if (!strncmp(info, "FROM_HANDLE ", 12)) { @@ -647,7 +680,7 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line) } else if (!strncmp(info, "BODY ", 5)) { info += 5; sd->body = g_list_append(sd->body, g_strdup(info)); - } else if (!strncmp(info, "TYPE ", 5)) { + } else if (!strncmp(info, "TYPE ", 5)) { info += 5; g_free(sd->type); sd->type = g_strdup(info); @@ -659,14 +692,15 @@ static void skype_parse_chatmessage(struct im_connection *ic, char *line) for (i = 0; i < g_list_length(sd->body); i++) { char *body = g_list_nth_data(sd->body, i); if (!strcmp(sd->type, "SAID") || - !strcmp(sd->type, "EMOTED")) { + !strcmp(sd->type, "EMOTED")) { skype_parse_chatmessage_said_emoted(ic, gc, body); - } else if (!strcmp(sd->type, "SETTOPIC") && gc) + } else if (!strcmp(sd->type, "SETTOPIC") && gc) { imcb_chat_topic(gc, - sd->handle, body, 0); - else if (!strcmp(sd->type, "LEFT") && gc) + sd->handle, body, 0); + } else if (!strcmp(sd->type, "LEFT") && gc) { imcb_chat_remove_buddy(gc, - sd->handle, NULL); + sd->handle, NULL); + } } g_list_free(sd->body); sd->body = NULL; @@ -680,19 +714,22 @@ static void skype_parse_call(struct im_connection *ic, char *line) char *id = strchr(line, ' '); char buf[IRC_LINE_SIZE]; - if (!++id) + if (!++id) { return; + } char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; - if (!strncmp(info, "FAILUREREASON ", 14)) + if (!strncmp(info, "FAILUREREASON ", 14)) { sd->failurereason = atoi(strchr(info, ' ')); - else if (!strcmp(info, "STATUS RINGING")) { - if (sd->call_id) + } else if (!strcmp(info, "STATUS RINGING")) { + if (sd->call_id) { g_free(sd->call_id); + } sd->call_id = g_strdup(id); skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_RINGING; @@ -709,64 +746,69 @@ static void skype_parse_call(struct im_connection *ic, char *line) skype_printf(ic, "GET CALL %s PARTNER_HANDLE\n", id); sd->call_status = SKYPE_CALL_REFUSED; } else if (!strcmp(info, "STATUS UNPLACED")) { - if (sd->call_id) + if (sd->call_id) { g_free(sd->call_id); + } /* Save the ID for later usage (Cancel/Finish). */ sd->call_id = g_strdup(id); sd->call_out = TRUE; } else if (!strcmp(info, "STATUS FAILED")) { imcb_error(ic, "Call failed: %s", - skype_call_strerror(sd->failurereason)); + skype_call_strerror(sd->failurereason)); sd->call_id = NULL; } else if (!strncmp(info, "DURATION ", 9)) { - if (sd->call_duration) + if (sd->call_duration) { g_free(sd->call_duration); - sd->call_duration = g_strdup(info+9); + } + sd->call_duration = g_strdup(info + 9); } else if (!strncmp(info, "PARTNER_HANDLE ", 15)) { info += 15; - if (!sd->call_status) + if (!sd->call_status) { return; + } switch (sd->call_status) { case SKYPE_CALL_RINGING: - if (sd->call_out) + if (sd->call_out) { imcb_log(ic, "You are currently ringing the user %s.", info); - else { + } else { g_snprintf(buf, IRC_LINE_SIZE, - "The user %s is currently ringing you.", - info); + "The user %s is currently ringing you.", + info); skype_call_ask(ic, sd->call_id, buf); } break; case SKYPE_CALL_MISSED: imcb_log(ic, "You have missed a call from user %s.", - info); + info); break; case SKYPE_CALL_CANCELLED: imcb_log(ic, "You cancelled the call to the user %s.", - info); + info); sd->call_status = 0; sd->call_out = FALSE; break; case SKYPE_CALL_REFUSED: - if (sd->call_out) + if (sd->call_out) { imcb_log(ic, "The user %s refused the call.", - info); - else + info); + } else { imcb_log(ic, - "You refused the call from user %s.", - info); + "You refused the call from user %s.", + info); + } sd->call_out = FALSE; break; case SKYPE_CALL_FINISHED: - if (sd->call_duration) + if (sd->call_duration) { imcb_log(ic, - "You finished the call to the user %s " - "(duration: %s seconds).", - info, sd->call_duration); - else + "You finished the call to the user %s " + "(duration: %s seconds).", + info, sd->call_duration); + } else { imcb_log(ic, - "You finished the call to the user %s.", - info); + "You finished the call to the user %s.", + info); + } sd->call_out = FALSE; break; default: @@ -782,21 +824,23 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line) struct skype_data *sd = ic->proto_data; char *id = strchr(line, ' '); - if (!++id) + if (!++id) { return; + } char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; if (!strcmp(info, "STATUS NEW")) { skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", - id); + id); sd->filetransfer_status = SKYPE_FILETRANSFER_NEW; } else if (!strcmp(info, "STATUS FAILED")) { skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", - id); + id); sd->filetransfer_status = SKYPE_FILETRANSFER_FAILED; } else if (!strcmp(info, "STATUS COMPLETED")) { skype_printf(ic, "GET FILETRANSFER %s PARTNER_HANDLE\n", id); @@ -809,23 +853,25 @@ static void skype_parse_filetransfer(struct im_connection *ic, char *line) sd->filetransfer_path = g_strdup(info); } else if (!strncmp(info, "PARTNER_HANDLE ", 15)) { info += 15; - if (!sd->filetransfer_status) + if (!sd->filetransfer_status) { return; + } switch (sd->filetransfer_status) { case SKYPE_FILETRANSFER_NEW: imcb_log(ic, "The user %s offered a new file for you.", - info); + info); break; case SKYPE_FILETRANSFER_FAILED: imcb_log(ic, "Failed to transfer file from user %s.", - info); + info); break; case SKYPE_FILETRANSFER_COMPLETED: imcb_log(ic, "File transfer from user %s completed.", info); break; case SKYPE_FILETRANSFER_TRANSFERRING: if (sd->filetransfer_path) { - imcb_log(ic, "File transfer from user %s started, saving to %s.", info, sd->filetransfer_path); + imcb_log(ic, "File transfer from user %s started, saving to %s.", info, + sd->filetransfer_path); g_free(sd->filetransfer_path); sd->filetransfer_path = NULL; } @@ -841,10 +887,11 @@ static struct skype_group *skype_group_by_id(struct im_connection *ic, int id) int i; for (i = 0; i < g_list_length(sd->groups); i++) { - struct skype_group *sg = (struct skype_group *)g_list_nth_data(sd->groups, i); + struct skype_group *sg = (struct skype_group *) g_list_nth_data(sd->groups, i); - if (sg->id == id) + if (sg->id == id) { return sg; + } } return NULL; } @@ -858,8 +905,9 @@ static void skype_group_free(struct skype_group *sg, gboolean usersonly) g_free(user); } sg->users = NULL; - if (usersonly) + if (usersonly) { return; + } g_free(sg->name); g_free(sg); } @@ -882,13 +930,15 @@ static void skype_parse_group(struct im_connection *ic, char *line) struct skype_data *sd = ic->proto_data; char *id = strchr(line, ' '); - if (!++id) + if (!++id) { return; + } char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; @@ -922,9 +972,10 @@ static void skype_parse_group(struct im_connection *ic, char *line) } g_strfreev(users); skype_group_users(ic, sg); - } else + } else { log_message(LOGLVL_ERROR, - "No skype group with id %s. That's probably a bug.", id); + "No skype group with id %s. That's probably a bug.", id); + } } else if (!strncmp(info, "NROFUSERS ", 10)) { if (!sd->pending_user) { /* Number of users changed in this group, query its type to see @@ -941,12 +992,14 @@ static void skype_parse_group(struct im_connection *ic, char *line) skype_printf(ic, "ALTER GROUP %d ADDUSER %s\n", sg->id, sd->pending_user); g_free(sd->pending_user); sd->pending_user = NULL; - } else + } else { log_message(LOGLVL_ERROR, - "No skype group with id %s. That's probably a bug.", id); - } else if (!strcmp(info, "TYPE CUSTOM_GROUP")) + "No skype group with id %s. That's probably a bug.", id); + } + } else if (!strcmp(info, "TYPE CUSTOM_GROUP")) { /* This one is interesting, query its users. */ skype_printf(ic, "GET GROUP %s USERS\n", id); + } } static void skype_parse_chat(struct im_connection *ic, char *line) @@ -955,19 +1008,22 @@ static void skype_parse_chat(struct im_connection *ic, char *line) char buf[IRC_LINE_SIZE]; char *id = strchr(line, ' '); - if (!++id) + if (!++id) { return; + } struct groupchat *gc; char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; /* Remove fake chat if we created one in skype_chat_with() */ gc = bee_chat_by_title(ic->bee, ic, ""); - if (gc) + if (gc) { imcb_chat_free(gc); + } if (!strcmp(info, "STATUS MULTI_SUBSCRIBED")) { gc = bee_chat_by_title(ic->bee, ic, id); if (!gc) { @@ -987,7 +1043,7 @@ static void skype_parse_chat(struct im_connection *ic, char *line) * just leave it out. */ /*skype_printf(ic, "OPEN CHAT %s\n", id);*/ g_snprintf(buf, IRC_LINE_SIZE, "%s@skype.com", - sd->groupchat_with); + sd->groupchat_with); imcb_chat_add_buddy(gc, buf); imcb_chat_add_buddy(gc, sd->username); g_free(sd->groupchat_with); @@ -996,8 +1052,9 @@ static void skype_parse_chat(struct im_connection *ic, char *line) skype_printf(ic, "GET CHAT %s TOPIC\n", id); } else if (!strcmp(info, "STATUS UNSUBSCRIBED")) { gc = bee_chat_by_title(ic->bee, ic, id); - if (gc) - gc->data = (void *)FALSE; + if (gc) { + gc->data = (void *) FALSE; + } } else if (!strncmp(info, "ADDER ", 6)) { info += 6; g_free(sd->adder); @@ -1014,28 +1071,32 @@ static void skype_parse_chat(struct im_connection *ic, char *line) g_free(sd->adder); sd->adder = NULL; } - } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14) ) { - if (!strncmp(info, "MEMBERS ", 8)) + } else if (!strncmp(info, "MEMBERS ", 8) || !strncmp(info, "ACTIVEMEMBERS ", 14)) { + if (!strncmp(info, "MEMBERS ", 8)) { info += 8; - else + } else { info += 14; + } gc = bee_chat_by_title(ic->bee, ic, id); /* Hack! We set ->data to TRUE * while we're on the channel * so that we won't rejoin * after a /part. */ - if (!gc || gc->data) + if (!gc || gc->data) { return; + } char **members = g_strsplit(info, " ", 0); int i; for (i = 0; members[i]; i++) { - if (!strcmp(members[i], sd->username)) + if (!strcmp(members[i], sd->username)) { continue; + } g_snprintf(buf, IRC_LINE_SIZE, "%s@skype.com", - members[i]); + members[i]); if (!g_list_find_custom(gc->in_room, buf, - (GCompareFunc)strcmp)) + (GCompareFunc) strcmp)) { imcb_chat_add_buddy(gc, buf); + } } imcb_chat_add_buddy(gc, sd->username); g_strfreev(members); @@ -1044,9 +1105,9 @@ static void skype_parse_chat(struct im_connection *ic, char *line) static void skype_parse_password(struct im_connection *ic, char *line) { - if (!strncmp(line+9, "OK", 2)) + if (!strncmp(line + 9, "OK", 2)) { imcb_connected(ic); - else { + } else { imcb_error(ic, "Authentication Failed"); imc_logout(ic, TRUE); } @@ -1054,7 +1115,7 @@ static void skype_parse_password(struct im_connection *ic, char *line) static void skype_parse_profile(struct im_connection *ic, char *line) { - imcb_log(ic, "SkypeOut balance value is '%s'.", line+21); + imcb_log(ic, "SkypeOut balance value is '%s'.", line + 21); } static void skype_parse_ping(struct im_connection *ic, char *line) @@ -1080,8 +1141,9 @@ static void skype_parse_chats(struct im_connection *ic, char *line) static void skype_parse_groups(struct im_connection *ic, char *line) { - if (!set_getbool(&ic->acc->set, "read_groups")) + if (!set_getbool(&ic->acc->set, "read_groups")) { return; + } char **i; char **groups = g_strsplit(line + 7, ", ", 0); @@ -1099,13 +1161,15 @@ static void skype_parse_alter_group(struct im_connection *ic, char *line) { char *id = line + strlen("ALTER GROUP"); - if (!++id) + if (!++id) { return; + } char *info = strchr(id, ' '); - if (!info) + if (!info) { return; + } *info = '\0'; info++; @@ -1118,16 +1182,17 @@ static void skype_parse_alter_group(struct im_connection *ic, char *line) sg->users = g_list_append(sg->users, g_strdup(info)); imcb_add_buddy(ic, buf, sg->name); g_free(buf); - } else + } else { log_message(LOGLVL_ERROR, - "No skype group with id %s. That's probably a bug.", id); + "No skype group with id %s. That's probably a bug.", id); + } } } typedef void (*skype_parser)(struct im_connection *ic, char *line); static gboolean skype_read_callback(gpointer data, gint fd, - b_input_condition cond) + b_input_condition cond) { struct im_connection *ic = data; struct skype_data *sd = ic->proto_data; @@ -1157,11 +1222,12 @@ static gboolean skype_read_callback(gpointer data, gint fd, fd = fd; cond = cond; - if (!sd || sd->fd == -1) + if (!sd || sd->fd == -1) { return FALSE; + } /* Read the whole data. */ st = ssl_read(sd->ssl, buf, sizeof(buf)); - if (st >= IRC_LINE_SIZE-1) { + if (st >= IRC_LINE_SIZE - 1) { /* As we don't buffer incoming data, if IRC_LINE_SIZE amount of bytes * were received, there's a good chance last message was truncated * and the next recv() will yield garbage. */ @@ -1174,16 +1240,19 @@ static gboolean skype_read_callback(gpointer data, gint fd, lines = g_strsplit(buf, "\n", 0); lineptr = lines; while ((line = *lineptr)) { - if (!strlen(line)) + if (!strlen(line)) { break; - if (set_getbool(&ic->acc->set, "skypeconsole_receive")) + } + if (set_getbool(&ic->acc->set, "skypeconsole_receive")) { imcb_buddy_msg(ic, "skypeconsole", line, 0, 0); - for (i = 0; i < ARRAY_SIZE(parsers); i++) + } + for (i = 0; i < ARRAY_SIZE(parsers); i++) { if (!strncmp(line, parsers[i].k, - strlen(parsers[i].k))) { + strlen(parsers[i].k))) { parsers[i].v(ic, line); break; } + } lineptr++; } g_strfreev(lines); @@ -1204,12 +1273,14 @@ gboolean skype_start_stream(struct im_connection *ic) struct skype_data *sd = ic->proto_data; int st; - if (!sd) + if (!sd) { return FALSE; + } - if (sd->bfd <= 0) + if (sd->bfd <= 0) { sd->bfd = b_input_add(sd->fd, B_EV_IO_READ, - skype_read_callback, ic); + skype_read_callback, ic); + } /* Log in */ skype_printf(ic, "USERNAME %s\n", ic->acc->user); @@ -1259,14 +1330,15 @@ static void skype_login(account_t *acc) imcb_log(ic, "Connecting"); sd->ssl = ssl_connect(set_getstr(&acc->set, "server"), - set_getint(&acc->set, "port"), FALSE, skype_connected, ic); + set_getint(&acc->set, "port"), FALSE, skype_connected, ic); sd->fd = sd->ssl ? ssl_getfd(sd->ssl) : -1; sd->username = g_strdup(acc->user); sd->ic = ic; - if (set_getbool(&acc->set, "skypeconsole")) + if (set_getbool(&acc->set, "skypeconsole")) { imcb_add_buddy(ic, "skypeconsole", NULL); + } } static void skype_logout(struct im_connection *ic) @@ -1276,16 +1348,18 @@ static void skype_logout(struct im_connection *ic) skype_printf(ic, "SET USERSTATUS OFFLINE\n"); - while (ic->groupchats) + while (ic->groupchats) { imcb_chat_free(ic->groupchats->data); + } for (i = 0; i < g_list_length(sd->groups); i++) { - struct skype_group *sg = (struct skype_group *)g_list_nth_data(sd->groups, i); + struct skype_group *sg = (struct skype_group *) g_list_nth_data(sd->groups, i); skype_group_free(sg, FALSE); } - if (sd->ssl) + if (sd->ssl) { ssl_disconnect(sd->ssl); + } g_free(sd->username); g_free(sd->handle); @@ -1294,7 +1368,7 @@ static void skype_logout(struct im_connection *ic) } static int skype_buddy_msg(struct im_connection *ic, char *who, char *message, - int flags) + int flags) { char *ptr, *nick; int st; @@ -1304,13 +1378,15 @@ static int skype_buddy_msg(struct im_connection *ic, char *who, char *message, nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } - if (!strncmp(who, "skypeconsole", 12)) + if (!strncmp(who, "skypeconsole", 12)) { st = skype_printf(ic, "%s\n", message); - else + } else { st = skype_printf(ic, "MESSAGE %s %s\n", nick, message); + } g_free(nick); return st; @@ -1320,25 +1396,28 @@ const struct skype_away_state *skype_away_state_by_name(char *name) { int i; - for (i = 0; skype_away_state_list[i].full_name; i++) - if (g_strcasecmp(skype_away_state_list[i].full_name, name) == 0) + for (i = 0; skype_away_state_list[i].full_name; i++) { + if (g_strcasecmp(skype_away_state_list[i].full_name, name) == 0) { return skype_away_state_list + i; + } + } return NULL; } static void skype_set_away(struct im_connection *ic, char *state_txt, - char *message) + char *message) { const struct skype_away_state *state; /* Unused parameter */ message = message; - if (state_txt == NULL) + if (state_txt == NULL) { state = skype_away_state_by_name("Online"); - else + } else { state = skype_away_state_by_name(state_txt); + } skype_printf(ic, "SET USERSTATUS %s\n", state->code); } @@ -1350,10 +1429,12 @@ static GList *skype_away_states(struct im_connection *ic) /* Unused parameter */ ic = ic; - if (l == NULL) - for (i = 0; skype_away_state_list[i].full_name; i++) + if (l == NULL) { + for (i = 0; skype_away_state_list[i].full_name; i++) { l = g_list_append(l, - (void *)skype_away_state_list[i].full_name); + (void *) skype_away_state_list[i].full_name); + } + } return l; } @@ -1390,8 +1471,9 @@ static void skype_call(struct im_connection *ic, char *value) char *nick = g_strdup(value); char *ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } skype_printf(ic, "CALL %s\n", nick); g_free(nick); } @@ -1402,11 +1484,12 @@ static void skype_hangup(struct im_connection *ic) if (sd->call_id) { skype_printf(ic, "SET CALL %s STATUS FINISHED\n", - sd->call_id); + sd->call_id); g_free(sd->call_id); sd->call_id = 0; - } else + } else { imcb_error(ic, "There are no active calls currently."); + } } static char *skype_set_call(set_t *set, char *value) @@ -1414,10 +1497,11 @@ static char *skype_set_call(set_t *set, char *value) account_t *acc = set->data; struct im_connection *ic = acc->ic; - if (value) + if (value) { skype_call(ic, value); - else + } else { skype_hangup(ic); + } return value; } @@ -1428,12 +1512,13 @@ static void skype_add_buddy(struct im_connection *ic, char *who, char *group) nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } if (!group) { skype_printf(ic, "SET USER %s BUDDYSTATUS 2 Please authorize me\n", - nick); + nick); g_free(nick); } else { struct skype_group *sg = skype_group_by_name(ic, group); @@ -1458,8 +1543,9 @@ static void skype_remove_buddy(struct im_connection *ic, char *who, char *group) nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } skype_printf(ic, "SET USER %s BUDDYSTATUS 1\n", nick); g_free(nick); } @@ -1477,8 +1563,9 @@ void skype_chat_msg(struct groupchat *gc, char *message, int flags) void skype_chat_leave(struct groupchat *gc) { struct im_connection *ic = gc->ic; + skype_printf(ic, "ALTER CHAT %s LEAVE\n", gc->title); - gc->data = (void *)TRUE; + gc->data = (void *) TRUE; } void skype_chat_invite(struct groupchat *gc, char *who, char *message) @@ -1488,8 +1575,9 @@ void skype_chat_invite(struct groupchat *gc, char *who, char *message) nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } skype_printf(ic, "ALTER CHAT %s ADDMEMBERS %s\n", gc->title, nick); g_free(nick); } @@ -1498,8 +1586,9 @@ void skype_chat_topic(struct groupchat *gc, char *message) { struct im_connection *ic = gc->ic; struct skype_data *sd = ic->proto_data; + skype_printf(ic, "ALTER CHAT %s SETTOPIC %s\n", - gc->title, message); + gc->title, message); sd->topic_wait = 1; } @@ -1507,10 +1596,12 @@ struct groupchat *skype_chat_with(struct im_connection *ic, char *who) { struct skype_data *sd = ic->proto_data; char *ptr, *nick; + nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } skype_printf(ic, "CHAT CREATE %s\n", nick); sd->groupchat_with = g_strdup(nick); g_free(nick); @@ -1523,10 +1614,12 @@ static void skype_get_info(struct im_connection *ic, char *who) { struct skype_data *sd = ic->proto_data; char *ptr, *nick; + nick = g_strdup(who); ptr = strchr(nick, '@'); - if (ptr) + if (ptr) { *ptr = '\0'; + } sd->is_info = TRUE; skype_printf(ic, "GET USER %s FULLNAME\n", nick); skype_printf(ic, "GET USER %s PHONE_HOME\n", nick); @@ -1555,14 +1648,14 @@ static void skype_init(account_t *acc) set_t *s; s = set_add(&acc->set, "server", SKYPE_DEFAULT_SERVER, set_eval_account, - acc); + acc); s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add(&acc->set, "port", SKYPE_DEFAULT_PORT, set_eval_int, acc); s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add(&acc->set, "display_name", NULL, skype_set_display_name, - acc); + acc); s->flags |= SET_NOSAVE | ACC_SET_ONLINE_ONLY; s = set_add(&acc->set, "mood_text", NULL, skype_set_mood_text, acc); @@ -1580,7 +1673,7 @@ static void skype_init(account_t *acc) s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add(&acc->set, "skypeconsole_receive", "false", set_eval_bool, - acc); + acc); s->flags |= ACC_SET_OFFLINE_ONLY; s = set_add(&acc->set, "auto_join", "false", set_eval_bool, acc); @@ -1592,7 +1685,7 @@ static void skype_init(account_t *acc) s = set_add(&acc->set, "show_moods", "false", set_eval_bool, acc); s = set_add(&acc->set, "edit_prefix", "EDIT:", - NULL, acc); + NULL, acc); s = set_add(&acc->set, "read_groups", "false", set_eval_bool, acc); } @@ -1607,13 +1700,14 @@ GList *skype_buddy_action_list(bee_user_t *bu) if (ret == NULL) { static const struct buddy_action ba[2] = { - {"CALL", "Initiate a call" }, - {"HANGUP", "Hang up a call" }, + { "CALL", "Initiate a call" }, + { "HANGUP", "Hang up a call" }, }; int i; - for (i = 0; i < ARRAY_SIZE(ba); i++) - ret = g_list_prepend(ret, (void *)(ba + i)); + for (i = 0; i < ARRAY_SIZE(ba); i++) { + ret = g_list_prepend(ret, (void *) (ba + i)); + } } return ret; @@ -1625,10 +1719,11 @@ void *skype_buddy_action(struct bee_user *bu, const char *action, char * const a args = args; data = data; - if (!g_strcasecmp(action, "CALL")) + if (!g_strcasecmp(action, "CALL")) { skype_call(bu->ic, bu->handle); - else if (!g_strcasecmp(action, "HANGUP")) + } else if (!g_strcasecmp(action, "HANGUP")) { skype_hangup(bu->ic); + } return NULL; } diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index eb30187f..f3dcde31 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -90,14 +90,15 @@ static struct twitter_filter *twitter_filter_get(struct groupchat *c, { struct twitter_data *td = c->ic->proto_data; struct twitter_filter *tf = NULL; - struct twitter_filter tfc = {type, (char*) text}; + struct twitter_filter tfc = { type, (char *) text }; GSList *l; for (l = td->filters; l; l = g_slist_next(l)) { tf = l->data; - if (twitter_filter_cmp(tf, &tfc) == 0) + if (twitter_filter_cmp(tf, &tfc) == 0) { break; + } tf = NULL; } @@ -109,15 +110,17 @@ static struct twitter_filter *twitter_filter_get(struct groupchat *c, td->filters = g_slist_prepend(td->filters, tf); } - if (!g_slist_find(tf->groupchats, c)) + if (!g_slist_find(tf->groupchats, c)) { tf->groupchats = g_slist_prepend(tf->groupchats, c); + } - if (td->filter_update_id > 0) + if (td->filter_update_id > 0) { b_event_remove(td->filter_update_id); + } /* Wait for other possible filter changes to avoid request spam */ td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT, - twitter_filter_update, c->ic); + twitter_filter_update, c->ic); return tf; } @@ -148,12 +151,14 @@ static void twitter_filter_remove(struct groupchat *c) } } - if (td->filter_update_id > 0) + if (td->filter_update_id > 0) { b_event_remove(td->filter_update_id); + } /* Wait for other possible filter changes to avoid request spam */ td->filter_update_id = b_timeout_add(TWITTER_FILTER_UPDATE_WAIT, - twitter_filter_update, c->ic);} + twitter_filter_update, c->ic); +} static void twitter_filter_remove_all(struct im_connection *ic) { @@ -168,8 +173,9 @@ static void twitter_filter_remove_all(struct im_connection *ic) /* Build up a list of groupchats to be freed */ for (p = tf->groupchats; p; p = g_slist_next(p)) { - if (!g_slist_find(chats, p->data)) + if (!g_slist_find(chats, p->data)) { chats = g_slist_prepend(chats, p->data); + } } p = l; @@ -216,8 +222,9 @@ static GSList *twitter_filter_parse(struct groupchat *c, const char *text) }; for (f = fs; *f; f++) { - if ((v = strchr(*f, ':')) == NULL) + if ((v = strchr(*f, ':')) == NULL) { continue; + } *(v++) = 0; @@ -228,8 +235,9 @@ static GSList *twitter_filter_parse(struct groupchat *c, const char *text) } } - if (t < 0 || strlen(v) == 0) + if (t < 0 || strlen(v) == 0) { continue; + } tf = twitter_filter_get(c, types[t], v); ret = g_slist_prepend(ret, tf); @@ -247,8 +255,9 @@ gboolean twitter_main_loop(gpointer data, gint fd, b_input_condition cond) struct im_connection *ic = data; // Check if we are still logged in... - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return FALSE; + } // Do stuff.. return twitter_get_timeline(ic, -1) && @@ -260,24 +269,27 @@ static void twitter_main_loop_start(struct im_connection *ic) struct twitter_data *td = ic->proto_data; char *last_tweet = set_getstr(&ic->acc->set, "_last_tweet"); - if (last_tweet) + + if (last_tweet) { td->timeline_id = g_ascii_strtoull(last_tweet, NULL, 0); + } /* Create the room now that we "logged in". */ - if (td->flags & TWITTER_MODE_CHAT) + if (td->flags & TWITTER_MODE_CHAT) { twitter_groupchat_init(ic); + } imcb_log(ic, "Getting initial statuses"); // Run this once. After this queue the main loop function (or open the // stream if available). twitter_main_loop(ic, -1, 0); - + if (set_getbool(&ic->acc->set, "stream")) { /* That fetch was just to get backlog, the stream will give us the rest. \o/ */ twitter_open_stream(ic); - + /* Stream sends keepalives (empty lines) or actual data at least twice a minute. Disconnect if this stops. */ ic->flags |= OPT_PONGS; @@ -285,8 +297,8 @@ static void twitter_main_loop_start(struct im_connection *ic) /* Not using the streaming API, so keep polling the old- fashioned way. :-( */ td->main_loop_id = - b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, - twitter_main_loop, ic); + b_timeout_add(set_getint(&ic->acc->set, "fetch_interval") * 1000, + twitter_main_loop, ic); } } @@ -297,8 +309,9 @@ struct groupchat *twitter_groupchat_init(struct im_connection *ic) struct twitter_data *td = ic->proto_data; GSList *l; - if (td->timeline_gc) + if (td->timeline_gc) { return td->timeline_gc; + } td->timeline_gc = gc = imcb_chat_new(ic, "twitter/timeline"); @@ -308,11 +321,12 @@ struct groupchat *twitter_groupchat_init(struct im_connection *ic) for (l = ic->bee->users; l; l = l->next) { bee_user_t *bu = l->data; - if (bu->ic == ic) + if (bu->ic == ic) { imcb_chat_add_buddy(gc, bu->handle); + } } imcb_chat_add_buddy(gc, ic->acc->user); - + return gc; } @@ -324,14 +338,15 @@ void twitter_login_finish(struct im_connection *ic) td->flags &= ~TWITTER_DOING_TIMELINE; - if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) + if (set_getbool(&ic->acc->set, "oauth") && !td->oauth_info) { twitter_oauth_start(ic); - else if (!(td->flags & TWITTER_MODE_ONE) && - !(td->flags & TWITTER_HAVE_FRIENDS)) { + } else if (!(td->flags & TWITTER_MODE_ONE) && + !(td->flags & TWITTER_HAVE_FRIENDS)) { imcb_log(ic, "Getting contact list"); twitter_get_friends_ids(ic, -1); - } else + } else { twitter_main_loop_start(ic); + } } static const struct oauth_service twitter_oauth = { @@ -356,10 +371,11 @@ static const struct oauth_service *get_oauth_service(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; - if (strstr(td->url_host, "identi.ca")) + if (strstr(td->url_host, "identi.ca")) { return &identica_oauth; - else + } else { return &twitter_oauth; + } /* Could add more services, or allow configuring your own base URL + API keys. */ @@ -371,10 +387,11 @@ static void twitter_oauth_start(struct im_connection *ic) const char *url = set_getstr(&ic->acc->set, "base_url"); imcb_log(ic, "Requesting OAuth request token"); - - if (!strstr(url, "twitter.com") && !strstr(url, "identi.ca")) + + if (!strstr(url, "twitter.com") && !strstr(url, "identi.ca")) { imcb_log(ic, "Warning: OAuth only works with identi.ca and " - "Twitter."); + "Twitter."); + } td->oauth_info = oauth_request_token(get_oauth_service(ic), twitter_oauth_callback, ic); @@ -388,8 +405,9 @@ static gboolean twitter_oauth_callback(struct oauth_info *info) struct im_connection *ic = info->data; struct twitter_data *td; - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return FALSE; + } td = ic->proto_data; if (info->stage == OAUTH_REQUEST_TOKEN) { @@ -403,24 +421,25 @@ static gboolean twitter_oauth_callback(struct oauth_info *info) name = g_strdup_printf("%s_%s", td->prefix, ic->acc->user); msg = g_strdup_printf("To finish OAuth authentication, please visit " - "%s and respond with the resulting PIN code.", - info->auth_url); + "%s and respond with the resulting PIN code.", + info->auth_url); imcb_buddy_msg(ic, name, msg, 0, 0); g_free(name); g_free(msg); } else if (info->stage == OAUTH_ACCESS_TOKEN) { const char *sn; - + if (info->token == NULL || info->token_secret == NULL) { imcb_error(ic, "OAuth error: %s", twitter_parse_error(info->http)); imc_logout(ic, TRUE); return FALSE; } - + if ((sn = oauth_params_get(&info->params, "screen_name"))) { - if (ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) + if (ic->acc->prpl->handle_cmp(sn, ic->acc->user) != 0) { imcb_log(ic, "Warning: You logged in via OAuth as %s " "instead of %s.", sn, ic->acc->user); + } g_free(td->user); td->user = g_strdup(sn); } @@ -443,16 +462,18 @@ int twitter_url_len_diff(gchar *msg, unsigned int target_len) static GRegex *regex = NULL; GMatchInfo *match_info; - if (regex == NULL) + if (regex == NULL) { regex = g_regex_new("(^|\\s)(http(s)?://[^\\s$]+)", 0, 0, NULL); - + } + g_regex_match(regex, msg, 0, &match_info); while (g_match_info_matches(match_info)) { gchar *url = g_match_info_fetch(match_info, 2); url_len_diff += target_len - g_utf8_strlen(url, -1); /* Add another character for https://t.co/... URLs */ - if (g_match_info_fetch(match_info, 3) != NULL) + if (g_match_info_fetch(match_info, 3) != NULL) { url_len_diff += 1; + } g_free(url); g_match_info_next(match_info, NULL); } @@ -467,11 +488,13 @@ static gboolean twitter_length_check(struct im_connection *ic, gchar * msg) int target_len = set_getint(&ic->acc->set, "target_url_length"); int url_len_diff = 0; - if (target_len > 0) + if (target_len > 0) { url_len_diff = twitter_url_len_diff(msg, target_len); + } - if (max == 0 || (len = g_utf8_strlen(msg, -1) + url_len_diff) <= max) + if (max == 0 || (len = g_utf8_strlen(msg, -1) + url_len_diff) <= max) { return TRUE; + } twitter_log(ic, "Maximum message length exceeded: %d > %d", len, max); @@ -480,19 +503,21 @@ static gboolean twitter_length_check(struct im_connection *ic, gchar * msg) static char *set_eval_commands(set_t * set, char *value) { - if (g_strcasecmp(value, "strict") == 0 ) + if (g_strcasecmp(value, "strict") == 0) { return value; - else + } else { return set_eval_bool(set, value); + } } static char *set_eval_mode(set_t * set, char *value) { if (g_strcasecmp(value, "one") == 0 || - g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) + g_strcasecmp(value, "many") == 0 || g_strcasecmp(value, "chat") == 0) { return value; - else + } else { return NULL; + } } static void twitter_init(account_t * acc) @@ -506,7 +531,7 @@ static void twitter_init(account_t * acc) def_url = TWITTER_API_URL; def_tul = "22"; def_mentions = "true"; - } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ + } else { /* if( strcmp( acc->prpl->name, "identica" ) == 0 ) */ def_url = IDENTICA_API_URL; def_tul = "0"; def_mentions = "false"; @@ -538,7 +563,7 @@ static void twitter_init(account_t * acc) s = set_add(&acc->set, "show_old_mentions", "0", set_eval_int, acc); s = set_add(&acc->set, "strip_newlines", "false", set_eval_bool, acc); - + s = set_add(&acc->set, "_last_tweet", "0", NULL, acc); s->flags |= SET_HIDDEN | SET_NOSAVE; @@ -559,7 +584,7 @@ static void twitter_login(account_t * acc) char name[strlen(acc->user) + 9]; url_t url; char *s; - + if (!url_set(&url, set_getstr(&ic->acc->set, "base_url")) || (url.proto != PROTO_HTTP && url.proto != PROTO_HTTPS)) { imcb_error(ic, "Incorrect API base URL: %s", set_getstr(&ic->acc->set, "base_url")); @@ -570,7 +595,7 @@ static void twitter_login(account_t * acc) if (!strstr(url.host, "twitter.com") && set_getbool(&ic->acc->set, "stream")) { imcb_error(ic, "Warning: The streaming API is only supported by Twitter, " - "and you seem to be connecting to a different service."); + "and you seem to be connecting to a different service."); } imcb_log(ic, "Connecting"); @@ -583,21 +608,23 @@ static void twitter_login(account_t * acc) td->url_ssl = url.proto == PROTO_HTTPS; td->url_port = url.port; td->url_host = g_strdup(url.host); - if (strcmp(url.file, "/") != 0) + if (strcmp(url.file, "/") != 0) { td->url_path = g_strdup(url.file); - else { + } else { td->url_path = g_strdup(""); - if (g_str_has_suffix(url.host, "twitter.com")) + if (g_str_has_suffix(url.host, "twitter.com")) { /* May fire for people who turned on HTTPS. */ imcb_error(ic, "Warning: Twitter requires a version number in API calls " - "now. Try resetting the base_url account setting."); + "now. Try resetting the base_url account setting."); + } } - + /* Hacky string mangling: Turn identi.ca into identi.ca and api.twitter.com into twitter, and try to be sensible if we get anything else. */ td->prefix = g_strdup(url.host); - if (g_str_has_suffix(td->prefix, ".com")) + if (g_str_has_suffix(td->prefix, ".com")) { td->prefix[strlen(url.host) - 4] = '\0'; + } if ((s = strrchr(td->prefix, '.')) && strlen(s) > 4) { /* If we have at least 3 chars after the last dot, cut off the rest. (mostly a www/api prefix or sth) */ @@ -605,9 +632,10 @@ static void twitter_login(account_t * acc) g_free(td->prefix); td->prefix = s; } - - if (strstr(acc->pass, "oauth_token=")) + + if (strstr(acc->pass, "oauth_token=")) { td->oauth_info = oauth_from_string(acc->pass, get_oauth_service(ic)); + } sprintf(name, "%s_%s", td->prefix, acc->user); imcb_add_buddy(ic, name, NULL); @@ -615,14 +643,15 @@ static void twitter_login(account_t * acc) td->log = g_new0(struct twitter_log_data, TWITTER_LOG_LENGTH); td->log_id = -1; - + s = set_getstr(&ic->acc->set, "mode"); - if (g_strcasecmp(s, "one") == 0) + if (g_strcasecmp(s, "one") == 0) { td->flags |= TWITTER_MODE_ONE; - else if (g_strcasecmp(s, "many") == 0) + } else if (g_strcasecmp(s, "many") == 0) { td->flags |= TWITTER_MODE_MANY; - else + } else { td->flags |= TWITTER_MODE_CHAT; + } twitter_login_finish(ic); } @@ -640,12 +669,14 @@ static void twitter_logout(struct im_connection *ic) // Remove the main_loop function from the function queue. b_event_remove(td->main_loop_id); - if (td->timeline_gc) + if (td->timeline_gc) { imcb_chat_free(td->timeline_gc); + } if (td) { - if (td->filter_update_id > 0) + if (td->filter_update_id > 0) { b_event_remove(td->filter_update_id); + } http_close(td->stream); twitter_filter_remove_all(ic); @@ -678,19 +709,21 @@ static int twitter_buddy_msg(struct im_connection *ic, char *who, char *message, char pin[strlen(message) + 1], *s; strcpy(pin, message); - for (s = pin + sizeof(pin) - 2; s > pin && g_ascii_isspace(*s); s--) + for (s = pin + sizeof(pin) - 2; s > pin && g_ascii_isspace(*s); s--) { *s = '\0'; + } for (s = pin; *s && g_ascii_isspace(*s); s++) { } if (!oauth_access_token(s, td->oauth_info)) { imcb_error(ic, "OAuth error: %s", - "Failed to send access token request"); + "Failed to send access token request"); imc_logout(ic, TRUE); return FALSE; } - } else + } else { twitter_handle_command(ic, message); + } } else { twitter_direct_messages_new(ic, who, message); } @@ -713,8 +746,9 @@ static void twitter_remove_buddy(struct im_connection *ic, char *who, char *grou static void twitter_chat_msg(struct groupchat *c, char *message, int flags) { - if (c && message) + if (c && message) { twitter_handle_command(c->ic, message); + } } static void twitter_chat_invite(struct groupchat *c, char *who, char *message) @@ -736,17 +770,20 @@ static struct groupchat *twitter_chat_join(struct im_connection *ic, for (l = fs; l; l = g_slist_next(l)) { tf = l->data; - if (topic->len > 0) + if (topic->len > 0) { g_string_append(topic, ", "); + } - if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) + if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) { g_string_append_c(topic, '@'); + } g_string_append(topic, tf->text); } - if (topic->len > 0) + if (topic->len > 0) { g_string_prepend(topic, "Twitter Filter: "); + } imcb_chat_topic(c, NULL, topic->str, 0); imcb_chat_add_buddy(c, ic->acc->user); @@ -819,40 +856,48 @@ static void twitter_buddy_data_free(struct bee_user *bu) * * Returns 0 if the user provides garbage. */ -static guint64 twitter_message_id_from_command_arg(struct im_connection *ic, char *arg, bee_user_t **bu_) { +static guint64 twitter_message_id_from_command_arg(struct im_connection *ic, char *arg, bee_user_t **bu_) +{ struct twitter_data *td = ic->proto_data; struct twitter_user_data *tud; bee_user_t *bu = NULL; guint64 id = 0; - - if (bu_) + + if (bu_) { *bu_ = NULL; - if (!arg || !arg[0]) + } + if (!arg || !arg[0]) { return 0; - + } + if (arg[0] != '#' && (bu = bee_user_by_handle(ic->bee, ic, arg))) { - if ((tud = bu->data)) + if ((tud = bu->data)) { id = tud->last_id; + } } else { - if (arg[0] == '#') + if (arg[0] == '#') { arg++; + } if (sscanf(arg, "%" G_GINT64_MODIFIER "x", &id) == 1 && id < TWITTER_LOG_LENGTH) { bu = td->log[id].bu; id = td->log[id].id; /* Beware of dangling pointers! */ - if (!g_slist_find(ic->bee->users, bu)) + if (!g_slist_find(ic->bee->users, bu)) { bu = NULL; + } } else if (sscanf(arg, "%" G_GINT64_MODIFIER "d", &id) == 1) { /* Allow normal tweet IDs as well; not a very useful feature but it's always been there. Just ignore very low IDs to avoid accidents. */ - if (id < 1000000) + if (id < 1000000) { id = 0; + } } } - if (bu_) + if (bu_) { *bu_ = bu; + } return id; } @@ -862,7 +907,7 @@ static void twitter_handle_command(struct im_connection *ic, char *message) char *cmds, **cmd, *new = NULL; guint64 in_reply_to = 0, id; gboolean allow_post = - g_strcasecmp(set_getstr(&ic->acc->set, "commands"), "strict") != 0; + g_strcasecmp(set_getstr(&ic->acc->set, "commands"), "strict") != 0; bee_user_t *bu = NULL; cmds = g_strdup(message); @@ -873,17 +918,18 @@ static void twitter_handle_command(struct im_connection *ic, char *message) } else if (!set_getbool(&ic->acc->set, "commands") && allow_post) { /* Not supporting commands if "commands" is set to true/strict. */ } else if (g_strcasecmp(cmd[0], "undo") == 0) { - if (cmd[1] == NULL) + if (cmd[1] == NULL) { twitter_status_destroy(ic, td->last_status_id); - else if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) + } else if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { twitter_status_destroy(ic, id); - else + } else { twitter_log(ic, "Could not undo last action"); + } goto eof; } else if ((g_strcasecmp(cmd[0], "favourite") == 0 || - g_strcasecmp(cmd[0], "favorite") == 0 || - g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) { + g_strcasecmp(cmd[0], "favorite") == 0 || + g_strcasecmp(cmd[0], "fav") == 0) && cmd[1]) { if ((id = twitter_message_id_from_command_arg(ic, cmd[1], NULL))) { twitter_favourite_tweet(ic, id); } else { @@ -899,33 +945,35 @@ static void twitter_handle_command(struct im_connection *ic, char *message) } else if ((g_strcasecmp(cmd[0], "report") == 0 || g_strcasecmp(cmd[0], "spam") == 0) && cmd[1]) { char *screen_name; - + /* Report nominally works on users but look up the user who posted the given ID if the user wants to do it that way */ twitter_message_id_from_command_arg(ic, cmd[1], &bu); - if (bu) + if (bu) { screen_name = bu->handle; - else + } else { screen_name = cmd[1]; - + } + twitter_report_spam(ic, screen_name); goto eof; } else if (g_strcasecmp(cmd[0], "rt") == 0 && cmd[1]) { id = twitter_message_id_from_command_arg(ic, cmd[1], NULL); td->last_status_id = 0; - if (id) + if (id) { twitter_status_retweet(ic, id); - else + } else { twitter_log(ic, "User `%s' does not exist or didn't " - "post any statuses recently", cmd[1]); + "post any statuses recently", cmd[1]); + } goto eof; } else if (g_strcasecmp(cmd[0], "reply") == 0 && cmd[1] && cmd[2]) { id = twitter_message_id_from_command_arg(ic, cmd[1], &bu); if (!id || !bu) { twitter_log(ic, "User `%s' does not exist or didn't " - "post any statuses recently", cmd[1]); + "post any statuses recently", cmd[1]); goto eof; } message = new = g_strdup_printf("@%s %s", bu->handle, cmd[2]); @@ -948,8 +996,9 @@ static void twitter_handle_command(struct im_connection *ic, char *message) if (allow_post) { char *s; - if (!twitter_length_check(ic, message)) + if (!twitter_length_check(ic, message)) { goto eof; + } s = cmd[0] + strlen(cmd[0]) - 1; if (!new && s > cmd[0] && (*s == ':' || *s == ',')) { @@ -959,12 +1008,13 @@ static void twitter_handle_command(struct im_connection *ic, char *message) struct twitter_user_data *tud = bu->data; new = g_strdup_printf("@%s %s", bu->handle, - message + (s - cmd[0]) + 2); + message + (s - cmd[0]) + 2); message = new; if (time(NULL) < tud->last_time + - set_getint(&ic->acc->set, "auto_reply_timeout")) + set_getint(&ic->acc->set, "auto_reply_timeout")) { in_reply_to = tud->last_id; + } } } @@ -980,21 +1030,22 @@ eof: g_free(cmds); } -void twitter_log(struct im_connection *ic, char *format, ... ) +void twitter_log(struct im_connection *ic, char *format, ...) { struct twitter_data *td = ic->proto_data; va_list params; char *text; - + va_start(params, format); text = g_strdup_vprintf(format, params); va_end(params); - - if (td->timeline_gc) + + if (td->timeline_gc) { imcb_chat_log(td->timeline_gc, "%s", text); - else + } else { imcb_log(ic, "%s", text); - + } + g_free(text); } diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h index 00230cc0..7cfd9148 100644 --- a/protocols/twitter/twitter.h +++ b/protocols/twitter/twitter.h @@ -28,13 +28,12 @@ #define _TWITTER_H #ifdef DEBUG_TWITTER -#define debug( text... ) imcb_log( ic, text ); +#define debug(text ...) imcb_log(ic, text); #else -#define debug( text... ) +#define debug(text ...) #endif -typedef enum -{ +typedef enum { TWITTER_HAVE_FRIENDS = 0x00001, TWITTER_MODE_ONE = 0x00002, TWITTER_MODE_MANY = 0x00004, @@ -44,16 +43,14 @@ typedef enum TWITTER_GOT_MENTIONS = 0x40000, } twitter_flags_t; -typedef enum -{ +typedef enum { TWITTER_FILTER_TYPE_FOLLOW = 0, TWITTER_FILTER_TYPE_TRACK } twitter_filter_type_t; struct twitter_log_data; -struct twitter_data -{ +struct twitter_data { char* user; struct oauth_info *oauth_info; @@ -64,7 +61,7 @@ struct twitter_data GSList *follow_ids; GSList *filters; - + guint64 last_status_id; /* For undo */ gint main_loop_id; gint filter_update_id; @@ -73,7 +70,7 @@ struct twitter_data struct groupchat *timeline_gc; gint http_fails; twitter_flags_t flags; - + /* set base_url */ gboolean url_ssl; int url_port; @@ -81,47 +78,44 @@ struct twitter_data char *url_path; char *prefix; /* Used to generate contact + channel name. */ - + /* set show_ids */ struct twitter_log_data *log; int log_id; }; #define TWITTER_FILTER_UPDATE_WAIT 3000 -struct twitter_filter -{ +struct twitter_filter { twitter_filter_type_t type; char *text; guint64 uid; GSList *groupchats; }; -struct twitter_user_data -{ +struct twitter_user_data { guint64 last_id; time_t last_time; }; #define TWITTER_LOG_LENGTH 256 -struct twitter_log_data -{ +struct twitter_log_data { guint64 id; struct bee_user *bu; /* DANGER: can be a dead pointer. Check it first. */ }; /** - * This has the same function as the msn_connections GSList. We use this to + * This has the same function as the msn_connections GSList. We use this to * make sure the connection is still alive in callbacks before we do anything * else. */ extern GSList *twitter_connections; -void twitter_login_finish( struct im_connection *ic ); +void twitter_login_finish(struct im_connection *ic); struct http_request; -char *twitter_parse_error( struct http_request *req ); +char *twitter_parse_error(struct http_request *req); -void twitter_log(struct im_connection *ic, char *format, ... ); +void twitter_log(struct im_connection *ic, char *format, ...); struct groupchat *twitter_groupchat_init(struct im_connection *ic); #endif //_TWITTER_H diff --git a/protocols/twitter/twitter_http.c b/protocols/twitter/twitter_http.c index f7ab6e18..7a180b5e 100644 --- a/protocols/twitter/twitter_http.c +++ b/protocols/twitter/twitter_http.c @@ -47,7 +47,7 @@ static char *twitter_url_append(char *url, char *key, char *value); * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c */ struct http_request *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, - gpointer data, int is_post, char **arguments, int arguments_len) + gpointer data, int is_post, char **arguments, int arguments_len) { struct twitter_data *td = ic->proto_data; char *tmp; @@ -67,7 +67,7 @@ struct http_request *twitter_http(struct im_connection *ic, char *url_string, ht url_arguments = tmp; } } - + if (strstr(url_string, "://")) { base_url = g_new0(url_t, 1); if (!url_set(base_url, url_string)) { @@ -75,28 +75,29 @@ struct http_request *twitter_http(struct im_connection *ic, char *url_string, ht return NULL; } } - + // Make the request. g_string_printf(request, "%s %s%s%s%s HTTP/1.1\r\n" - "Host: %s\r\n" - "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n", - is_post ? "POST" : "GET", - base_url ? base_url->file : td->url_path, - base_url ? "" : url_string, - is_post ? "" : "?", is_post ? "" : url_arguments, - base_url ? base_url->host : td->url_host); + "Host: %s\r\n" + "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n", + is_post ? "POST" : "GET", + base_url ? base_url->file : td->url_path, + base_url ? "" : url_string, + is_post ? "" : "?", is_post ? "" : url_arguments, + base_url ? base_url->host : td->url_host); // If a pass and user are given we append them to the request. if (td->oauth_info) { char *full_header; char *full_url; - if (base_url) + if (base_url) { full_url = g_strdup(url_string); - else + } else { full_url = g_strconcat(set_getstr(&ic->acc->set, "base_url"), url_string, NULL); + } full_header = oauth_http_header(td->oauth_info, is_post ? "POST" : "GET", - full_url, url_arguments); + full_url, url_arguments); g_string_append_printf(request, "Authorization: %s\r\n", full_header); g_free(full_header); @@ -115,18 +116,20 @@ struct http_request *twitter_http(struct im_connection *ic, char *url_string, ht if (is_post) { // Append the Content-Type and url-encoded arguments. g_string_append_printf(request, - "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %zd\r\n\r\n%s", - strlen(url_arguments), url_arguments); + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %zd\r\n\r\n%s", + strlen(url_arguments), url_arguments); } else { // Append an extra \r\n to end the request... g_string_append(request, "\r\n"); } - if (base_url) - ret = http_dorequest(base_url->host, base_url->port, base_url->proto == PROTO_HTTPS, request->str, func, data); - else + if (base_url) { + ret = http_dorequest(base_url->host, base_url->port, base_url->proto == PROTO_HTTPS, request->str, func, + data); + } else { ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data); + } g_free(url_arguments); g_string_free(request, TRUE); @@ -135,26 +138,31 @@ struct http_request *twitter_http(struct im_connection *ic, char *url_string, ht } struct http_request *twitter_http_f(struct im_connection *ic, char *url_string, http_input_function func, - gpointer data, int is_post, char **arguments, int arguments_len, twitter_http_flags_t flags) + gpointer data, int is_post, char **arguments, int arguments_len, + twitter_http_flags_t flags) { struct http_request *ret = twitter_http(ic, url_string, func, data, is_post, arguments, arguments_len); - if (ret) + + if (ret) { ret->flags |= flags; + } return ret; } static char *twitter_url_append(char *url, char *key, char *value) { char *key_encoded = g_strndup(key, 3 * strlen(key)); + http_encode(key_encoded); char *value_encoded = g_strndup(value, 3 * strlen(value)); http_encode(value_encoded); char *retval; - if (strlen(url) != 0) + if (strlen(url) != 0) { retval = g_strdup_printf("%s&%s=%s", url, key_encoded, value_encoded); - else + } else { retval = g_strdup_printf("%s=%s", key_encoded, value_encoded); + } g_free(key_encoded); g_free(value_encoded); diff --git a/protocols/twitter/twitter_http.h b/protocols/twitter/twitter_http.h index 09ef350c..d46ee4e5 100644 --- a/protocols/twitter/twitter_http.h +++ b/protocols/twitter/twitter_http.h @@ -38,7 +38,8 @@ struct oauth_info; struct http_request *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, gpointer data, int is_post, char** arguments, int arguments_len); struct http_request *twitter_http_f(struct im_connection *ic, char *url_string, http_input_function func, - gpointer data, int is_post, char** arguments, int arguments_len, twitter_http_flags_t flags); + gpointer data, int is_post, char** arguments, int arguments_len, + twitter_http_flags_t flags); #endif //_TWITTER_HTTP_H diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index c8956606..05932bef 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -23,7 +23,7 @@ ****************************************************************************/ /* For strptime(): */ -#if(__sun) +#if (__sun) #else #define _XOPEN_SOURCE #endif @@ -69,8 +69,9 @@ struct twitter_xml_status { */ static void txu_free(struct twitter_xml_user *txu) { - if (txu == NULL) + if (txu == NULL) { return; + } g_free(txu->name); g_free(txu->screen_name); @@ -82,8 +83,9 @@ static void txu_free(struct twitter_xml_user *txu) */ static void txs_free(struct twitter_xml_status *txs) { - if (txs == NULL) + if (txs == NULL) { return; + } g_free(txs->text); txu_free(txs->user); @@ -97,8 +99,10 @@ static void txs_free(struct twitter_xml_status *txs) static void txl_free(struct twitter_xml_list *txl) { GSList *l; - if (txl == NULL) + + if (txl == NULL) { return; + } for (l = txl->list; l; l = g_slist_next(l)) { if (txl->type == TXL_STATUS) { @@ -147,10 +151,12 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char * /* Necessary so that nicks always get translated to the exact Twitter username. */ imcb_buddy_nick_hint(ic, name, name); - if (td->timeline_gc) + if (td->timeline_gc) { imcb_chat_add_buddy(td->timeline_gc, name); - } else if (td->flags & TWITTER_MODE_MANY) + } + } else if (td->flags & TWITTER_MODE_MANY) { imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL); + } } } @@ -170,8 +176,9 @@ char *twitter_parse_error(struct http_request *req) if (err && err->type == json_array && (err = err->u.array.values[0]) && err->type == json_object) { const char *msg = json_o_str(err, "message"); - if (msg) + if (msg) { ret = g_strdup_printf("%s (%s)", req->status_string, msg); + } } json_value_free(root); } @@ -188,34 +195,37 @@ static json_value *twitter_parse_response(struct im_connection *ic, struct http_ struct twitter_data *td = ic->proto_data; json_value *ret; char path[64] = "", *s; - + if ((s = strchr(req->request, ' '))) { - path[sizeof(path)-1] = '\0'; + path[sizeof(path) - 1] = '\0'; strncpy(path, s + 1, sizeof(path) - 1); - if ((s = strchr(path, '?')) || (s = strchr(path, ' '))) + if ((s = strchr(path, '?')) || (s = strchr(path, ' '))) { *s = '\0'; + } } - + /* Kinda nasty. :-( Trying to suppress error messages, but only for periodic (i.e. mentions/timeline) queries. */ periodic = strstr(path, "timeline") || strstr(path, "mentions"); - + if (req->status_code == 401 && logging_in) { /* IIRC Twitter once had an outage where they were randomly throwing 401s so I'll keep treating this one as fatal only during login. */ imcb_error(ic, "Authentication failure (%s)", - twitter_parse_error(req)); + twitter_parse_error(req)); imc_logout(ic, FALSE); return NULL; } else if (req->status_code != 200) { // It didn't go well, output the error and return. - if (!periodic || logging_in || ++td->http_fails >= 5) + if (!periodic || logging_in || ++td->http_fails >= 5) { twitter_log(ic, "Error: Could not retrieve %s: %s", - path, twitter_parse_error(req)); - - if (logging_in) + path, twitter_parse_error(req)); + } + + if (logging_in) { imc_logout(ic, TRUE); + } return NULL; } else { td->http_fails = 0; @@ -223,7 +233,7 @@ static json_value *twitter_parse_response(struct im_connection *ic, struct http_ if ((ret = json_parse(req->reply_body, req->body_size)) == NULL) { imcb_error(ic, "Could not retrieve %s: %s", - path, "XML parse error"); + path, "XML parse error"); } return ret; } @@ -237,6 +247,7 @@ void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor) { // Primitive, but hey! It works... char *args[2]; + args[0] = "cursor"; args[1] = g_strdup_printf("%" G_GINT64_FORMAT, next_cursor); twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2); @@ -256,23 +267,26 @@ static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_ txl->type = TXL_ID; c = json_o_get(node, "ids"); - if (!c || c->type != json_array) + if (!c || c->type != json_array) { return FALSE; + } - for (i = 0; i < c->u.array.length; i ++) { - if (c->u.array.values[i]->type != json_integer) + for (i = 0; i < c->u.array.length; i++) { + if (c->u.array.values[i]->type != json_integer) { continue; - + } + txl->list = g_slist_prepend(txl->list, - g_strdup_printf("%" PRIu64, c->u.array.values[i]->u.integer)); + g_strdup_printf("%" PRIu64, c->u.array.values[i]->u.integer)); } - + c = json_o_get(node, "next_cursor"); - if (c && c->type == json_integer) + if (c && c->type == json_integer) { txl->next_cursor = c->u.integer; - else + } else { txl->next_cursor = -1; - + } + return TRUE; } @@ -291,8 +305,9 @@ static void twitter_http_get_friends_ids(struct http_request *req) ic = req->data; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } td = ic->proto_data; @@ -300,20 +315,22 @@ static void twitter_http_get_friends_ids(struct http_request *req) txl->list = td->follow_ids; // Parse the data. - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { return; - + } + twitter_xt_get_friends_id_list(parsed, txl); json_value_free(parsed); td->follow_ids = txl->list; - if (txl->next_cursor) + if (txl->next_cursor) { /* These were just numbers. Up to 4000 in a response AFAIK so if we get here we may be using a spammer account. \o/ */ twitter_get_friends_ids(ic, txl->next_cursor); - else + } else { /* Now to convert all those numbers into names.. */ twitter_get_users_lookup(ic); + } txl->list = NULL; txl_free(txl); @@ -331,10 +348,10 @@ static void twitter_get_users_lookup(struct im_connection *ic) }; GString *ids = g_string_new(""); int i; - + /* We can request up to 100 users at a time. */ - for (i = 0; i < 100 && td->follow_ids; i ++) { - g_string_append_printf(ids, ",%s", (char*) td->follow_ids->data); + for (i = 0; i < 100 && td->follow_ids; i++) { + g_string_append_printf(ids, ",%s", (char *) td->follow_ids->data); g_free(td->follow_ids->data); td->follow_ids = g_slist_remove(td->follow_ids, td->follow_ids->data); } @@ -353,8 +370,8 @@ static void twitter_get_users_lookup(struct im_connection *ic) /** * Callback for getting (twitter)friends... * - * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has - * hundreds of friends?" you wonder? You probably not, since you are reading the source of + * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has + * hundreds of friends?" you wonder? You probably not, since you are reading the source of * BitlBee... Get a life and meet new people! */ static void twitter_http_get_users_lookup(struct http_request *req) @@ -366,15 +383,17 @@ static void twitter_http_get_users_lookup(struct http_request *req) struct twitter_xml_user *user; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } txl = g_new0(struct twitter_xml_list, 1); txl->list = NULL; // Get the user list from the parsed xml feed. - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { return; + } twitter_xt_get_users(parsed, txl); json_value_free(parsed); @@ -394,14 +413,14 @@ struct twitter_xml_user *twitter_xt_get_user(const json_value *node) { struct twitter_xml_user *txu; json_value *jv; - + txu = g_new0(struct twitter_xml_user, 1); txu->name = g_strdup(json_o_str(node, "name")); txu->screen_name = g_strdup(json_o_str(node, "screen_name")); - + jv = json_o_get(node, "id"); txu->uid = jv->u.integer; - + return txu; } @@ -418,15 +437,17 @@ static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list * // Set the type of the list. txl->type = TXL_USER; - if (!node || node->type != json_array) + if (!node || node->type != json_array) { return FALSE; + } // The root <users> node should hold the list of users <user> // Walk over the nodes children. - for (i = 0; i < node->u.array.length; i ++) { + for (i = 0; i < node->u.array.length; i++) { txu = twitter_xt_get_user(node->u.array.values[i]); - if (txu) + if (txu) { txl->list = g_slist_prepend(txl->list, txu); + } } return TRUE; @@ -452,12 +473,13 @@ static struct twitter_xml_status *twitter_xt_get_status(const json_value *node) { struct twitter_xml_status *txs; const json_value *rt = NULL, *entities = NULL; - - if (node->type != json_object) + + if (node->type != json_object) { return FALSE; + } txs = g_new0(struct twitter_xml_status, 1); - JSON_O_FOREACH (node, k, v) { + JSON_O_FOREACH(node, k, v) { if (strcmp("text", k) == 0 && v->type == json_string) { txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); strip_html(txs->text); @@ -469,8 +491,9 @@ static struct twitter_xml_status *twitter_xt_get_status(const json_value *node) /* Very sensitive to changes to the formatting of this field. :-( Also assumes the timezone used is UTC since C time handling functions suck. */ - if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) + if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) { txs->created_at = mktime_utc(&parsed); + } } else if (strcmp("user", k) == 0 && v->type == json_object) { txs->user = twitter_xt_get_user(v); } else if (strcmp("id", k) == 0 && v->type == json_integer) { @@ -496,9 +519,10 @@ static struct twitter_xml_status *twitter_xt_get_status(const json_value *node) txs->text = expand_entities(txs->text, entities); } - if (txs->text && txs->user && txs->id) + if (txs->text && txs->user && txs->id) { return txs; - + } + txs_free(txs); return NULL; } @@ -510,12 +534,13 @@ static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node) { struct twitter_xml_status *txs; const json_value *entities = NULL; - - if (node->type != json_object) + + if (node->type != json_object) { return FALSE; + } txs = g_new0(struct twitter_xml_status, 1); - JSON_O_FOREACH (node, k, v) { + JSON_O_FOREACH(node, k, v) { if (strcmp("text", k) == 0 && v->type == json_string) { txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); strip_html(txs->text); @@ -525,8 +550,9 @@ static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node) /* Very sensitive to changes to the formatting of this field. :-( Also assumes the timezone used is UTC since C time handling functions suck. */ - if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) + if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) { txs->created_at = mktime_utc(&parsed); + } } else if (strcmp("sender", k) == 0 && v->type == json_object) { txs->user = twitter_xt_get_user(v); } else if (strcmp("id", k) == 0 && v->type == json_integer) { @@ -538,42 +564,48 @@ static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node) txs->text = expand_entities(txs->text, entities); } - if (txs->text && txs->user && txs->id) + if (txs->text && txs->user && txs->id) { return txs; - + } + txs_free(txs); return NULL; } -static char* expand_entities(char* text, const json_value *entities) { - JSON_O_FOREACH (entities, k, v) { +static char* expand_entities(char* text, const json_value *entities) +{ + JSON_O_FOREACH(entities, k, v) { int i; - - if (v->type != json_array) + + if (v->type != json_array) { continue; - if (strcmp(k, "urls") != 0 && strcmp(k, "media") != 0) + } + if (strcmp(k, "urls") != 0 && strcmp(k, "media") != 0) { continue; - - for (i = 0; i < v->u.array.length; i ++) { - if (v->u.array.values[i]->type != json_object) + } + + for (i = 0; i < v->u.array.length; i++) { + if (v->u.array.values[i]->type != json_object) { continue; - + } + const char *kort = json_o_str(v->u.array.values[i], "url"); const char *disp = json_o_str(v->u.array.values[i], "display_url"); char *pos, *new; - - if (!kort || !disp || !(pos = strstr(text, kort))) + + if (!kort || !disp || !(pos = strstr(text, kort))) { continue; - + } + *pos = '\0'; new = g_strdup_printf("%s%s <%s>%s", text, kort, disp, pos + strlen(kort)); - + g_free(text); text = new; } } - + return text; } @@ -591,17 +623,19 @@ static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_ // Set the type of the list. txl->type = TXL_STATUS; - - if (node->type != json_array) + + if (node->type != json_array) { return FALSE; + } // The root <statuses> node should hold the list of statuses <status> // Walk over the nodes children. - for (i = 0; i < node->u.array.length; i ++) { + for (i = 0; i < node->u.array.length; i++) { txs = twitter_xt_get_status(node->u.array.values[i]); - if (!txs) + if (!txs) { continue; - + } + txl->list = g_slist_prepend(txl->list, txs); } @@ -611,7 +645,7 @@ static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_ /* Will log messages either way. Need to keep track of IDs for stream deduping. Plus, show_ids is on by default and I don't see why anyone would disable it. */ static char *twitter_msg_add_id(struct im_connection *ic, - struct twitter_xml_status *txs, const char *prefix) + struct twitter_xml_status *txs, const char *prefix) { struct twitter_data *td = ic->proto_data; int reply_to = -1; @@ -619,11 +653,12 @@ static char *twitter_msg_add_id(struct im_connection *ic, if (txs->reply_to) { int i; - for (i = 0; i < TWITTER_LOG_LENGTH; i++) + for (i = 0; i < TWITTER_LOG_LENGTH; i++) { if (td->log[i].id == txs->reply_to) { reply_to = i; break; } + } } if (txs->user && txs->user->screen_name && @@ -635,29 +670,32 @@ static char *twitter_msg_add_id(struct im_connection *ic, tud->last_time = txs->created_at; } } - + td->log_id = (td->log_id + 1) % TWITTER_LOG_LENGTH; td->log[td->log_id].id = txs->id; td->log[td->log_id].bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name); - + /* This is all getting hairy. :-( If we RT'ed something ourselves, remember OUR id instead so undo will work. In other cases, the original tweet's id should be remembered for deduplicating. */ - if (g_strcasecmp(txs->user->screen_name, td->user) == 0) + if (g_strcasecmp(txs->user->screen_name, td->user) == 0) { td->log[td->log_id].id = txs->rt_id; - + } + if (set_getbool(&ic->acc->set, "show_ids")) { - if (reply_to != -1) + if (reply_to != -1) { return g_strdup_printf("\002[\002%02x->%02x\002]\002 %s%s", td->log_id, reply_to, prefix, txs->text); - else + } else { return g_strdup_printf("\002[\002%02x\002]\002 %s%s", td->log_id, prefix, txs->text); + } } else { - if (*prefix) + if (*prefix) { return g_strconcat(prefix, txs->text, NULL); - else + } else { return NULL; + } } } @@ -677,13 +715,15 @@ static void twitter_status_show_filter(struct im_connection *ic, struct twitter_ switch (tf->type) { case TWITTER_FILTER_TYPE_FOLLOW: - if (status->user->uid != tf->uid) + if (status->user->uid != tf->uid) { continue; + } break; case TWITTER_FILTER_TYPE_TRACK: - if (strcasestr(status->text, tf->text) == NULL) + if (strcasestr(status->text, tf->text) == NULL) { continue; + } break; default: @@ -692,7 +732,7 @@ static void twitter_status_show_filter(struct im_connection *ic, struct twitter_ for (l = tf->groupchats; l; l = g_slist_next(l)) { imcb_chat_msg(l->data, status->user->screen_name, - msg ? msg : status->text, 0, 0); + msg ? msg : status->text, 0, 0); } } @@ -712,17 +752,18 @@ static void twitter_status_show_chat(struct im_connection *ic, struct twitter_xm // Create a new groupchat if it does not exsist. gc = twitter_groupchat_init(ic); - if (!me) + if (!me) { /* MUST be done before twitter_msg_add_id() to avoid #872. */ twitter_add_buddy(ic, status->user->screen_name, status->user->name); + } msg = twitter_msg_add_id(ic, status, ""); - + // Say it! if (me) { imcb_chat_log(gc, "You: %s", msg ? msg : status->text); } else { imcb_chat_msg(gc, status->user->screen_name, - msg ? msg : status->text, 0, status->created_at); + msg ? msg : status->text, 0, status->created_at); } g_free(msg); @@ -743,13 +784,14 @@ static void twitter_status_show_msg(struct im_connection *ic, struct twitter_xml from[MAX_STRING - 1] = '\0'; } - if (td->flags & TWITTER_MODE_ONE) + if (td->flags & TWITTER_MODE_ONE) { prefix = g_strdup_printf("\002<\002%s\002>\002 ", status->user->screen_name); - else if (!me) + } else if (!me) { twitter_add_buddy(ic, status->user->screen_name, status->user->name); - else + } else { prefix = g_strdup("You: "); + } text = twitter_msg_add_id(ic, status, prefix ? prefix : ""); @@ -765,21 +807,24 @@ static void twitter_status_show(struct im_connection *ic, struct twitter_xml_sta { struct twitter_data *td = ic->proto_data; char *last_id_str; - - if (status->user == NULL || status->text == NULL) + + if (status->user == NULL || status->text == NULL) { return; - + } + /* Grrrr. Would like to do this during parsing, but can't access settings from there. */ - if (set_getbool(&ic->acc->set, "strip_newlines")) + if (set_getbool(&ic->acc->set, "strip_newlines")) { strip_newlines(status->text); - - if (status->from_filter) + } + + if (status->from_filter) { twitter_status_show_filter(ic, status); - else if (td->flags & TWITTER_MODE_CHAT) + } else if (td->flags & TWITTER_MODE_CHAT) { twitter_status_show_chat(ic, status); - else + } else { twitter_status_show_msg(ic, status); + } // Update the timeline_id to hold the highest id, so that by the next request // we won't pick up the updates already in the list. @@ -800,34 +845,37 @@ static void twitter_http_stream(struct http_request *req) int len = 0; char c, *nl; gboolean from_filter; - - if (!g_slist_find(twitter_connections, ic)) + + if (!g_slist_find(twitter_connections, ic)) { return; - + } + ic->flags |= OPT_PONGED; td = ic->proto_data; - + if ((req->flags & HTTPC_EOF) || !req->reply_body) { - if (req == td->stream) + if (req == td->stream) { td->stream = NULL; - else if (req == td->filter_stream) + } else if (req == td->filter_stream) { td->filter_stream = NULL; + } imcb_error(ic, "Stream closed (%s)", req->status_string); imc_logout(ic, TRUE); return; } - + /* MUST search for CRLF, not just LF: https://dev.twitter.com/docs/streaming-apis/processing#Parsing_responses */ - if (!(nl = strstr(req->reply_body, "\r\n"))) + if (!(nl = strstr(req->reply_body, "\r\n"))) { return; - + } + len = nl - req->reply_body; if (len > 0) { c = req->reply_body[len]; req->reply_body[len] = '\0'; - + if ((parsed = json_parse(req->reply_body, req->body_size))) { from_filter = (req == td->filter_stream); twitter_stream_handle_object(ic, parsed, from_filter); @@ -835,12 +883,13 @@ static void twitter_http_stream(struct http_request *req) json_value_free(parsed); req->reply_body[len] = c; } - + http_flush_bytes(req, len + 2); - + /* One notification might bring multiple events! */ - if (req->body_size > 0) + if (req->body_size > 0) { twitter_http_stream(req); + } } static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o); @@ -851,7 +900,7 @@ static gboolean twitter_stream_handle_object(struct im_connection *ic, json_valu struct twitter_data *td = ic->proto_data; struct twitter_xml_status *txs; json_value *c; - + if ((txs = twitter_xt_get_status(o))) { txs->from_filter = from_filter; gboolean ret = twitter_stream_handle_status(ic, txs); @@ -859,9 +908,10 @@ static gboolean twitter_stream_handle_object(struct im_connection *ic, json_valu return ret; } else if ((c = json_o_get(o, "direct_message")) && (txs = twitter_xt_get_dm(c))) { - if (g_strcasecmp(txs->user->screen_name, td->user) != 0) + if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { imcb_buddy_msg(ic, txs->user->screen_name, - txs->text, 0, txs->created_at); + txs->text, 0, txs->created_at); + } txs_free(txs); return TRUE; } else if ((c = json_o_get(o, "event")) && c->type == json_string) { @@ -885,14 +935,14 @@ static gboolean twitter_stream_handle_status(struct im_connection *ic, struct tw { struct twitter_data *td = ic->proto_data; int i; - + for (i = 0; i < TWITTER_LOG_LENGTH; i++) { if (td->log[i].id == txs->id) { /* Got a duplicate (RT, probably). Drop it. */ return TRUE; } } - + if (!(g_strcasecmp(txs->user->screen_name, td->user) == 0 || set_getbool(&ic->acc->set, "fetch_mentions") || bee_user_by_handle(ic->bee, ic, txs->user->screen_name))) { @@ -904,9 +954,9 @@ static gboolean twitter_stream_handle_status(struct im_connection *ic, struct tw @Wilmer. But meh. You want spam, you get spam. */ return TRUE; } - + twitter_status_show(ic, txs); - + return TRUE; } @@ -916,12 +966,12 @@ static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value json_value *source = json_o_get(o, "source"); json_value *target = json_o_get(o, "target"); const char *type = json_o_str(o, "event"); - + if (!type || !source || source->type != json_object - || !target || target->type != json_object) { + || !target || target->type != json_object) { return FALSE; } - + if (strcmp(type, "follow") == 0) { struct twitter_xml_user *us = twitter_xt_get_user(source); struct twitter_xml_user *ut = twitter_xt_get_user(target); @@ -931,15 +981,15 @@ static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value txu_free(us); txu_free(ut); } - + return TRUE; } gboolean twitter_open_stream(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; - char *args[2] = {"with", "followings"}; - + char *args[2] = { "with", "followings" }; + if ((td->stream = twitter_http(ic, TWITTER_USER_STREAM_URL, twitter_http_stream, ic, 0, args, 2))) { /* This flag must be enabled or we'll get no data until EOF @@ -947,14 +997,14 @@ gboolean twitter_open_stream(struct im_connection *ic) td->stream->flags |= HTTPC_STREAMING; return TRUE; } - + return FALSE; } static gboolean twitter_filter_stream(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; - char *args[4] = {"follow", NULL, "track", NULL}; + char *args[4] = { "follow", NULL, "track", NULL }; GString *followstr = g_string_new(""); GString *trackstr = g_string_new(""); gboolean ret = FALSE; @@ -966,16 +1016,18 @@ static gboolean twitter_filter_stream(struct im_connection *ic) switch (tf->type) { case TWITTER_FILTER_TYPE_FOLLOW: - if (followstr->len > 0) + if (followstr->len > 0) { g_string_append_c(followstr, ','); + } g_string_append_printf(followstr, "%" G_GUINT64_FORMAT, - tf->uid); + tf->uid); break; case TWITTER_FILTER_TYPE_TRACK: - if (trackstr->len > 0) + if (trackstr->len > 0) { g_string_append_c(trackstr, ','); + } g_string_append(trackstr, tf->text); break; @@ -988,12 +1040,13 @@ static gboolean twitter_filter_stream(struct im_connection *ic) args[1] = followstr->str; args[3] = trackstr->str; - if (td->filter_stream) + if (td->filter_stream) { http_close(td->filter_stream); + } if ((td->filter_stream = twitter_http(ic, TWITTER_FILTER_STREAM_URL, twitter_http_stream, ic, 0, - args, 4))) { + args, 4))) { /* This flag must be enabled or we'll get no data until EOF (which err, kind of, defeats the purpose of a streaming API). */ td->filter_stream->flags |= HTTPC_STREAMING; @@ -1021,30 +1074,35 @@ static void twitter_filter_users_post(struct http_request *req) int i; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } td = ic->proto_data; - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { return; + } for (l = td->filters; l; l = g_slist_next(l)) { tf = l->data; - if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) + if (tf->type == TWITTER_FILTER_TYPE_FOLLOW) { users = g_list_prepend(users, tf); + } } - if (parsed->type != json_array) + if (parsed->type != json_array) { goto finish; + } for (i = 0; i < parsed->u.array.length; i++) { id = json_o_get(parsed->u.array.values[i], "id"); name = json_o_str(parsed->u.array.values[i], "screen_name"); - if (!name || !id || id->type != json_integer) + if (!name || !id || id->type != json_integer) { continue; + } for (u = users; u; u = g_list_next(u)) { tf = u->data; @@ -1061,14 +1119,16 @@ finish: json_value_free(parsed); twitter_filter_stream(ic); - if (!users) + if (!users) { return; + } fstr = g_string_new(""); for (u = users; u; u = g_list_next(u)) { - if (fstr->len > 0) + if (fstr->len > 0) { g_string_append(fstr, ", "); + } g_string_append(fstr, tf->text); } @@ -1082,7 +1142,7 @@ finish: gboolean twitter_open_filter_stream(struct im_connection *ic) { struct twitter_data *td = ic->proto_data; - char *args[2] = {"screen_name", NULL}; + char *args[2] = { "screen_name", NULL }; GString *ustr = g_string_new(""); struct twitter_filter *tf; struct http_request *req; @@ -1091,11 +1151,13 @@ gboolean twitter_open_filter_stream(struct im_connection *ic) for (l = td->filters; l; l = g_slist_next(l)) { tf = l->data; - if (tf->type != TWITTER_FILTER_TYPE_FOLLOW || tf->uid != 0) + if (tf->type != TWITTER_FILTER_TYPE_FOLLOW || tf->uid != 0) { continue; + } - if (ustr->len > 0) + if (ustr->len > 0) { g_string_append_c(ustr, ','); + } g_string_append(ustr, tf->text); } @@ -1107,8 +1169,8 @@ gboolean twitter_open_filter_stream(struct im_connection *ic) args[1] = ustr->str; req = twitter_http(ic, TWITTER_USERS_LOOKUP_URL, - twitter_filter_users_post, - ic, 0, args, 2); + twitter_filter_users_post, + ic, 0, args, 2); g_string_free(ustr, TRUE); return req != NULL; @@ -1140,7 +1202,7 @@ gboolean twitter_get_timeline(struct im_connection *ic, gint64 next_cursor) if (include_mentions) { twitter_get_mentions(ic, next_cursor); } - + return TRUE; } @@ -1160,7 +1222,7 @@ void twitter_flush_timeline(struct im_connection *ic) GSList *l; imcb_connected(ic); - + if (!(td->flags & TWITTER_GOT_TIMELINE)) { return; } @@ -1188,8 +1250,9 @@ void twitter_flush_timeline(struct im_connection *ic) // See if the user wants to see the messages in a groupchat window or as private messages. while (output) { struct twitter_xml_status *txs = output->data; - if (txs->id != last_id) + if (txs->id != last_id) { twitter_status_show(ic, txs); + } last_id = txs->id; output = g_slist_remove(output, txs); } @@ -1226,10 +1289,11 @@ static void twitter_get_home_timeline(struct im_connection *ic, gint64 next_curs } if (twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, - td->timeline_id ? 6 : 4) == NULL) { - if (++td->http_fails >= 5) + td->timeline_id ? 6 : 4) == NULL) { + if (++td->http_fails >= 5) { imcb_error(ic, "Could not retrieve %s: %s", TWITTER_HOME_TIMELINE_URL, "connection failed"); + } td->flags |= TWITTER_GOT_TIMELINE; twitter_flush_timeline(ic); } @@ -1266,9 +1330,10 @@ static void twitter_get_mentions(struct im_connection *ic, gint64 next_cursor) if (twitter_http(ic, TWITTER_MENTIONS_URL, twitter_http_get_mentions, ic, 0, args, 6) == NULL) { - if (++td->http_fails >= 5) + if (++td->http_fails >= 5) { imcb_error(ic, "Could not retrieve %s: %s", TWITTER_MENTIONS_URL, "connection failed"); + } td->flags |= TWITTER_GOT_MENTIONS; twitter_flush_timeline(ic); } @@ -1288,8 +1353,9 @@ static void twitter_http_get_home_timeline(struct http_request *req) struct twitter_xml_list *txl; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } td = ic->proto_data; @@ -1297,16 +1363,18 @@ static void twitter_http_get_home_timeline(struct http_request *req) txl->list = NULL; // The root <statuses> node should hold the list of statuses <status> - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { goto end; + } twitter_xt_get_status_list(ic, parsed, txl); json_value_free(parsed); td->home_timeline_obj = txl; - end: - if (!g_slist_find(twitter_connections, ic)) +end: + if (!g_slist_find(twitter_connections, ic)) { return; + } td->flags |= TWITTER_GOT_TIMELINE; @@ -1324,8 +1392,9 @@ static void twitter_http_get_mentions(struct http_request *req) struct twitter_xml_list *txl; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } td = ic->proto_data; @@ -1333,16 +1402,18 @@ static void twitter_http_get_mentions(struct http_request *req) txl->list = NULL; // The root <statuses> node should hold the list of statuses <status> - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { goto end; + } twitter_xt_get_status_list(ic, parsed, txl); json_value_free(parsed); td->mentions_obj = txl; - end: - if (!g_slist_find(twitter_connections, ic)) +end: + if (!g_slist_find(twitter_connections, ic)) { return; + } td->flags |= TWITTER_GOT_MENTIONS; @@ -1360,23 +1431,26 @@ static void twitter_http_post(struct http_request *req) json_value *parsed, *id; // Check if the connection is still active. - if (!g_slist_find(twitter_connections, ic)) + if (!g_slist_find(twitter_connections, ic)) { return; + } td = ic->proto_data; td->last_status_id = 0; - if (!(parsed = twitter_parse_response(ic, req))) + if (!(parsed = twitter_parse_response(ic, req))) { return; - + } + if ((id = json_o_get(parsed, "id")) && id->type == json_integer) { td->last_status_id = id->u.integer; } - + json_value_free(parsed); - - if (req->flags & TWITTER_HTTP_USER_ACK) + + if (req->flags & TWITTER_HTTP_USER_ACK) { twitter_log(ic, "Command processed successfully"); + } } /** @@ -1389,8 +1463,9 @@ void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_t "in_reply_to_status_id", g_strdup_printf("%" G_GUINT64_FORMAT, in_reply_to) }; + twitter_http(ic, TWITTER_STATUS_UPDATE_URL, twitter_http_post, ic, 1, - args, in_reply_to ? 4 : 2); + args, in_reply_to ? 4 : 2); g_free(args[3]); } @@ -1401,6 +1476,7 @@ void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_t void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg) { char *args[4]; + args[0] = "screen_name"; args[1] = who; args[2] = "text"; @@ -1412,15 +1488,17 @@ void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg) void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create) { char *args[2]; + args[0] = "screen_name"; args[1] = who; twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, - twitter_http_post, ic, 1, args, 2); + twitter_http_post, ic, 1, args, 2); } void twitter_status_destroy(struct im_connection *ic, guint64 id) { char *url; + url = g_strdup_printf("%s%" G_GUINT64_FORMAT "%s", TWITTER_STATUS_DESTROY_URL, id, ".json"); twitter_http_f(ic, url, twitter_http_post, ic, 1, NULL, 0, @@ -1431,6 +1509,7 @@ void twitter_status_destroy(struct im_connection *ic, guint64 id) void twitter_status_retweet(struct im_connection *ic, guint64 id) { char *url; + url = g_strdup_printf("%s%" G_GUINT64_FORMAT "%s", TWITTER_STATUS_RETWEET_URL, id, ".json"); twitter_http_f(ic, url, twitter_http_post, ic, 1, NULL, 0, @@ -1447,6 +1526,7 @@ void twitter_report_spam(struct im_connection *ic, char *screen_name) "screen_name", NULL, }; + args[1] = screen_name; twitter_http_f(ic, TWITTER_REPORT_SPAM_URL, twitter_http_post, ic, 1, args, 2, TWITTER_HTTP_USER_ACK); @@ -1461,6 +1541,7 @@ void twitter_favourite_tweet(struct im_connection *ic, guint64 id) "id", NULL, }; + args[1] = g_strdup_printf("%" G_GUINT64_FORMAT, id); twitter_http_f(ic, TWITTER_FAVORITE_CREATE_URL, twitter_http_post, ic, 1, args, 2, TWITTER_HTTP_USER_ACK); diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index 9956514d..9188c809 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -2,13 +2,13 @@ * libyahoo2: libyahoo2.c * * Some code copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net> - * YMSG16 code copyright (C) 2009, - * Siddhesh Poyarekar <siddhesh dot poyarekar at gmail dot com> + * YMSG16 code copyright (C) 2009, + * Siddhesh Poyarekar <siddhesh dot poyarekar at gmail dot com> * * Yahoo Search copyright (C) 2003, Konstantin Klyagin <konst AT konst.org.ua> * * Much of this code was taken and adapted from the yahoo module for - * gaim released under the GNU GPL. This code is also released under the + * gaim released under the GNU GPL. This code is also released under the * GNU GPL. * * This code is derivitive of Gaim <http://gaim.sourceforge.net> @@ -29,7 +29,7 @@ * <hiro-y@kcn.ne.jp> * * YMSG16 authentication code based mostly on write-up at: - * http://www.carbonize.co.uk/ymsg16.html + * http://www.carbonize.co.uk/ymsg16.html * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,10 +59,10 @@ # define strchr index # define strrchr rindex # endif -char *strchr (), *strrchr (); +char *strchr(), *strrchr(); # if !HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# define memmove(d, s, n) bcopy ((s), (d), (n)) +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memmove(d, s, n) bcopy((s), (d), (n)) # endif #endif @@ -99,9 +99,9 @@ void yahoo_register_callbacks(struct yahoo_callbacks *tyc) yc = tyc; } -#define YAHOO_CALLBACK(x) yc->x +#define YAHOO_CALLBACK(x) yc->x #else -#define YAHOO_CALLBACK(x) x +#define YAHOO_CALLBACK(x) x #endif static int yahoo_send_data(void *fd, void *data, int len); @@ -112,10 +112,11 @@ int yahoo_log_message(char *fmt, ...) { char out[1024]; va_list ap; + va_start(ap, fmt); vsnprintf(out, sizeof(out), fmt, ap); va_end(ap); - return YAHOO_CALLBACK(ext_yahoo_log) ("%s", out); + return YAHOO_CALLBACK (ext_yahoo_log) ("%s", out); } static enum yahoo_log_level log_level = YAHOO_LOG_NONE; @@ -128,16 +129,17 @@ enum yahoo_log_level yahoo_get_log_level() int yahoo_set_log_level(enum yahoo_log_level level) { enum yahoo_log_level l = log_level; + log_level = level; return l; } /* default values for servers */ -static char *default_pager_hosts[] = { "scs.msg.yahoo.com", - "scsa.msg.yahoo.com", - "scsb.msg.yahoo.com", - "scsc.msg.yahoo.com", - NULL}; +static char *default_pager_hosts[] = { "scs.msg.yahoo.com", + "scsa.msg.yahoo.com", + "scsb.msg.yahoo.com", + "scsc.msg.yahoo.com", + NULL }; static int pager_port = 5050; static int fallback_ports[] = { 23, 25, 80, 20, 119, 8001, 8002, 5050, 0 }; @@ -221,21 +223,21 @@ struct yahoo_server_settings { static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over); static void yahoo_process_filetransfer(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); + struct yahoo_packet *pkt); static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); + struct yahoo_packet *pkt); static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); + struct yahoo_packet *pkt); static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn); static void *_yahoo_default_server_settings() { struct yahoo_server_settings *yss = - y_new0(struct yahoo_server_settings, 1); + y_new0(struct yahoo_server_settings, 1); /* Give preference to the default host list - * Make sure that only one of the two is set at any time + * Make sure that only one of the two is set at any time */ yss->pager_host = NULL; yss->pager_host_list = default_pager_hosts; @@ -262,8 +264,9 @@ static void *_yahoo_assign_server_settings(va_list ap) while (1) { key = va_arg(ap, char *); - if (key == NULL) + if (key == NULL) { break; + } if (!strcmp(key, "pager_host")) { svalue = va_arg(ap, char *); @@ -305,8 +308,8 @@ static void *_yahoo_assign_server_settings(va_list ap) yss->conn_type = nvalue; } else { WARNING(("Unknown key passed to yahoo_init, " - "perhaps you didn't terminate the list " - "with NULL")); + "perhaps you didn't terminate the list " + "with NULL")); } } @@ -315,8 +318,9 @@ static void *_yahoo_assign_server_settings(va_list ap) static void yahoo_free_server_settings(struct yahoo_server_settings *yss) { - if (!yss) + if (!yss) { return; + } free(yss->pager_host); free(yss->filetransfer_host); @@ -339,10 +343,12 @@ static void add_to_list(struct yahoo_data *yd) static struct yahoo_data *find_conn_by_id(int id) { YList *l; + for (l = conns; l; l = y_list_next(l)) { struct yahoo_data *yd = l->data; - if (yd->client_id == id) + if (yd->client_id == id) { return yd; + } } return NULL; } @@ -356,44 +362,48 @@ static void del_from_list(struct yahoo_data *yd) /* static struct yahoo_input_data * find_input_by_id(int id) { - YList *l; - for(l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if(yid->yd->client_id == id) - return yid; - } - return NULL; + YList *l; + for(l = inputs; l; l = y_list_next(l)) { + struct yahoo_input_data *yid = l->data; + if(yid->yd->client_id == id) + return yid; + } + return NULL; } */ #if 0 static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, - const char *who) + const char *who) { YList *l; + LOG(("find_input_by_id_and_webcam_user")); for (l = inputs; l; l = y_list_next(l)) { struct yahoo_input_data *yid = l->data; if (yid->type == YAHOO_CONNECTION_WEBCAM - && yid->yd->client_id == id && yid->wcm && ((who - && yid->wcm->user - && !strcmp(who, yid->wcm->user)) - || !(yid->wcm->user && !who))) + && yid->yd->client_id == id && yid->wcm && ((who + && yid->wcm->user + && !strcmp(who, yid->wcm->user)) + || !(yid->wcm->user && !who))) { return yid; + } } return NULL; } #endif static struct yahoo_input_data *find_input_by_id_and_type(int id, - enum yahoo_connection_type type) + enum yahoo_connection_type type) { YList *l; + LOG(("find_input_by_id_and_type")); for (l = inputs; l; l = y_list_next(l)) { struct yahoo_input_data *yid = l->data; - if (yid->type == type && yid->yd->client_id == id) + if (yid->type == type && yid->yd->client_id == id) { return yid; + } } return NULL; } @@ -401,11 +411,13 @@ static struct yahoo_input_data *find_input_by_id_and_type(int id, static struct yahoo_input_data *find_input_by_id_and_fd(int id, void *fd) { YList *l; + LOG(("find_input_by_id_and_fd")); for (l = inputs; l; l = y_list_next(l)) { struct yahoo_input_data *yid = l->data; - if (yid->fd == fd && yid->yd->client_id == id) + if (yid->fd == fd && yid->yd->client_id == id) { return yid; + } } return NULL; } @@ -414,11 +426,13 @@ static int count_inputs_with_id(int id) { int c = 0; YList *l; + LOG(("counting %d", id)); for (l = inputs; l; l = y_list_next(l)) { struct yahoo_input_data *yid = l->data; - if (yid->yd->client_id == id) + if (yid->yd->client_id == id) { c++; + } } LOG(("%d", c)); return c; @@ -431,8 +445,9 @@ static void yahoo_free_buddies(YList *list) for (l = list; l; l = l->next) { struct yahoo_buddy *bud = l->data; - if (!bud) + if (!bud) { continue; + } FREE(bud->group); FREE(bud->id); @@ -502,7 +517,7 @@ static void yahoo_free_data(struct yahoo_data *yd) #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4) static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, - enum ypacket_status status, int id) + enum ypacket_status status, int id) { struct yahoo_packet *pkt = y_new0(struct yahoo_packet, 1); @@ -514,9 +529,10 @@ static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, } static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, - const char *value) + const char *value) { struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1); + pair->key = key; pair->value = strdup(value); pkt->hash = y_list_append(pkt->hash, pair); @@ -544,23 +560,23 @@ static int yahoo_packet_length(struct yahoo_packet *pkt) } #define yahoo_put16(buf, data) ( \ - (*(buf) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+1) = (unsigned char)(data)&0xff), \ - 2) -#define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff)) + (*(buf) = (unsigned char) ((data) >> 8) & 0xff), \ + (*((buf) + 1) = (unsigned char) (data) & 0xff), \ + 2) +#define yahoo_get16(buf) ((((*(buf)) & 0xff) << 8) + ((*((buf) + 1)) & 0xff)) #define yahoo_put32(buf, data) ( \ - (*((buf)) = (unsigned char)((data)>>24)&0xff), \ - (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \ - (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+3) = (unsigned char)(data)&0xff), \ - 4) -#define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \ - (((*((buf)+1))&0xff)<<16) + \ - (((*((buf)+2))&0xff)<< 8) + \ - (((*((buf)+3))&0xff))) + (*((buf)) = (unsigned char) ((data) >> 24) & 0xff), \ + (*((buf) + 1) = (unsigned char) ((data) >> 16) & 0xff), \ + (*((buf) + 2) = (unsigned char) ((data) >> 8) & 0xff), \ + (*((buf) + 3) = (unsigned char) (data) & 0xff), \ + 4) +#define yahoo_get32(buf) ((((*(buf)) & 0xff) << 24) + \ + (((*((buf) + 1)) & 0xff) << 16) + \ + (((*((buf) + 2)) & 0xff) << 8) + \ + (((*((buf) + 3)) & 0xff))) static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, - int len) + int len) { int pos = 0; @@ -574,47 +590,52 @@ static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, key = malloc(len + 1); x = 0; while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) { break; + } key[x++] = data[pos++]; } key[x] = 0; pos += 2; pair->key = strtol(key, NULL, 10); free(key); - + /* Libyahoo2 developer(s) don't seem to have the time to fix this problem, so for now try to work around it: - + Sometimes we receive an invalid packet with not any more data at this point. I don't know how to handle this in a clean way, but let's hope this is clean enough: */ - + if (pos + 1 < len) { - accept = x; + accept = x; /* if x is 0 there was no key, so don't accept it */ - if (accept) + if (accept) { value = malloc(len - pos + 1); + } x = 0; while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) + if (data[pos] == 0xc0 && data[pos + 1] == 0x80) { break; - if (accept) + } + if (accept) { value[x++] = data[pos++]; + } } - if (accept) + if (accept) { value[x] = 0; + } pos += 2; } else { accept = 0; } - + if (accept) { pair->value = strdup(value); FREE(value); pkt->hash = y_list_append(pkt->hash, pair); DEBUG_MSG(("Key: %d \tValue: %s", pair->key, - pair->value)); + pair->value)); } else { FREE(pair); } @@ -630,13 +651,13 @@ static void yahoo_packet_write(struct yahoo_packet *pkt, unsigned char *data) struct yahoo_pair *pair = l->data; unsigned char buf[100]; - snprintf((char *)buf, sizeof(buf), "%d", pair->key); - strcpy((char *)data + pos, (char *)buf); - pos += strlen((char *)buf); + snprintf((char *) buf, sizeof(buf), "%d", pair->key); + strcpy((char *) data + pos, (char *) buf); + pos += strlen((char *) buf); data[pos++] = 0xc0; data[pos++] = 0x80; - strcpy((char *)data + pos, pair->value); + strcpy((char *) data + pos, pair->value); pos += strlen(pair->value); data[pos++] = 0xc0; data[pos++] = 0x80; @@ -659,24 +680,29 @@ static void yahoo_packet_dump(unsigned char *data, int len) if (yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { int i; for (i = 0; i < len; i++) { - if ((i % 8 == 0) && i) - YAHOO_CALLBACK(ext_yahoo_log) (" "); - if ((i % 16 == 0) && i) - YAHOO_CALLBACK(ext_yahoo_log) ("\n"); - YAHOO_CALLBACK(ext_yahoo_log) ("%02x ", data[i]); + if ((i % 8 == 0) && i) { + YAHOO_CALLBACK (ext_yahoo_log) (" "); + } + if ((i % 16 == 0) && i) { + YAHOO_CALLBACK (ext_yahoo_log) ("\n"); + } + YAHOO_CALLBACK (ext_yahoo_log) ("%02x ", data[i]); } - YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + YAHOO_CALLBACK (ext_yahoo_log) ("\n"); for (i = 0; i < len; i++) { - if ((i % 8 == 0) && i) - YAHOO_CALLBACK(ext_yahoo_log) (" "); - if ((i % 16 == 0) && i) - YAHOO_CALLBACK(ext_yahoo_log) ("\n"); - if (isprint(data[i])) - YAHOO_CALLBACK(ext_yahoo_log) (" %c ", data[i]); - else - YAHOO_CALLBACK(ext_yahoo_log) (" . "); + if ((i % 8 == 0) && i) { + YAHOO_CALLBACK (ext_yahoo_log) (" "); + } + if ((i % 16 == 0) && i) { + YAHOO_CALLBACK (ext_yahoo_log) ("\n"); + } + if (isprint(data[i])) { + YAHOO_CALLBACK (ext_yahoo_log) (" %c ", data[i]); + } else { + YAHOO_CALLBACK (ext_yahoo_log) (" . "); + } } - YAHOO_CALLBACK(ext_yahoo_log) ("\n"); + YAHOO_CALLBACK (ext_yahoo_log) ("\n"); } } @@ -702,51 +728,55 @@ static void to_y64(unsigned char *out, const unsigned char *in, int inlen) } static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, - int length) + int length) { struct data_queue *tx = y_new0(struct data_queue, 1); + tx->queue = y_new0(unsigned char, length); tx->len = length; memcpy(tx->queue, data, length); yid->txqueues = y_list_append(yid->txqueues, tx); - if (!yid->write_tag) + if (!yid->write_tag) { yid->write_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd-> - client_id, yid->fd, YAHOO_INPUT_WRITE, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd-> + client_id, yid->fd, YAHOO_INPUT_WRITE, yid); + } } static void yahoo_send_packet(struct yahoo_input_data *yid, - struct yahoo_packet *pkt, int extra_pad) + struct yahoo_packet *pkt, int extra_pad) { int pktlen = yahoo_packet_length(pkt); int len = YAHOO_PACKET_HDRLEN + pktlen; unsigned char *data; int pos = 0; - if (yid->fd < 0) + if (yid->fd < 0) { return; + } data = y_new0(unsigned char, len + 1); memcpy(data + pos, "YMSG", 4); pos += 4; - pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); /* version [latest 12 0x000c] */ - pos += yahoo_put16(data + pos, 0x0000); /* HIWORD pkt length??? */ - pos += yahoo_put16(data + pos, pktlen + extra_pad); /* LOWORD pkt length? */ - pos += yahoo_put16(data + pos, pkt->service); /* service */ - pos += yahoo_put32(data + pos, pkt->status); /* status [4bytes] */ - pos += yahoo_put32(data + pos, pkt->id); /* session [4bytes] */ + pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); /* version [latest 12 0x000c] */ + pos += yahoo_put16(data + pos, 0x0000); /* HIWORD pkt length??? */ + pos += yahoo_put16(data + pos, pktlen + extra_pad); /* LOWORD pkt length? */ + pos += yahoo_put16(data + pos, pkt->service); /* service */ + pos += yahoo_put32(data + pos, pkt->status); /* status [4bytes] */ + pos += yahoo_put32(data + pos, pkt->id); /* session [4bytes] */ yahoo_packet_write(pkt, data + pos); yahoo_packet_dump(data, len); - if (yid->type == YAHOO_CONNECTION_FT) + if (yid->type == YAHOO_CONNECTION_FT) { yahoo_send_data(yid->fd, data, len); - else + } else { yahoo_add_to_send_queue(yid, data, len); + } FREE(data); } @@ -769,13 +799,14 @@ static int yahoo_send_data(void *fd, void *data, int len) int ret; int e; - if (fd == NULL) + if (fd == NULL) { return -1; + } yahoo_packet_dump(data, len); do { - ret = YAHOO_CALLBACK(ext_yahoo_write) (fd, data, len); + ret = YAHOO_CALLBACK (ext_yahoo_write) (fd, data, len); } while (ret == -1 && errno == EINTR); e = errno; @@ -792,14 +823,17 @@ static int yahoo_send_data(void *fd, void *data, int len) void yahoo_close(int id) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return; + } del_from_list(yd); yahoo_free_data(yd); - if (id == last_id) + if (id == last_id) { last_id--; + } } static void yahoo_input_close(struct yahoo_input_data *yid) @@ -807,14 +841,15 @@ static void yahoo_input_close(struct yahoo_input_data *yid) inputs = y_list_remove(inputs, yid); LOG(("yahoo_input_close(read)")); - YAHOO_CALLBACK(ext_yahoo_remove_handler) (yid->yd->client_id, - yid->read_tag); + YAHOO_CALLBACK (ext_yahoo_remove_handler) (yid->yd->client_id, + yid->read_tag); LOG(("yahoo_input_close(write)")); - YAHOO_CALLBACK(ext_yahoo_remove_handler) (yid->yd->client_id, - yid->write_tag); + YAHOO_CALLBACK (ext_yahoo_remove_handler) (yid->yd->client_id, + yid->write_tag); yid->read_tag = yid->write_tag = 0; - if (yid->fd) - YAHOO_CALLBACK(ext_yahoo_close) (yid->fd); + if (yid->fd) { + YAHOO_CALLBACK (ext_yahoo_close) (yid->fd); + } yid->fd = 0; FREE(yid->rxqueue); if (count_inputs_with_id(yid->yd->client_id) == 0) { @@ -822,8 +857,9 @@ static void yahoo_input_close(struct yahoo_input_data *yid) yahoo_close(yid->yd->client_id); } yahoo_free_webcam(yid->wcm); - if (yid->wcd) + if (yid->wcd) { FREE(yid->wcd); + } if (yid->ys) { FREE(yid->ys->lsearch_text); FREE(yid->ys); @@ -845,14 +881,16 @@ static char *getcookie(char *rawcookie) char *tmpcookie; char *cookieend; - if (strlen(rawcookie) < 2) + if (strlen(rawcookie) < 2) { return NULL; + } tmpcookie = strdup(rawcookie + 2); cookieend = strchr(tmpcookie, ';'); - if (cookieend) + if (cookieend) { *cookieend = '\0'; + } cookie = strdup(tmpcookie); FREE(tmpcookie); @@ -871,8 +909,9 @@ static char *getlcookie(char *cookie) if (tmpend) { tmp = strdup(tmpend + 2); tmpend = strchr(tmp, '&'); - if (tmpend) + if (tmpend) { *tmpend = '\0'; + } login_cookie = strdup(tmp); FREE(tmp); } @@ -881,7 +920,7 @@ static char *getlcookie(char *cookie) } static void yahoo_process_notify(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *msg = NULL; @@ -891,52 +930,61 @@ static void yahoo_process_notify(struct yahoo_input_data *yid, int accept = 0; char *ind = NULL; YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 4) + if (pair->key == 4) { from = pair->value; - if (pair->key == 5) + } + if (pair->key == 5) { to = pair->value; - if (pair->key == 49) + } + if (pair->key == 49) { msg = pair->value; - if (pair->key == 13) + } + if (pair->key == 13) { stat = atoi(pair->value); - if (pair->key == 14) + } + if (pair->key == 14) { ind = pair->value; - if (pair->key == 16) { /* status == -1 */ + } + if (pair->key == 16) { /* status == -1 */ NOTICE((pair->value)); return; } } - if (!msg) + if (!msg) { return; + } - if (!strncasecmp(msg, "TYPING", strlen("TYPING"))) - YAHOO_CALLBACK(ext_yahoo_typing_notify) (yd->client_id, to, - from, stat); - else if (!strncasecmp(msg, "GAME", strlen("GAME"))) - YAHOO_CALLBACK(ext_yahoo_game_notify) (yd->client_id, to, from, - stat, ind); - else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { + if (!strncasecmp(msg, "TYPING", strlen("TYPING"))) { + YAHOO_CALLBACK (ext_yahoo_typing_notify) (yd->client_id, to, + from, stat); + } else if (!strncasecmp(msg, "GAME", strlen("GAME"))) { + YAHOO_CALLBACK (ext_yahoo_game_notify) (yd->client_id, to, from, + stat, ind); + } else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { if (!strcmp(ind, " ")) { - YAHOO_CALLBACK(ext_yahoo_webcam_invite) (yd->client_id, - to, from); + YAHOO_CALLBACK (ext_yahoo_webcam_invite) (yd->client_id, + to, from); } else { accept = atoi(ind); /* accept the invitation (-1 = deny 1 = accept) */ - if (accept < 0) + if (accept < 0) { accept = 0; - YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply) (yd-> - client_id, to, from, accept); + } + YAHOO_CALLBACK (ext_yahoo_webcam_invite_reply) (yd-> + client_id, to, from, accept); } - } else + } else { LOG(("Got unknown notification: %s", msg)); + } } static void yahoo_process_conference(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *msg = NULL; @@ -950,97 +998,120 @@ static void yahoo_process_conference(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 50) + if (pair->key == 50) { host = pair->value; + } - if (pair->key == 52) { /* invite */ + if (pair->key == 52) { /* invite */ members = y_list_append(members, strdup(pair->value)); } - if (pair->key == 53) /* logon */ + if (pair->key == 53) { /* logon */ who = pair->value; - if (pair->key == 54) /* decline */ + } + if (pair->key == 54) { /* decline */ who = pair->value; - if (pair->key == 55) /* unavailable (status == 2) */ + } + if (pair->key == 55) { /* unavailable (status == 2) */ who = pair->value; - if (pair->key == 56) /* logoff */ + } + if (pair->key == 56) { /* logoff */ who = pair->value; + } - if (pair->key == 57) + if (pair->key == 57) { room = pair->value; + } - if (pair->key == 58) /* join message */ + if (pair->key == 58) { /* join message */ msg = pair->value; - if (pair->key == 14) /* decline/conf message */ + } + if (pair->key == 14) { /* decline/conf message */ msg = pair->value; + } - if (pair->key == 13) + if (pair->key == 13) { ; - if (pair->key == 16) /* error */ + } + if (pair->key == 16) { /* error */ msg = pair->value; + } - if (pair->key == 1) /* my id */ + if (pair->key == 1) { /* my id */ id = pair->value; - if (pair->key == 3) /* message sender */ + } + if (pair->key == 3) { /* message sender */ who = pair->value; + } - if (pair->key == 97) + if (pair->key == 97) { utf8 = atoi(pair->value); + } } - if (!room) + if (!room) { return; + } if (host) { for (l = members; l; l = l->next) { char *w = l->data; - if (!strcmp(w, host)) + if (!strcmp(w, host)) { break; + } } - if (!l) + if (!l) { members = y_list_append(members, strdup(host)); + } } /* invite, decline, join, left, message -> status == 1 */ switch (pkt->service) { case YAHOO_SERVICE_CONFINVITE: - if (pkt->status == 2) ; - else if (members) - YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd-> - client_id, id, host, room, msg, members); - else if (msg) - YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, msg, 0, - E_CONFNOTAVAIL); + if (pkt->status == 2) { + ; + } else if (members) { + YAHOO_CALLBACK (ext_yahoo_got_conf_invite) (yd-> + client_id, id, host, room, msg, members); + } else if (msg) { + YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, msg, 0, + E_CONFNOTAVAIL); + } break; case YAHOO_SERVICE_CONFADDINVITE: - if (pkt->status == 1) - YAHOO_CALLBACK(ext_yahoo_got_conf_invite) (yd-> - client_id, id, host, room, msg, members); + if (pkt->status == 1) { + YAHOO_CALLBACK (ext_yahoo_got_conf_invite) (yd-> + client_id, id, host, room, msg, members); + } break; case YAHOO_SERVICE_CONFDECLINE: - if (who) - YAHOO_CALLBACK(ext_yahoo_conf_userdecline) (yd-> - client_id, id, who, room, msg); + if (who) { + YAHOO_CALLBACK (ext_yahoo_conf_userdecline) (yd-> + client_id, id, who, room, msg); + } break; case YAHOO_SERVICE_CONFLOGON: - if (who) - YAHOO_CALLBACK(ext_yahoo_conf_userjoin) (yd->client_id, - id, who, room); + if (who) { + YAHOO_CALLBACK (ext_yahoo_conf_userjoin) (yd->client_id, + id, who, room); + } break; case YAHOO_SERVICE_CONFLOGOFF: - if (who) - YAHOO_CALLBACK(ext_yahoo_conf_userleave) (yd->client_id, - id, who, room); + if (who) { + YAHOO_CALLBACK (ext_yahoo_conf_userleave) (yd->client_id, + id, who, room); + } break; case YAHOO_SERVICE_CONFMSG: - if (who) - YAHOO_CALLBACK(ext_yahoo_conf_message) (yd->client_id, - id, who, room, msg, utf8); + if (who) { + YAHOO_CALLBACK (ext_yahoo_conf_message) (yd->client_id, + id, who, room, msg, utf8); + } break; } } static void yahoo_process_chat(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { char *msg = NULL; char *id = NULL; @@ -1086,7 +1157,7 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, if (pkt->service == YAHOO_SERVICE_CHATJOIN) { currentmember = - y_new0(struct yahoo_chat_member, 1); + y_new0(struct yahoo_chat_member, 1); currentmember->id = strdup(pair->value); members = y_list_append(members, currentmember); } @@ -1094,26 +1165,30 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, if (pair->key == 110) { /* age */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) + if (pkt->service == YAHOO_SERVICE_CHATJOIN) { currentmember->age = atoi(pair->value); + } } if (pair->key == 113) { /* attribs */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) + if (pkt->service == YAHOO_SERVICE_CHATJOIN) { currentmember->attribs = atoi(pair->value); + } } if (pair->key == 141) { /* alias */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) + if (pkt->service == YAHOO_SERVICE_CHATJOIN) { currentmember->alias = strdup(pair->value); + } } if (pair->key == 142) { /* location */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) + if (pkt->service == YAHOO_SERVICE_CHATJOIN) { currentmember->location = strdup(pair->value); + } } if (pair->key == 130) { @@ -1138,14 +1213,14 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, } if (!room) { - if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */ - YAHOO_CALLBACK(ext_yahoo_chat_yahoologout) (yid->yd-> - client_id, id); + if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */ + YAHOO_CALLBACK (ext_yahoo_chat_yahoologout) (yid->yd-> + client_id, id); return; } if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr) { - YAHOO_CALLBACK(ext_yahoo_chat_yahooerror) (yid->yd-> - client_id, id); + YAHOO_CALLBACK (ext_yahoo_chat_yahooerror) (yid->yd-> + client_id, id); return; } @@ -1159,8 +1234,8 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, WARNING(("Count of members doesn't match No. of members we got")); } if (firstjoin && members) { - YAHOO_CALLBACK(ext_yahoo_chat_join) (yid->yd->client_id, - id, room, topic, members, yid->fd); + YAHOO_CALLBACK (ext_yahoo_chat_join) (yid->yd->client_id, + id, room, topic, members, yid->fd); } else if (who) { if (y_list_length(members) != 1) { WARNING(("Got more than 1 member on a normal join")); @@ -1169,8 +1244,8 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, while (members) { YList *n = members->next; currentmember = members->data; - YAHOO_CALLBACK(ext_yahoo_chat_userjoin) (yid-> - yd->client_id, id, room, currentmember); + YAHOO_CALLBACK (ext_yahoo_chat_userjoin) (yid-> + yd->client_id, id, room, currentmember); y_list_free_1(members); members = n; } @@ -1178,21 +1253,21 @@ static void yahoo_process_chat(struct yahoo_input_data *yid, break; case YAHOO_SERVICE_CHATEXIT: if (who) { - YAHOO_CALLBACK(ext_yahoo_chat_userleave) (yid->yd-> - client_id, id, room, who); + YAHOO_CALLBACK (ext_yahoo_chat_userleave) (yid->yd-> + client_id, id, room, who); } break; case YAHOO_SERVICE_COMMENT: if (who) { - YAHOO_CALLBACK(ext_yahoo_chat_message) (yid->yd-> - client_id, id, who, room, msg, msgtype, utf8); + YAHOO_CALLBACK (ext_yahoo_chat_message) (yid->yd-> + client_id, id, who, room, msg, msgtype, utf8); } break; } } static void yahoo_process_message(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; @@ -1212,30 +1287,35 @@ static void yahoo_process_message(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; if (pair->key == 1 || pair->key == 4) { - if (!message->from) + if (!message->from) { message->from = pair->value; - } else if (pair->key == 5) + } + } else if (pair->key == 5) { message->to = pair->value; - else if (pair->key == 15) + } else if (pair->key == 15) { message->tm = strtol(pair->value, NULL, 10); - else if (pair->key == 97) + } else if (pair->key == 97) { message->utf8 = atoi(pair->value); + } /* This comes when the official client sends us a message */ - else if (pair->key == 429) + else if (pair->key == 429) { message->gunk = pair->value; + } /* user message *//* sys message */ - else if (pair->key == 14 || pair->key == 16) + else if (pair->key == 14 || pair->key == 16) { message->msg = pair->value; - else if (pair->key == 31) { + } else if (pair->key == 31) { if (message->i_31) { messages = y_list_append(messages, message); message = y_new0(struct m, 1); } message->i_31 = atoi(pair->value); - } else if (pair->key == 32) + } else if (pair->key == 32) { message->i_32 = atoi(pair->value); - else - LOG(("yahoo_process_message: status: %d, key: %d, value: %s", pkt->status, pair->key, pair->value)); + } else { + LOG(("yahoo_process_message: status: %d, key: %d, value: %s", pkt->status, pair->key, + pair->value)); + } } messages = y_list_append(messages, message); @@ -1243,15 +1323,15 @@ static void yahoo_process_message(struct yahoo_input_data *yid, for (l = messages; l; l = l->next) { message = l->data; if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) { - YAHOO_CALLBACK(ext_yahoo_system_message) (yd->client_id, - message->to, message->from, message->msg); + YAHOO_CALLBACK (ext_yahoo_system_message) (yd->client_id, + message->to, message->from, message->msg); } else if (pkt->status <= 2 || pkt->status == 5) { /* Confirm message receipt if we got the gunk */ - if(message->gunk) { + if (message->gunk) { struct yahoo_packet *outpkt; - + outpkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_CONFIRM, - YPACKET_STATUS_DEFAULT, 0); + YPACKET_STATUS_DEFAULT, 0); yahoo_packet_hash(outpkt, 1, yd->user); yahoo_packet_hash(outpkt, 5, message->from); yahoo_packet_hash(outpkt, 302, "430"); @@ -1259,20 +1339,21 @@ static void yahoo_process_message(struct yahoo_input_data *yid, yahoo_packet_hash(outpkt, 303, "430"); yahoo_packet_hash(outpkt, 450, "0"); yahoo_send_packet(yid, outpkt, 0); - + yahoo_packet_free(outpkt); } - if (!strcmp(message->msg, "<ding>")) - YAHOO_CALLBACK(ext_yahoo_got_buzz) (yd->client_id, - message->to, message->from, message->tm); - else - YAHOO_CALLBACK(ext_yahoo_got_im) (yd->client_id, - message->to, message->from, message->msg, - message->tm, pkt->status, message->utf8); + if (!strcmp(message->msg, "<ding>")) { + YAHOO_CALLBACK (ext_yahoo_got_buzz) (yd->client_id, + message->to, message->from, message->tm); + } else { + YAHOO_CALLBACK (ext_yahoo_got_im) (yd->client_id, + message->to, message->from, message->msg, + message->tm, pkt->status, message->utf8); + } } else if (pkt->status == 0xffffffff) { - YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, - message->msg, 0, E_SYSTEM); + YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, + message->msg, 0, E_SYSTEM); } FREE(message); } @@ -1285,26 +1366,26 @@ static void yahoo_process_message(struct yahoo_input_data *yid, * * 3 level: * ======= - * + * * 302 (318) - Beginning level 1 - * 300 (318) - Begin level 2 - * 302 (319) - End level 2 header - * 300 (319) - Begin level 3 - * 301 (319) - End level 3 - * 303 (319) - End level 2 + * 300 (318) - Begin level 2 + * 302 (319) - End level 2 header + * 300 (319) - Begin level 3 + * 301 (319) - End level 3 + * 303 (319) - End level 2 * 303 (318) - End level 1 * * 2 level: * ======= * * 302 (315) - Beginning level 1 - * 300 (315) - Begin level 2 - * 301 (315) - End level 2 + * 300 (315) - Begin level 2 + * 301 (315) - End level 2 * 303 (315) - End level 1 * */ static void yahoo_process_status(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; struct yahoo_data *yd = yid->yd; @@ -1314,15 +1395,15 @@ static void yahoo_process_status(struct yahoo_input_data *yid, YList *users = 0; if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_DUPL, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_DUPL, NULL); return; } - /* - * Status updates may be spread accross multiple packets and not - * even on buddy boundaries, so keeping some state is important. - * So, continue where we left off, and only add a user entry to + /* + * Status updates may be spread accross multiple packets and not + * even on buddy boundaries, so keeping some state is important. + * So, continue where we left off, and only add a user entry to * the list once it's complete (301-315 End buddy). */ u = yd->half_user; @@ -1331,37 +1412,39 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pair *pair = l->data; switch (pair->key) { - case 300: /* Begin buddy */ + case 300: /* Begin buddy */ if (!strcmp(pair->value, "315") && !u) { u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1); } break; - case 301: /* End buddy */ + case 301: /* End buddy */ if (!strcmp(pair->value, "315") && u) { /* Sometimes user info comes in an odd format with no "begin buddy" but *with* an "end buddy". Don't add it twice. */ - if (!y_list_find(users, u)) + if (!y_list_find(users, u)) { users = y_list_prepend(users, u); + } u = yd->half_user = NULL; } break; - case 0: /* we won't actually do anything with this */ + case 0: /* we won't actually do anything with this */ NOTICE(("key %d:%s", pair->key, pair->value)); break; - case 1: /* we don't get the full buddy list here. */ + case 1: /* we don't get the full buddy list here. */ if (!yd->logged_in) { yd->logged_in = 1; - if (yd->current_status < 0) + if (yd->current_status < 0) { yd->current_status = yd->initial_status; - YAHOO_CALLBACK(ext_yahoo_login_response) (yd-> - client_id, YAHOO_LOGIN_OK, NULL); + } + YAHOO_CALLBACK (ext_yahoo_login_response) (yd-> + client_id, YAHOO_LOGIN_OK, NULL); } break; - case 8: /* how many online buddies we have */ + case 8: /* how many online buddies we have */ NOTICE(("key %d:%s", pair->key, pair->value)); break; - case 7: /* the current buddy */ + case 7: /* the current buddy */ if (!u) { /* This will only happen in case of a single level message */ u = y_new0(struct yahoo_process_status_entry, 1); @@ -1369,28 +1452,28 @@ static void yahoo_process_status(struct yahoo_input_data *yid, } u->name = pair->value; break; - case 10: /* state */ + case 10: /* state */ u->state = strtol(pair->value, NULL, 10); break; - case 19: /* custom status message */ + case 19: /* custom status message */ u->msg = pair->value; break; - case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */ + case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */ u->away = atoi(pair->value); break; - case 137: /* seconds idle */ + case 137: /* seconds idle */ u->idle = atoi(pair->value); break; - case 11: /* this is the buddy's session id */ + case 11: /* this is the buddy's session id */ u->buddy_session = atoi(pair->value); break; - case 17: /* in chat? */ + case 17: /* in chat? */ u->f17 = atoi(pair->value); break; - case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ + case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ u->flags = atoi(pair->value); break; - case 60: /* SMS -> 1 MOBILE USER */ + case 60: /* SMS -> 1 MOBILE USER */ /* sometimes going offline makes this 2, but invisible never sends it */ u->mobile = atoi(pair->value); break; @@ -1421,13 +1504,13 @@ static void yahoo_process_status(struct yahoo_input_data *yid, case 213: u->f213 = atoi(pair->value); break; - case 16: /* Custom error message */ - YAHOO_CALLBACK(ext_yahoo_error) (yd->client_id, - pair->value, 0, E_CUSTOM); + case 16: /* Custom error message */ + YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, + pair->value, 0, E_CUSTOM); break; default: WARNING(("unknown status key %d:%s", pair->key, - pair->value)); + pair->value)); break; } } @@ -1438,21 +1521,22 @@ static void yahoo_process_status(struct yahoo_input_data *yid, if (u->name != NULL) { if (pkt->service == - YAHOO_SERVICE_LOGOFF - /*|| u->flags == 0 No flags for YMSG16 */ ) { - YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> - client_id, u->name, - YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); + YAHOO_SERVICE_LOGOFF + /*|| u->flags == 0 No flags for YMSG16 */) { + YAHOO_CALLBACK (ext_yahoo_status_changed) (yd-> + client_id, u->name, + YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); } else { /* Key 47 always seems to be 1 for YMSG16 */ - if (!u->state) + if (!u->state) { u->away = 0; - else + } else { u->away = 1; + } - YAHOO_CALLBACK(ext_yahoo_status_changed) (yd-> - client_id, u->name, u->state, u->msg, - u->away, u->idle, u->mobile); + YAHOO_CALLBACK (ext_yahoo_status_changed) (yd-> + client_id, u->name, u->state, u->msg, + u->away, u->idle, u->mobile); } } @@ -1463,7 +1547,7 @@ static void yahoo_process_status(struct yahoo_input_data *yid, } static void yahoo_process_buddy_list(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; @@ -1479,10 +1563,11 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, case 300: case 301: case 302: - break; /* Separators. Our logic does not need them */ + break; /* Separators. Our logic does not need them */ case 303: - if (318 == atoi(pair->value)) + if (318 == atoi(pair->value)) { last_packet = 1; + } break; case 65: cur_group = strdup(pair->value); @@ -1490,16 +1575,17 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, case 7: newbud = y_new0(struct yahoo_buddy, 1); newbud->id = strdup(pair->value); - if (cur_group) + if (cur_group) { newbud->group = strdup(cur_group); - else if (yd->buddies) { + } else if (yd->buddies) { struct yahoo_buddy *lastbud = - (struct yahoo_buddy *)y_list_nth(yd-> - buddies, - y_list_length(yd->buddies) - 1)->data; + (struct yahoo_buddy *) y_list_nth(yd-> + buddies, + y_list_length(yd->buddies) - 1)->data; newbud->group = strdup(lastbud->group); - } else + } else { newbud->group = strdup("Buddies"); + } yd->buddies = y_list_append(yd->buddies, newbud); @@ -1508,22 +1594,24 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, } /* we could be getting multiple packets here */ - if (pkt->hash && !last_packet) + if (pkt->hash && !last_packet) { return; + } - YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, yd->buddies); + YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, yd->buddies); /* Logged in */ if (!yd->logged_in) { yd->logged_in = 1; - if (yd->current_status < 0) + if (yd->current_status < 0) { yd->current_status = yd->initial_status; - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_OK, NULL); + } + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_OK, NULL); /* yahoo_set_away(yd->client_id, yd->initial_status, NULL, - (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); + (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); yahoo_get_yab(yd->client_id); */ @@ -1532,7 +1620,7 @@ static void yahoo_process_buddy_list(struct yahoo_input_data *yid, } static void yahoo_process_list(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; @@ -1542,21 +1630,22 @@ static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_pair *pair = l->data; switch (pair->key) { - case 89: /* identities */ - { - char **identities = - y_strsplit(pair->value, ",", -1); - int i; - for (i = 0; identities[i]; i++) - yd->identities = - y_list_append(yd->identities, - strdup(identities[i])); - y_strfreev(identities); + case 89: /* identities */ + { + char **identities = + y_strsplit(pair->value, ",", -1); + int i; + for (i = 0; identities[i]; i++) { + yd->identities = + y_list_append(yd->identities, + strdup(identities[i])); } - YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id, - yd->identities); + y_strfreev(identities); + } + YAHOO_CALLBACK (ext_yahoo_got_identities) (yd->client_id, + yd->identities); break; - case 59: /* cookies */ + case 59: /* cookies */ if (pair->value[0] == 'Y') { FREE(yd->cookie_y); FREE(yd->login_cookie); @@ -1574,34 +1663,35 @@ static void yahoo_process_list(struct yahoo_input_data *yid, } break; - case 3: /* my id */ - case 90: /* 1 */ - case 100: /* 0 */ - case 101: /* NULL */ - case 102: /* NULL */ - case 93: /* 86400/1440 */ + case 3: /* my id */ + case 90: /* 1 */ + case 100: /* 0 */ + case 101: /* NULL */ + case 102: /* NULL */ + case 93: /* 86400/1440 */ break; } } - if (yd->cookie_y && yd->cookie_t) /* We don't get cookie_c anymore */ - YAHOO_CALLBACK(ext_yahoo_got_cookies) (yd->client_id); + if (yd->cookie_y && yd->cookie_t) { /* We don't get cookie_c anymore */ + YAHOO_CALLBACK (ext_yahoo_got_cookies) (yd->client_id); + } } static void yahoo_process_verify(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; if (pkt->status != 0x01) { DEBUG_MSG(("expected status: 0x01, got: %d", pkt->status)); - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_LOCK, ""); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_LOCK, ""); return; } pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_send_packet(yid, pkt, 0); @@ -1611,7 +1701,7 @@ static void yahoo_process_verify(struct yahoo_input_data *yid, } static void yahoo_process_picture_checksum(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *from = NULL; @@ -1637,12 +1727,12 @@ static void yahoo_process_picture_checksum(struct yahoo_input_data *yid, } } - YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum) (yd->client_id, to, - from, checksum); + YAHOO_CALLBACK (ext_yahoo_got_buddyicon_checksum) (yd->client_id, to, + from, checksum); } static void yahoo_process_picture(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *url = NULL; @@ -1657,63 +1747,64 @@ static void yahoo_process_picture(struct yahoo_input_data *yid, switch (pair->key) { case 1: - case 4: /* sender */ + case 4: /* sender */ from = pair->value; break; - case 5: /* we */ + case 5: /* we */ to = pair->value; break; - case 13: /* request / sending */ + case 13: /* request / sending */ status = atoi(pair->value); break; - case 20: /* url */ + case 20: /* url */ url = pair->value; break; - case 192: /*checksum */ + case 192: /*checksum */ checksum = atoi(pair->value); break; } } switch (status) { - case 1: /* this is a request, ignore for now */ - YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request) (yd->client_id, - to, from); + case 1: /* this is a request, ignore for now */ + YAHOO_CALLBACK (ext_yahoo_got_buddyicon_request) (yd->client_id, + to, from); break; - case 2: /* this is cool - we get a picture :) */ - YAHOO_CALLBACK(ext_yahoo_got_buddyicon) (yd->client_id, to, - from, url, checksum); + case 2: /* this is cool - we get a picture :) */ + YAHOO_CALLBACK (ext_yahoo_got_buddyicon) (yd->client_id, to, + from, url, checksum); break; } } static void yahoo_process_picture_upload(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; YList *l; char *url = NULL; - if (pkt->status != 1) - return; /* something went wrong */ + if (pkt->status != 1) { + return; /* something went wrong */ + } for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; switch (pair->key) { - case 5: /* we */ + case 5: /* we */ break; - case 20: /* url */ + case 20: /* url */ url = pair->value; break; - case 27: /* local filename */ + case 27: /* local filename */ break; - case 38: /* time */ + case 38: /* time */ break; } } - YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded) (yd->client_id, url); + YAHOO_CALLBACK (ext_yahoo_buddyicon_uploaded) (yd->client_id, url); } void yahoo_login(int id, int initial) @@ -1726,6 +1817,7 @@ void yahoo_login(int id, int initial) char *host; struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); + yid->yd = yd; yid->type = YAHOO_CONNECTION_PAGER; inputs = y_list_prepend(inputs, yid); @@ -1738,25 +1830,26 @@ void yahoo_login(int id, int initial) host = yss->pager_host; - if (!host) + if (!host) { host = yss->pager_host_list[0]; + } - tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, - host, yss->pager_port, yahoo_connected, ccd, 0); + tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd->client_id, + host, yss->pager_port, yahoo_connected, ccd, 0); /* * if tag <= 0, then callback has already been called * so ccd will have been freed */ - if (tag > 0) + if (tag > 0) { ccd->tag = tag; - else if (tag < 0) - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_SOCK, NULL); + } else if (tag < 0) { + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_SOCK, NULL); + } } -struct yahoo_https_auth_data -{ +struct yahoo_https_auth_data { struct yahoo_input_data *yid; char *token; char *chal; @@ -1773,42 +1866,43 @@ static char *yahoo_ha_find_key(char *response, char *key) { char *s, *end; int len = strlen(key); - + s = response; do { if (strncmp(s, key, len) == 0 && s[len] == '=') { s += len + 1; - if ((end = strchr(s, '\r'))) + if ((end = strchr(s, '\r'))) { return g_strndup(s, end - s); - else + } else { return g_strdup(s); + } + } + + if ((s = strchr(s, '\n'))) { + s++; } - - if ((s = strchr(s, '\n'))) - s ++; } while (s && *s); - + return NULL; } static enum yahoo_status yahoo_https_status_parse(int code) { - switch (code) - { - case 1212: return (enum yahoo_status) YAHOO_LOGIN_PASSWD; - case 1213: return (enum yahoo_status) YAHOO_LOGIN_LOCK; - case 1235: return (enum yahoo_status) YAHOO_LOGIN_UNAME; - default: return (enum yahoo_status) code; + switch (code) { + case 1212: return (enum yahoo_status) YAHOO_LOGIN_PASSWD; + case 1213: return (enum yahoo_status) YAHOO_LOGIN_LOCK; + case 1235: return (enum yahoo_status) YAHOO_LOGIN_UNAME; + default: return (enum yahoo_status) code; } } static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn) { struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1); - + had->yid = yid; had->chal = g_strdup(seed); - + yahoo_https_auth_token_init(had); } @@ -1818,19 +1912,19 @@ static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had) struct yahoo_data *yd = yid->yd; char *login, *passwd, *chal; char *url; - + login = g_strndup(yd->user, 3 * strlen(yd->user)); http_encode(login); passwd = g_strndup(yd->password, 3 * strlen(yd->password)); http_encode(passwd); chal = g_strndup(had->chal, 3 * strlen(had->chal)); http_encode(chal); - + url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s", - (int) time(NULL), login, passwd, chal); - + (int) time(NULL), login, passwd, chal); + http_dorequest_url(url, yahoo_https_auth_token_finish, had); - + g_free(url); g_free(chal); g_free(passwd); @@ -1843,31 +1937,32 @@ static void yahoo_https_auth_token_finish(struct http_request *req) struct yahoo_input_data *yid; struct yahoo_data *yd; int st; - - if (y_list_find(inputs, had->yid) == NULL) + + if (y_list_find(inputs, had->yid) == NULL) { return; - + } + yid = had->yid; yd = yid->yd; - + if (req->status_code != 200) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); goto fail; } - + if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); goto fail; } - + if ((had->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, 3001, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 3001, NULL); goto fail; } - + yahoo_https_auth_init(had); return; - + fail: g_free(had->token); g_free(had->chal); @@ -1877,12 +1972,12 @@ fail: static void yahoo_https_auth_init(struct yahoo_https_auth_data *had) { char *url; - + url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s", (int) time(NULL), had->token); - + http_dorequest_url(url, yahoo_https_auth_finish, had); - + g_free(url); } @@ -1894,38 +1989,39 @@ static void yahoo_https_auth_finish(struct http_request *req) struct yahoo_packet *pack; char *crumb = NULL; int st; - - if (y_list_find(inputs, had->yid) == NULL) + + if (y_list_find(inputs, had->yid) == NULL) { return; - + } + yid = had->yid; yd = yid->yd; - + md5_byte_t result[16]; md5_state_t ctx; - + unsigned char yhash[32]; if (req->status_code != 200) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); goto fail; } - + if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); goto fail; } - + if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL || (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL || (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, 3002, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 3002, NULL); goto fail; } - - md5_init(&ctx); - md5_append(&ctx, (unsigned char*) crumb, 11); - md5_append(&ctx, (unsigned char*) had->chal, strlen(had->chal)); + + md5_init(&ctx); + md5_append(&ctx, (unsigned char *) crumb, 11); + md5_append(&ctx, (unsigned char *) had->chal, strlen(had->chal)); md5_finish(&ctx, result); to_y64(yhash, result, 16); @@ -1934,17 +2030,17 @@ static void yahoo_https_auth_finish(struct http_request *req) yahoo_packet_hash(pack, 0, yd->user); yahoo_packet_hash(pack, 277, yd->cookie_y); yahoo_packet_hash(pack, 278, yd->cookie_t); - yahoo_packet_hash(pack, 307, (char*) yhash); + yahoo_packet_hash(pack, 307, (char *) yhash); yahoo_packet_hash(pack, 244, "524223"); yahoo_packet_hash(pack, 2, yd->user); yahoo_packet_hash(pack, 2, "1"); yahoo_packet_hash(pack, 98, "us"); yahoo_packet_hash(pack, 135, "7.5.0.647"); - + yahoo_send_packet(yid, pack, 0); - + yahoo_packet_free(pack); - + fail: g_free(crumb); g_free(had->token); @@ -1953,7 +2049,7 @@ fail: } static void yahoo_process_auth(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { char *seed = NULL; char *sn = NULL; @@ -1978,21 +2074,22 @@ static void yahoo_process_auth(struct yahoo_input_data *yid, l = l->next; } - if (!seed) + if (!seed) { return; + } - if (m==2) + if (m == 2) { yahoo_https_auth(yid, seed, sn); - else { + } else { /* call error */ WARNING(("unknown auth type %d", m)); - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_UNKNOWN, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_UNKNOWN, NULL); } } static void yahoo_process_auth_resp(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *url = NULL; @@ -2002,25 +2099,26 @@ static void yahoo_process_auth_resp(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 0) + if (pair->key == 0) { ; /* login_id */ - else if (pair->key == 1) + } else if (pair->key == 1) { ; /* handle */ - else if (pair->key == 20) + } else if (pair->key == 20) { url = pair->value; - else if (pair->key == 66) + } else if (pair->key == 66) { login_status = atoi(pair->value); + } } if (pkt->status == YPACKET_STATUS_DISCONNECTED) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - login_status, url); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + login_status, url); /* yahoo_logoff(yd->client_id); */ } } static void yahoo_process_mail(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *who = NULL; @@ -2031,30 +2129,32 @@ static void yahoo_process_mail(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 9) + if (pair->key == 9) { count = strtol(pair->value, NULL, 10); - else if (pair->key == 43) + } else if (pair->key == 43) { who = pair->value; - else if (pair->key == 42) + } else if (pair->key == 42) { email = pair->value; - else if (pair->key == 18) + } else if (pair->key == 18) { subj = pair->value; - else + } else { LOG(("key: %d => value: %s", pair->key, pair->value)); + } } if (who && email && subj) { char from[1024]; snprintf(from, sizeof(from), "%s (%s)", who, email); - YAHOO_CALLBACK(ext_yahoo_mail_notify) (yd->client_id, from, - subj, count); - } else if (count > 0) - YAHOO_CALLBACK(ext_yahoo_mail_notify) (yd->client_id, NULL, - NULL, count); + YAHOO_CALLBACK (ext_yahoo_mail_notify) (yd->client_id, from, + subj, count); + } else if (count > 0) { + YAHOO_CALLBACK (ext_yahoo_mail_notify) (yd->client_id, NULL, + NULL, count); + } } static void yahoo_process_new_contact(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *me = NULL; @@ -2066,26 +2166,28 @@ static void yahoo_process_new_contact(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 4) + if (pair->key == 4) { who = pair->value; - else if (pair->key == 5) + } else if (pair->key == 5) { me = pair->value; - else if (pair->key == 14) + } else if (pair->key == 14) { msg = pair->value; - else if (pair->key == 13) + } else if (pair->key == 13) { online = strtol(pair->value, NULL, 10); + } } - if (who && online < 0) - YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, me, who, - msg); - else if (online == 2) - YAHOO_CALLBACK(ext_yahoo_rejected) (yd->client_id, who, msg); + if (who && online < 0) { + YAHOO_CALLBACK (ext_yahoo_contact_added) (yd->client_id, me, who, + msg); + } else if (online == 2) { + YAHOO_CALLBACK (ext_yahoo_rejected) (yd->client_id, who, msg); + } } /* UNUSED? */ static void yahoo_process_contact(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *id = NULL; @@ -2101,41 +2203,43 @@ static void yahoo_process_contact(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 1) + if (pair->key == 1) { id = pair->value; - else if (pair->key == 3) + } else if (pair->key == 3) { who = pair->value; - else if (pair->key == 14) + } else if (pair->key == 14) { msg = pair->value; - else if (pair->key == 7) + } else if (pair->key == 7) { name = pair->value; - else if (pair->key == 10) + } else if (pair->key == 10) { state = strtol(pair->value, NULL, 10); - else if (pair->key == 15) + } else if (pair->key == 15) { ; /* tm */ - else if (pair->key == 13) + } else if (pair->key == 13) { ; /* online */ - else if (pair->key == 47) + } else if (pair->key == 47) { away = strtol(pair->value, NULL, 10); - else if (pair->key == 137) + } else if (pair->key == 137) { idle = strtol(pair->value, NULL, 10); - else if (pair->key == 60) + } else if (pair->key == 60) { mobile = strtol(pair->value, NULL, 10); + } } - if (id) - YAHOO_CALLBACK(ext_yahoo_contact_added) (yd->client_id, id, who, - msg); - else if (name) - YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, name, - state, msg, away, idle, mobile); - else if (pkt->status == 0x07) - YAHOO_CALLBACK(ext_yahoo_rejected) (yd->client_id, who, msg); + if (id) { + YAHOO_CALLBACK (ext_yahoo_contact_added) (yd->client_id, id, who, + msg); + } else if (name) { + YAHOO_CALLBACK (ext_yahoo_status_changed) (yd->client_id, name, + state, msg, away, idle, mobile); + } else if (pkt->status == 0x07) { + YAHOO_CALLBACK (ext_yahoo_rejected) (yd->client_id, who, msg); + } } static void yahoo_process_buddyadd(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *who = NULL; @@ -2145,22 +2249,29 @@ static void yahoo_process_buddyadd(struct yahoo_input_data *yid, struct yahoo_buddy *bud = NULL; YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 1) + if (pair->key == 1) { ; /* Me... don't care */ - if (pair->key == 7) + } + if (pair->key == 7) { who = pair->value; - if (pair->key == 65) + } + if (pair->key == 65) { where = pair->value; - if (pair->key == 66) + } + if (pair->key == 66) { status = strtol(pair->value, NULL, 10); + } } - if (!who) + if (!who) { return; - if (!where) + } + if (!where) { where = "Unknown"; + } bud = y_new0(struct yahoo_buddy, 1); bud->id = strdup(who); @@ -2180,26 +2291,26 @@ static void yahoo_process_buddyadd(struct yahoo_input_data *yid, will be a separate "went online" packet when the auth. request is accepted. Couldn't find any test account that doesn't require auth. unfortunately (if there is even such a thing?) */ - - /* A non-zero status (i've seen 2) seems to mean the buddy is already + + /* A non-zero status (i've seen 2) seems to mean the buddy is already * added and is online */ if (status) { LOG(("Setting online see packet for info")); yahoo_dump_unhandled(pkt); - YAHOO_CALLBACK(ext_yahoo_status_changed) (yd->client_id, who, - YAHOO_STATUS_AVAILABLE, NULL, 0, 0, 0); + YAHOO_CALLBACK (ext_yahoo_status_changed) (yd->client_id, who, + YAHOO_STATUS_AVAILABLE, NULL, 0, 0, 0); } #endif /* BitlBee: Need ACK of added buddy, if it was successful. */ if (status == 0) { YList *tmp = y_list_append(NULL, bud); - YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, tmp); + YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, tmp); y_list_free(tmp); } } static void yahoo_process_buddydel(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { struct yahoo_data *yd = yid->yd; char *who = NULL; @@ -2209,23 +2320,26 @@ static void yahoo_process_buddydel(struct yahoo_input_data *yid, YList *buddy; YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 1) + if (pair->key == 1) { ; /* Me... don't care */ - else if (pair->key == 7) + } else if (pair->key == 7) { who = pair->value; - else if (pair->key == 65) + } else if (pair->key == 65) { where = pair->value; - else if (pair->key == 66) + } else if (pair->key == 66) { ; /* unk_66 */ - else + } else { DEBUG_MSG(("unknown key: %d = %s", pair->key, - pair->value)); + pair->value)); + } } - if (!who || !where) + if (!who || !where) { return; + } bud = y_new0(struct yahoo_buddy, 1); bud->id = strdup(who); @@ -2252,19 +2366,24 @@ static void yahoo_process_buddydel(struct yahoo_input_data *yid, } static void yahoo_process_ignore(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 0) + if (pair->key == 0) { ; /* who */ - if (pair->key == 1) + } + if (pair->key == 1) { ; /* Me... don't care */ - if (pair->key == 13) /* 1 == ignore, 2 == unignore */ + } + if (pair->key == 13) { /* 1 == ignore, 2 == unignore */ ; - if (pair->key == 66) + } + if (pair->key == 66) { ; /* status */ + } } /* @@ -2276,33 +2395,38 @@ static void yahoo_process_ignore(struct yahoo_input_data *yid, */ /* if(status) - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status); + YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status); */ } static void yahoo_process_voicechat(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { char *who = NULL; char *me = NULL; char *room = NULL; YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 4) + if (pair->key == 4) { who = pair->value; - if (pair->key == 5) + } + if (pair->key == 5) { me = pair->value; - if (pair->key == 13) + } + if (pair->key == 13) { ; /* voice room */ - if (pair->key == 57) + } + if (pair->key == 57) { room = pair->value; + } } NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, - me)); - /* + me)); + /* * send: s:0 1:me 5:who 57:room 13:1 * ???? s:4 5:who 10:99 19:-1615114531 * gotr: s:4 5:who 10:99 19:-1615114615 @@ -2314,23 +2438,25 @@ static void yahoo_process_voicechat(struct yahoo_input_data *yid, } static void yahoo_process_ping(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { char *errormsg = NULL; YList *l; + for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 16) + if (pair->key == 16) { errormsg = pair->value; + } } NOTICE(("got ping packet")); - YAHOO_CALLBACK(ext_yahoo_got_ping) (yid->yd->client_id, errormsg); + YAHOO_CALLBACK (ext_yahoo_got_ping) (yid->yd->client_id, errormsg); } static void yahoo_process_buddy_change_group(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; char *me = NULL; @@ -2340,18 +2466,22 @@ static void yahoo_process_buddy_change_group(struct yahoo_input_data *yid, for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 1) + if (pair->key == 1) { me = pair->value; - if (pair->key == 7) + } + if (pair->key == 7) { who = pair->value; - if (pair->key == 224) + } + if (pair->key == 224) { old_group = pair->value; - if (pair->key == 264) + } + if (pair->key == 264) { new_group = pair->value; + } } - YAHOO_CALLBACK(ext_yahoo_got_buddy_change_group) (yid->yd->client_id, - me, who, old_group, new_group); + YAHOO_CALLBACK (ext_yahoo_got_buddy_change_group) (yid->yd->client_id, + me, who, old_group, new_group); } static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d) @@ -2375,10 +2505,11 @@ static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d) inputs = y_list_prepend(inputs, yid); /* send initial packet */ - if (who) + if (who) { data = strdup("<RVWCFG>"); - else + } else { data = strdup("<RUPCFG>"); + } yahoo_add_to_send_queue(yid, data, strlen(data)); FREE(data); @@ -2403,12 +2534,12 @@ static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d) FREE(data); yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); } static void yahoo_webcam_get_server(struct yahoo_input_data *y, char *who, - char *key) + char *key) { struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); struct yahoo_server_settings *yss = y->yd->server_settings; @@ -2420,32 +2551,36 @@ static void yahoo_webcam_get_server(struct yahoo_input_data *y, char *who, yid->wcm->direction = who ? YAHOO_WEBCAM_DOWNLOAD : YAHOO_WEBCAM_UPLOAD; yid->wcm->key = strdup(key); - YAHOO_CALLBACK(ext_yahoo_connect_async) (yid->yd->client_id, - yss->webcam_host, yss->webcam_port, - _yahoo_webcam_get_server_connected, yid, 0); + YAHOO_CALLBACK (ext_yahoo_connect_async) (yid->yd->client_id, + yss->webcam_host, yss->webcam_port, + _yahoo_webcam_get_server_connected, yid, 0); } static YList *webcam_queue = NULL; static void yahoo_process_webcam_key(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { char *key = NULL; char *who = NULL; YList *l; + yahoo_dump_unhandled(pkt); for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; - if (pair->key == 5) + if (pair->key == 5) { ; /* me */ - if (pair->key == 61) + } + if (pair->key == 61) { key = pair->value; + } } l = webcam_queue; - if (!l) + if (!l) { return; + } who = l->data; webcam_queue = y_list_remove_link(webcam_queue, webcam_queue); y_list_free_1(l); @@ -2454,7 +2589,7 @@ static void yahoo_process_webcam_key(struct yahoo_input_data *yid, } static void yahoo_packet_process(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service)); switch (pkt->service) { @@ -2576,7 +2711,7 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, case YAHOO_SERVICE_PICTURE_UPLOAD: yahoo_process_picture_upload(yid, pkt); break; - case YAHOO_SERVICE_Y8_LIST: /* Buddy List */ + case YAHOO_SERVICE_Y8_LIST: /* Buddy List */ yahoo_process_buddy_list(yid, pkt); break; default: @@ -2593,8 +2728,9 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) int pos = 0; int pktlen; - if (!yd) + if (!yd) { return NULL; + } DEBUG_MSG(("rxlen is %d", yid->rxlen)); if (yid->rxlen < YAHOO_PACKET_HDRLEN) { @@ -2602,7 +2738,7 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) return NULL; } - pos += 4; /* YMSG */ + pos += 4; /* YMSG */ pos += 2; pos += 2; @@ -2625,7 +2761,7 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) pkt->status = yahoo_get32(yid->rxqueue + pos); pos += 4; DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt->service, - pkt->status)); + pkt->status)); pkt->id = yahoo_get32(yid->rxqueue + pos); pos += 4; @@ -2637,11 +2773,11 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); if (yid->rxlen > 0) { unsigned char *tmp = y_memdup(yid->rxqueue + YAHOO_PACKET_HDRLEN - + pktlen, yid->rxlen); + + pktlen, yid->rxlen); FREE(yid->rxqueue); yid->rxqueue = tmp; DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); + yid->rxqueue)); } else { DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); FREE(yid->rxqueue); @@ -2654,7 +2790,7 @@ static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) static struct yab *yahoo_yab_read(unsigned char *d, int len) { char *st, *en; - char *data = (char *)d; + char *data = (char *) d; struct yab *yab = NULL; data[len] = '\0'; @@ -2670,8 +2806,9 @@ static struct yab *yahoo_yab_read(unsigned char *d, int len) yab->email = yahoo_xmldecode(st); } - if (!en) + if (!en) { return NULL; + } st = strstr(en, "id=\""); if (st) { @@ -2754,44 +2891,50 @@ static struct yab *yahoo_getyab(struct yahoo_input_data *yid) int pos = 0, end = 0; struct yahoo_data *yd = yid->yd; - if (!yd) + if (!yd) { return NULL; + } do { DEBUG_MSG(("rxlen is %d", yid->rxlen)); - if (yid->rxlen <= strlen("<ct")) + if (yid->rxlen <= strlen("<ct")) { return NULL; + } /* start with <ct */ while (pos < yid->rxlen - strlen("<ct") + 1 - && memcmp(yid->rxqueue + pos, "<ct", strlen("<ct"))) + && memcmp(yid->rxqueue + pos, "<ct", strlen("<ct"))) { pos++; + } - if (pos >= yid->rxlen - 1) + if (pos >= yid->rxlen - 1) { return NULL; + } end = pos + 2; /* end with > */ while (end < yid->rxlen - strlen(">") - && memcmp(yid->rxqueue + end, ">", strlen(">"))) + && memcmp(yid->rxqueue + end, ">", strlen(">"))) { end++; + } - if (end >= yid->rxlen - 1) + if (end >= yid->rxlen - 1) { return NULL; + } yab = yahoo_yab_read(yid->rxqueue + pos, end + 2 - pos); yid->rxlen -= end + 1; DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); + yid->rxqueue)); if (yid->rxlen > 0) { unsigned char *tmp = - y_memdup(yid->rxqueue + end + 1, yid->rxlen); + y_memdup(yid->rxqueue + end + 1, yid->rxlen); FREE(yid->rxqueue); yid->rxqueue = tmp; DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); + yid->rxqueue)); } else { DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); FREE(yid->rxqueue); @@ -2811,25 +2954,27 @@ static char *yahoo_getwebcam_master(struct yahoo_input_data *yid) char *server = NULL; struct yahoo_data *yd = yid->yd; - if (!yid || !yd) + if (!yid || !yd) { return NULL; + } DEBUG_MSG(("rxlen is %d", yid->rxlen)); len = yid->rxqueue[pos++]; - if (yid->rxlen < len) + if (yid->rxlen < len) { return NULL; + } /* extract status (0 = ok, 6 = webcam not online) */ status = yid->rxqueue[pos++]; if (status == 0) { - pos += 2; /* skip next 2 bytes */ + pos += 2; /* skip next 2 bytes */ server = y_memdup(yid->rxqueue + pos, 16); pos += 16; } else if (status == 6) { - YAHOO_CALLBACK(ext_yahoo_webcam_closed) - (yd->client_id, yid->wcm->user, 4); + YAHOO_CALLBACK (ext_yahoo_webcam_closed) + (yd->client_id, yid->wcm->user, 4); } /* skip rest of the data */ @@ -2841,7 +2986,7 @@ static char *yahoo_getwebcam_master(struct yahoo_input_data *yid) FREE(yid->rxqueue); yid->rxqueue = tmp; DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); + yid->rxqueue)); } else { DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); FREE(yid->rxqueue); @@ -2862,11 +3007,13 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) int connect = 0; struct yahoo_data *yd = yid->yd; - if (!yd) + if (!yd) { return -1; + } - if (!yid->wcm || !yid->wcd || !yid->rxlen) + if (!yid->wcm || !yid->wcd || !yid->rxlen) { return -1; + } DEBUG_MSG(("rxlen is %d", yid->rxlen)); @@ -2875,8 +3022,9 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) header_len = yid->rxqueue[pos++]; yid->wcd->packet_type = 0; - if (yid->rxlen < header_len) + if (yid->rxlen < header_len) { return 0; + } if (header_len >= 8) { reason = yid->rxqueue[pos++]; @@ -2898,8 +3046,9 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) begin = pos; pos += yid->wcd->to_read; - if (pos > yid->rxlen) + if (pos > yid->rxlen) { pos = yid->rxlen; + } /* if it is not an image then make sure we have the whole packet */ if (yid->wcd->packet_type != 0x02) { @@ -2912,22 +3061,24 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) } DEBUG_MSG(("packet type %.2X, data length %d", yid->wcd->packet_type, - yid->wcd->data_size)); + yid->wcd->data_size)); /* find out what kind of packet we got */ switch (yid->wcd->packet_type) { case 0x00: /* user requests to view webcam (uploading) */ if (yid->wcd->data_size && - yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { + yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { end = begin; - while (end <= yid->rxlen && yid->rxqueue[end++] != 13) ; + while (end <= yid->rxlen && yid->rxqueue[end++] != 13) { + ; + } if (end > begin) { who = y_memdup(yid->rxqueue + begin, - end - begin); + end - begin); who[end - begin - 1] = 0; - YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd-> - client_id, who + 2, 2); + YAHOO_CALLBACK (ext_yahoo_webcam_viewer) (yd-> + client_id, who + 2, 2); FREE(who); } } @@ -2937,58 +3088,59 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) /* 0 = declined viewing permission */ /* 1 = accepted viewing permission */ if (yid->wcd->timestamp == 0) { - YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd-> - client_id, yid->wcm->user, 3); + YAHOO_CALLBACK (ext_yahoo_webcam_closed) (yd-> + client_id, yid->wcm->user, 3); } } break; - case 0x01: /* status packets?? */ + case 0x01: /* status packets?? */ /* timestamp contains status info */ /* 00 00 00 01 = we have data?? */ break; - case 0x02: /* image data */ - YAHOO_CALLBACK(ext_yahoo_got_webcam_image) (yd->client_id, - yid->wcm->user, yid->rxqueue + begin, - yid->wcd->data_size, pos - begin, yid->wcd->timestamp); + case 0x02: /* image data */ + YAHOO_CALLBACK (ext_yahoo_got_webcam_image) (yd->client_id, + yid->wcm->user, yid->rxqueue + begin, + yid->wcd->data_size, pos - begin, yid->wcd->timestamp); break; - case 0x05: /* response packets when uploading */ + case 0x05: /* response packets when uploading */ if (!yid->wcd->data_size) { - YAHOO_CALLBACK(ext_yahoo_webcam_data_request) (yd-> - client_id, yid->wcd->timestamp); + YAHOO_CALLBACK (ext_yahoo_webcam_data_request) (yd-> + client_id, yid->wcd->timestamp); } break; - case 0x07: /* connection is closing */ + case 0x07: /* connection is closing */ switch (reason) { - case 0x01: /* user closed connection */ + case 0x01: /* user closed connection */ closed = 1; break; - case 0x0F: /* user cancelled permission */ + case 0x0F: /* user cancelled permission */ closed = 2; break; } - YAHOO_CALLBACK(ext_yahoo_webcam_closed) (yd->client_id, - yid->wcm->user, closed); + YAHOO_CALLBACK (ext_yahoo_webcam_closed) (yd->client_id, + yid->wcm->user, closed); break; - case 0x0C: /* user connected */ - case 0x0D: /* user disconnected */ + case 0x0C: /* user connected */ + case 0x0D: /* user disconnected */ if (yid->wcd->data_size) { who = y_memdup(yid->rxqueue + begin, pos - begin + 1); who[pos - begin] = 0; - if (yid->wcd->packet_type == 0x0C) + if (yid->wcd->packet_type == 0x0C) { connect = 1; - else + } else { connect = 0; - YAHOO_CALLBACK(ext_yahoo_webcam_viewer) (yd->client_id, - who, connect); + } + YAHOO_CALLBACK (ext_yahoo_webcam_viewer) (yd->client_id, + who, connect); FREE(who); } break; - case 0x13: /* user data */ + case 0x13: /* user data */ /* i=user_ip (ip of the user we are viewing) */ /* j=user_ext_ip (external ip of the user we */ /* are viewing) */ break; - case 0x17: /* ?? */ + case 0x17: /* ?? */ break; } yid->wcd->to_read -= pos - begin; @@ -3000,15 +3152,16 @@ static int yahoo_get_webcam_data(struct yahoo_input_data *yid) FREE(yid->rxqueue); yid->rxqueue = tmp; DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); + yid->rxqueue)); } else { DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); FREE(yid->rxqueue); } /* If we read a complete packet return success */ - if (!yid->wcd->to_read) + if (!yid->wcd->to_read) { return 1; + } return 0; } @@ -3020,15 +3173,17 @@ int yahoo_write_ready(int id, void *fd, void *data) struct data_queue *tx; LOG(("write callback: id=%d fd=%p data=%p", id, fd, data)); - if (!yid || !yid->txqueues) + if (!yid || !yid->txqueues) { return -2; + } tx = yid->txqueues->data; LOG(("writing %d bytes", tx->len)); len = yahoo_send_data(fd, tx->queue, MIN(1024, tx->len)); - if (len == -1 && errno == EAGAIN) + if (len == -1 && errno == EAGAIN) { return 1; + } if (len <= 0) { int e = errno; @@ -3039,12 +3194,12 @@ int yahoo_write_ready(int id, void *fd, void *data) free(tx->queue); free(tx); yid->txqueues = - y_list_remove_link(yid->txqueues, - yid->txqueues); + y_list_remove_link(yid->txqueues, + yid->txqueues); y_list_free_1(l); } LOG(("yahoo_write_ready(%d, %p) len < 0", id, fd)); - YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, yid->write_tag); + YAHOO_CALLBACK (ext_yahoo_remove_handler) (id, yid->write_tag); yid->write_tag = 0; errno = e; return 0; @@ -3061,16 +3216,16 @@ int yahoo_write_ready(int id, void *fd, void *data) free(tx->queue); free(tx); yid->txqueues = - y_list_remove_link(yid->txqueues, yid->txqueues); + y_list_remove_link(yid->txqueues, yid->txqueues); y_list_free_1(l); /* - if(!yid->txqueues) + if(!yid->txqueues) LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd)); */ if (!yid->txqueues) { LOG(("yahoo_write_ready(%d, %p) !txqueues", id, fd)); - YAHOO_CALLBACK(ext_yahoo_remove_handler) (id, - yid->write_tag); + YAHOO_CALLBACK (ext_yahoo_remove_handler) (id, + yid->write_tag); yid->write_tag = 0; } } @@ -3079,17 +3234,18 @@ int yahoo_write_ready(int id, void *fd, void *data) } static void yahoo_process_pager_connection(struct yahoo_input_data *yid, - int over) + int over) { struct yahoo_packet *pkt; struct yahoo_data *yd = yid->yd; int id = yd->client_id; - if (over) + if (over) { return; + } while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER) - && (pkt = yahoo_getdata(yid)) != NULL) { + && (pkt = yahoo_getdata(yid)) != NULL) { yahoo_packet_process(yid, pkt); @@ -3098,14 +3254,15 @@ static void yahoo_process_pager_connection(struct yahoo_input_data *yid, } static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, - int over) + int over) { - if (over) + if (over) { return; + } - if (strstr((char *)yid->rxqueue + (yid->rxlen - 20), "</content>")) { - YAHOO_CALLBACK(ext_yahoo_chat_cat_xml) (yid->yd->client_id, - (char *)yid->rxqueue); + if (strstr((char *) yid->rxqueue + (yid->rxlen - 20), "</content>")) { + YAHOO_CALLBACK (ext_yahoo_chat_cat_xml) (yid->yd->client_id, + (char *) yid->rxqueue); } } @@ -3121,13 +3278,15 @@ static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) LOG(("Got data for YAB")); - if (over) + if (over) { return; + } while (find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB) - && (yab = yahoo_getyab(yid)) != NULL) { - if (!yab->id) + && (yab = yahoo_getyab(yid)) != NULL) { + if (!yab->id) { continue; + } changed = 1; yab_used = 0; @@ -3140,14 +3299,14 @@ static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) bud->real_name = strdup(yab->nname); } else if (yab->fname && yab->lname) { bud->real_name = y_new0(char, - strlen(yab->fname) + - strlen(yab->lname) + 2); + strlen(yab->fname) + + strlen(yab->lname) + 2); sprintf(bud->real_name, "%s %s", - yab->fname, yab->lname); + yab->fname, yab->lname); } else if (yab->fname) { bud->real_name = strdup(yab->fname); } - break; /* for */ + break; /* for */ } } @@ -3165,26 +3324,28 @@ static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) } - if (changed) - YAHOO_CALLBACK(ext_yahoo_got_buddies) (yd->client_id, - yd->buddies); + if (changed) { + YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, + yd->buddies); + } } #endif static void yahoo_process_search_connection(struct yahoo_input_data *yid, - int over) + int over) { struct yahoo_found_contact *yct = NULL; - char *p = (char *)yid->rxqueue, *np, *cp; + char *p = (char *) yid->rxqueue, *np, *cp; int k, n; int start = 0, found = 0, total = 0; YList *contacts = NULL; struct yahoo_input_data *pyid = - find_input_by_id_and_type(yid->yd->client_id, - YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(yid->yd->client_id, + YAHOO_CONNECTION_PAGER); - if (!over || !pyid) + if (!over || !pyid) { return; + } if (p && (p = strstr(p, "\r\n\r\n"))) { p += 4; @@ -3205,25 +3366,27 @@ static void yahoo_process_search_connection(struct yahoo_input_data *yid, } } - if (p) + if (p) { p++; + } k = 0; while (p && *p) { cp = p; np = strchr(p, 4); - if (!np) + if (!np) { break; + } *np = 0; p = np + 1; switch (k++) { case 1: if (strlen(cp) > 2 - && y_list_length(contacts) < total) { + && y_list_length(contacts) < total) { yct = y_new0(struct yahoo_found_contact, - 1); + 1); contacts = y_list_append(contacts, yct); yct->id = cp + 2; } else { @@ -3241,16 +3404,17 @@ static void yahoo_process_search_connection(struct yahoo_input_data *yid, break; case 5: /* not worth the context switch for strcmp */ - if (cp[0] != '\005' || cp[1] != '\000') + if (cp[0] != '\005' || cp[1] != '\000') { yct->location = cp; + } k = 0; break; } } } - YAHOO_CALLBACK(ext_yahoo_got_search_result) (yid->yd->client_id, found, - start, total, contacts); + YAHOO_CALLBACK (ext_yahoo_got_search_result) (yid->yd->client_id, found, + start, total, contacts); while (contacts) { YList *node = contacts; @@ -3356,8 +3520,8 @@ static void _yahoo_webcam_connected(void *fd, int error, void *d) FREE(data); yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, - yid->fd, YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, + yid->fd, YAHOO_INPUT_READ, yid); } static void yahoo_webcam_connect(struct yahoo_input_data *y) @@ -3365,8 +3529,9 @@ static void yahoo_webcam_connect(struct yahoo_input_data *y) struct yahoo_webcam *wcm = y->wcm; struct yahoo_input_data *yid; - if (!wcm || !wcm->server || !wcm->key) + if (!wcm || !wcm->server || !wcm->key) { return; + } yid = y_new0(struct yahoo_input_data, 1); yid->type = YAHOO_CONNECTION_WEBCAM; @@ -3379,19 +3544,20 @@ static void yahoo_webcam_connect(struct yahoo_input_data *y) yid->wcd = y_new0(struct yahoo_webcam_data, 1); LOG(("Connecting to: %s:%d", wcm->server, wcm->port)); - YAHOO_CALLBACK(ext_yahoo_connect_async) (y->yd->client_id, wcm->server, - wcm->port, _yahoo_webcam_connected, yid, 0); + YAHOO_CALLBACK (ext_yahoo_connect_async) (y->yd->client_id, wcm->server, + wcm->port, _yahoo_webcam_connected, yid, 0); } static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, - int over) + int over) { char *server; struct yahoo_server_settings *yss; - if (over) + if (over) { return; + } server = yahoo_getwebcam_master(yid); @@ -3401,35 +3567,40 @@ static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, yid->wcm->port = yss->webcam_port; yid->wcm->conn_type = yss->conn_type; yid->wcm->my_ip = strdup(yss->local_host); - if (yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) + if (yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { yid->wcm->description = strdup(yss->webcam_description); + } yahoo_webcam_connect(yid); FREE(server); } } static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, - int over) + int over) { int id = yid->yd->client_id; void *fd = yid->fd; - if (over) + if (over) { return; + } /* as long as we still have packets available keep processing them */ while (find_input_by_id_and_fd(id, fd) - && yahoo_get_webcam_data(yid) == 1) ; + && yahoo_get_webcam_data(yid) == 1) { + ; + } } -static void (*yahoo_process_connection[]) (struct yahoo_input_data *, - int over) = { -yahoo_process_pager_connection, yahoo_process_ft_connection, - NULL, /*yahoo_process_yab_connection, */ - yahoo_process_webcam_master_connection, - yahoo_process_webcam_connection, - yahoo_process_chatcat_connection, - yahoo_process_search_connection}; +static void(*yahoo_process_connection[]) (struct yahoo_input_data *, + int over) = { + yahoo_process_pager_connection, yahoo_process_ft_connection, + NULL, /*yahoo_process_yab_connection, */ + yahoo_process_webcam_master_connection, + yahoo_process_webcam_connection, + yahoo_process_chatcat_connection, + yahoo_process_search_connection +}; int yahoo_read_ready(int id, void *fd, void *data) { @@ -3438,31 +3609,34 @@ int yahoo_read_ready(int id, void *fd, void *data) int len; LOG(("read callback: id=%d fd=%p data=%p", id, fd, data)); - if (!yid) + if (!yid) { return -2; + } do { - len = YAHOO_CALLBACK(ext_yahoo_read) (fd, buf, sizeof(buf)); + len = YAHOO_CALLBACK (ext_yahoo_read) (fd, buf, sizeof(buf)); } while (len == -1 && errno == EINTR); - if (len == -1 && (errno == EAGAIN || errno == EINTR)) /* we'll try again later */ + if (len == -1 && (errno == EAGAIN || errno == EINTR)) { /* we'll try again later */ return 1; + } if (len <= 0) { int e = errno; DEBUG_MSG(("len == %d (<= 0)", len)); if (yid->type == YAHOO_CONNECTION_PAGER) { - YAHOO_CALLBACK(ext_yahoo_login_response) (yid->yd-> - client_id, YAHOO_LOGIN_SOCK, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yid->yd-> + client_id, YAHOO_LOGIN_SOCK, NULL); } yahoo_process_connection[yid->type] (yid, 1); yahoo_input_close(yid); /* no need to return an error, because we've already fixed it */ - if (len == 0) + if (len == 0) { return 1; + } errno = e; LOG(("read error: %s", strerror(errno))); @@ -3470,7 +3644,7 @@ int yahoo_read_ready(int id, void *fd, void *data) } yid->rxqueue = - y_renew(unsigned char, yid->rxqueue, len + yid->rxlen + 1); + y_renew(unsigned char, yid->rxqueue, len + yid->rxlen + 1); memcpy(yid->rxqueue + yid->rxlen, buf, len); yid->rxlen += len; yid->rxqueue[yid->rxlen] = 0; @@ -3487,8 +3661,9 @@ int yahoo_init_with_attributes(const char *username, const char *password, ...) yd = y_new0(struct yahoo_data, 1); - if (!yd) + if (!yd) { return 0; + } yd->user = strdup(username); yd->password = strdup(password); @@ -3525,18 +3700,20 @@ static void yahoo_connected(void *fd, int error, void *data) if (fallback_ports[ccd->i]) { char *host = yss->pager_host; - if (!host) + if (!host) { host = yss->pager_host_list[ccd->server_i]; + } yss->pager_port = fallback_ports[ccd->i++]; - tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd-> - client_id, host, yss->pager_port, - yahoo_connected, ccd, 0); + tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd-> + client_id, host, yss->pager_port, + yahoo_connected, ccd, 0); - if (tag > 0) + if (tag > 0) { ccd->tag = tag; + } } else if (yss->pager_host_list - && yss->pager_host_list[ccd->server_i]) { + && yss->pager_host_list[ccd->server_i]) { /* Get back to the default port */ yss->pager_port = pager_port; @@ -3544,13 +3721,14 @@ static void yahoo_connected(void *fd, int error, void *data) LOG(("Fallback: Connecting to %s:%d", yss->pager_host_list[ccd->server_i], yss->pager_port)); ccd->i = 0; - tag = YAHOO_CALLBACK(ext_yahoo_connect_async) (yd->client_id, - yss->pager_host_list[ccd->server_i], yss->pager_port, - yahoo_connected, ccd, 0); + tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd->client_id, + yss->pager_host_list[ccd->server_i], + yss->pager_port, + yahoo_connected, ccd, 0); } else { FREE(ccd); - YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_SOCK, NULL); + YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, + YAHOO_LOGIN_SOCK, NULL); } return; } @@ -3558,11 +3736,12 @@ static void yahoo_connected(void *fd, int error, void *data) FREE(ccd); /* fd == NULL && error == 0 means connect was cancelled */ - if (!fd) + if (!fd) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); NOTICE(("Sending initial packet")); yahoo_packet_hash(pkt, 1, yd->user); @@ -3575,18 +3754,20 @@ static void yahoo_connected(void *fd, int error, void *data) yahoo_packet_free(pkt); yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, - yid->fd, YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, + yid->fd, YAHOO_INPUT_READ, yid); } void *yahoo_get_fd(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - if (!yid) + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + + if (!yid) { return 0; - else + } else { return yid->fd; + } } #if 0 @@ -3597,34 +3778,37 @@ void yahoo_send_buzz(int id, const char *from, const char *who) #endif void yahoo_send_im(int id, const char *from, const char *who, const char *what, - int utf8, int picture) + int utf8, int picture) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_packet *pkt = NULL; struct yahoo_data *yd; char pic_str[10]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, (enum ypacket_status) YAHOO_STATUS_OFFLINE, - yd->session_id); + yd->session_id); snprintf(pic_str, sizeof(pic_str), "%d", picture); - if (from && strcmp(from, yd->user)) + if (from && strcmp(from, yd->user)) { yahoo_packet_hash(pkt, 0, yd->user); + } yahoo_packet_hash(pkt, 1, from ? from : yd->user); yahoo_packet_hash(pkt, 5, who); yahoo_packet_hash(pkt, 14, what); - if (utf8) + if (utf8) { yahoo_packet_hash(pkt, 97, "1"); + } - yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */ + yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */ yahoo_packet_hash(pkt, 64, "0"); yahoo_packet_hash(pkt, 206, pic_str); @@ -3636,15 +3820,17 @@ void yahoo_send_im(int id, const char *from, const char *who, const char *what, void yahoo_send_typing(int id, const char *from, const char *who, int typ) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 5, who); yahoo_packet_hash(pkt, 1, from ? from : yd->user); @@ -3660,14 +3846,15 @@ void yahoo_send_typing(int id, const char *from, const char *who, int typ) void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; int old_status; char s[4]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; @@ -3677,7 +3864,7 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) /* Thank you libpurple :) */ if (yd->current_status == YAHOO_STATUS_INVISIBLE) { pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, - (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); + (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 13, "2"); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); @@ -3686,17 +3873,17 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) } pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, - yd->current_status, yd->session_id); + yd->current_status, yd->session_id); snprintf(s, sizeof(s), "%d", yd->current_status); yahoo_packet_hash(pkt, 10, s); yahoo_packet_hash(pkt, 19, msg && state == YAHOO_STATUS_CUSTOM ? msg : ""); - yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); + yahoo_packet_hash(pkt, 47, (away == 2) ? "2" : (away) ? "1" : "0"); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); if (old_status == YAHOO_STATUS_INVISIBLE) { pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, - (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); + (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); yahoo_packet_hash(pkt, 13, "1"); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); @@ -3706,12 +3893,13 @@ void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) void yahoo_logoff(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; LOG(("yahoo_logoff: current status: %d", yd->current_status)); @@ -3721,7 +3909,7 @@ void yahoo_logoff(int id) get to do this so it'll just leak memory. And the TCP connection reset will hopefully be clear enough. */ pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yd->current_status = -1; if (pkt) { @@ -3731,8 +3919,8 @@ void yahoo_logoff(int id) } /* do { - yahoo_input_close(yid); - } while((yid = find_input_by_id(id)));*/ + yahoo_input_close(yid); + } while((yid = find_input_by_id(id)));*/ } @@ -3740,16 +3928,17 @@ void yahoo_logoff(int id) void yahoo_get_list(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); if (pkt) { yahoo_send_packet(yid, pkt, 0); @@ -3761,6 +3950,7 @@ void yahoo_get_list(int id) static void _yahoo_http_connected(int id, void *fd, int error, void *data) { struct yahoo_input_data *yid = data; + if (fd == NULL || error) { inputs = y_list_remove(inputs, yid); FREE(yid); @@ -3769,8 +3959,8 @@ static void _yahoo_http_connected(int id, void *fd, int error, void *data) yid->fd = fd; yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); } #if 0 @@ -3782,8 +3972,9 @@ void yahoo_get_yab(int id) char url[1024]; char buff[2048]; - if (!yd) + if (!yd) { return; + } yid = y_new0(struct yahoo_input_data, 1); yid->yd = yd; @@ -3792,15 +3983,15 @@ void yahoo_get_yab(int id) LOG(("Sending request for Address Book")); snprintf(url, 1024, - "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" - "&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252"); + "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" + "&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252"); snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); inputs = y_list_prepend(inputs, yid); yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); + _yahoo_http_connected, yid); } struct yahoo_post_data { @@ -3820,12 +4011,12 @@ static void _yahoo_http_post_connected(int id, void *fd, int error, void *data) return; } - YAHOO_CALLBACK(ext_yahoo_write) (fd, buff, strlen(buff)); + YAHOO_CALLBACK (ext_yahoo_write) (fd, buff, strlen(buff)); yid->fd = fd; yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); FREE(buff); FREE(yad); @@ -3842,53 +4033,56 @@ void yahoo_set_yab(int id, struct yab *yab) char post[1024]; int size = 0; - if (!yd) + if (!yd) { return; + } yid = y_new0(struct yahoo_input_data, 1); yid->type = YAHOO_CONNECTION_YAB; yid->yd = yd; - if(yab->yid) + if (yab->yid) { size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>" - "<ab k=\"%s\" cc=\"%d\">" - "<ct id=\"%d\" e=\"1\" yi=\"%s\" nn=\"%s\" />" - "</ab>", yd->user, 9, yab->yid, /* Don't know why */ - yab->id, yab->nname?yab->nname:""); - else + "<ab k=\"%s\" cc=\"%d\">" + "<ct id=\"%d\" e=\"1\" yi=\"%s\" nn=\"%s\" />" + "</ab>", yd->user, 9, yab->yid, /* Don't know why */ + yab->id, yab->nname ? yab->nname : ""); + } else { size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>" - "<ab k=\"%s\" cc=\"%d\">" - "<ct a=\"1\" yi=\"%s\" nn=\"%s\" />" - "</ab>", yd->user, 1, /* Don't know why */ - yab->id, yab->nname?yab->nname:""); + "<ab k=\"%s\" cc=\"%d\">" + "<ct a=\"1\" yi=\"%s\" nn=\"%s\" />" + "</ab>", yd->user, 1, /* Don't know why */ + yab->id, yab->nname ? yab->nname : ""); + } yad->yid = yid; yad->data = strdup(post); strcpy(url, "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" - "&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"); + "&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"); snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); inputs = y_list_prepend(inputs, yid); yahoo_http_post(yid->yd->client_id, url, buff, size, - _yahoo_http_post_connected, yad); + _yahoo_http_post_connected, yad); } void yahoo_set_identity_status(int id, const char *identity, int active) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(active ? YAHOO_SERVICE_IDACT : - YAHOO_SERVICE_IDDEACT, YPACKET_STATUS_DEFAULT, yd->session_id); + YAHOO_SERVICE_IDDEACT, YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 3, identity); if (pkt) { yahoo_send_packet(yid, pkt, 0); @@ -3899,16 +4093,17 @@ void yahoo_set_identity_status(int id, const char *identity, int active) void yahoo_refresh(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); if (pkt) { yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); @@ -3919,15 +4114,17 @@ void yahoo_refresh(int id) void yahoo_keepalive(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } @@ -3936,43 +4133,47 @@ void yahoo_keepalive(int id) void yahoo_chat_keepalive(int id) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } #endif void yahoo_add_buddy(int id, const char *who, const char *group, - const char *msg) + const char *msg) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; - if (!yd->logged_in) + if (!yd->logged_in) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT, - yd->session_id); - if (msg != NULL) /* add message/request "it's me add me" */ + yd->session_id); + if (msg != NULL) { /* add message/request "it's me add me" */ yahoo_packet_hash(pkt, 14, msg); - else + } else { yahoo_packet_hash(pkt, 14, ""); + } yahoo_packet_hash(pkt, 65, group); yahoo_packet_hash(pkt, 97, "1"); yahoo_packet_hash(pkt, 1, yd->user); @@ -3989,16 +4190,17 @@ void yahoo_add_buddy(int id, const char *who, const char *group, void yahoo_remove_buddy(int id, const char *who, const char *group) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 7, who); @@ -4010,24 +4212,26 @@ void yahoo_remove_buddy(int id, const char *who, const char *group) void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; - if (!yd->logged_in) + if (!yd->logged_in) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_AUTHORIZATION, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 5, who); - if (reject) + if (reject) { yahoo_packet_hash(pkt, 13, "2"); - else { + } else { yahoo_packet_hash(pkt, 241, "0"); yahoo_packet_hash(pkt, 13, "1"); } @@ -4047,19 +4251,21 @@ void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg) void yahoo_ignore_buddy(int id, const char *who, int unignore) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; - if (!yd->logged_in) + if (!yd->logged_in) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 7, who); yahoo_packet_hash(pkt, 13, unignore ? "2" : "1"); @@ -4070,19 +4276,21 @@ void yahoo_ignore_buddy(int id, const char *who, int unignore) void yahoo_stealth_buddy(int id, const char *who, int unstealth) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; - if (!yd->logged_in) + if (!yd->logged_in) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH_PERM, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 7, who); yahoo_packet_hash(pkt, 31, unstealth ? "2" : "1"); @@ -4093,19 +4301,20 @@ void yahoo_stealth_buddy(int id, const char *who, int unstealth) #endif void yahoo_change_buddy_group(int id, const char *who, const char *old_group, - const char *new_group) + const char *new_group) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_CHANGE_GROUP, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 302, "240"); yahoo_packet_hash(pkt, 300, "240"); @@ -4123,16 +4332,17 @@ void yahoo_change_buddy_group(int id, const char *who, const char *old_group, void yahoo_group_rename(int id, const char *old_group, const char *new_group) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt = NULL; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 65, old_group); yahoo_packet_hash(pkt, 67, new_group); @@ -4142,19 +4352,20 @@ void yahoo_group_rename(int id, const char *old_group, const char *new_group) } void yahoo_conference_addinvite(int id, const char *from, const char *who, - const char *room, const YList *members, const char *msg) + const char *room, const YList *members, const char *msg) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 51, who); @@ -4162,8 +4373,8 @@ void yahoo_conference_addinvite(int id, const char *from, const char *who, yahoo_packet_hash(pkt, 58, msg); yahoo_packet_hash(pkt, 13, "0"); for (; members; members = members->next) { - yahoo_packet_hash(pkt, 52, (char *)members->data); - yahoo_packet_hash(pkt, 53, (char *)members->data); + yahoo_packet_hash(pkt, 52, (char *) members->data); + yahoo_packet_hash(pkt, 53, (char *) members->data); } /* 52, 53 -> other members? */ @@ -4174,24 +4385,25 @@ void yahoo_conference_addinvite(int id, const char *from, const char *who, #endif void yahoo_conference_invite(int id, const char *from, YList *who, - const char *room, const char *msg) + const char *room, const char *msg) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 50, yd->user); for (; who; who = who->next) { - yahoo_packet_hash(pkt, 52, (char *)who->data); + yahoo_packet_hash(pkt, 52, (char *) who->data); } yahoo_packet_hash(pkt, 57, room); yahoo_packet_hash(pkt, 58, msg); @@ -4203,25 +4415,27 @@ void yahoo_conference_invite(int id, const char *from, YList *who, } void yahoo_conference_logon(int id, const char *from, YList *who, - const char *room) + const char *room) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); yahoo_packet_hash(pkt, 57, room); - for (; who; who = who->next) - yahoo_packet_hash(pkt, 3, (char *)who->data); + for (; who; who = who->next) { + yahoo_packet_hash(pkt, 3, (char *) who->data); + } yahoo_send_packet(yid, pkt, 0); @@ -4229,24 +4443,26 @@ void yahoo_conference_logon(int id, const char *from, YList *who, } void yahoo_conference_decline(int id, const char *from, YList *who, - const char *room, const char *msg) + const char *room, const char *msg) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); - for (; who; who = who->next) - yahoo_packet_hash(pkt, 3, (char *)who->data); + for (; who; who = who->next) { + yahoo_packet_hash(pkt, 3, (char *) who->data); + } yahoo_packet_hash(pkt, 57, room); yahoo_packet_hash(pkt, 14, msg); @@ -4256,24 +4472,26 @@ void yahoo_conference_decline(int id, const char *from, YList *who, } void yahoo_conference_logoff(int id, const char *from, YList *who, - const char *room) + const char *room) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); - for (; who; who = who->next) - yahoo_packet_hash(pkt, 3, (char *)who->data); + for (; who; who = who->next) { + yahoo_packet_hash(pkt, 3, (char *) who->data); + } yahoo_packet_hash(pkt, 57, room); @@ -4283,30 +4501,33 @@ void yahoo_conference_logoff(int id, const char *from, YList *who, } void yahoo_conference_message(int id, const char *from, YList *who, - const char *room, const char *msg, int utf8) + const char *room, const char *msg, int utf8) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 53, (from ? from : yd->user)); - for (; who; who = who->next) - yahoo_packet_hash(pkt, 53, (char *)who->data); + for (; who; who = who->next) { + yahoo_packet_hash(pkt, 53, (char *) who->data); + } yahoo_packet_hash(pkt, 57, room); yahoo_packet_hash(pkt, 14, msg); - if (utf8) + if (utf8) { yahoo_packet_hash(pkt, 97, "1"); + } yahoo_send_packet(yid, pkt, 0); @@ -4321,8 +4542,9 @@ void yahoo_get_chatrooms(int id, int chatroomid) char url[1024]; char buff[1024]; - if (!yd) + if (!yd) { return; + } yid = y_new0(struct yahoo_input_data, 1); yid->yd = yd; @@ -4330,11 +4552,11 @@ void yahoo_get_chatrooms(int id, int chatroomid) if (chatroomid == 0) { snprintf(url, 1024, - "http://insider.msg.yahoo.com/ycontent/?chatcat=0"); + "http://insider.msg.yahoo.com/ycontent/?chatcat=0"); } else { snprintf(url, 1024, - "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0", - chatroomid); + "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0", + chatroomid); } snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); @@ -4342,24 +4564,25 @@ void yahoo_get_chatrooms(int id, int chatroomid) inputs = y_list_prepend(inputs, yid); yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); + _yahoo_http_connected, yid); } void yahoo_chat_logon(int id, const char *from, const char *room, - const char *roomid) + const char *roomid) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 109, yd->user); @@ -4370,12 +4593,12 @@ void yahoo_chat_logon(int id, const char *from, const char *room, yahoo_packet_free(pkt); pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 104, room); yahoo_packet_hash(pkt, 129, roomid); - yahoo_packet_hash(pkt, 62, "2"); /* ??? */ + yahoo_packet_hash(pkt, 62, "2"); /* ??? */ yahoo_send_packet(yid, pkt, 0); @@ -4383,21 +4606,22 @@ void yahoo_chat_logon(int id, const char *from, const char *room, } void yahoo_chat_message(int id, const char *from, const char *room, - const char *msg, const int msgtype, const int utf8) + const char *msg, const int msgtype, const int utf8) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; char buf[2]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); yahoo_packet_hash(pkt, 104, room); @@ -4406,8 +4630,9 @@ void yahoo_chat_message(int id, const char *from, const char *room, snprintf(buf, sizeof(buf), "%d", msgtype); yahoo_packet_hash(pkt, 124, buf); - if (utf8) + if (utf8) { yahoo_packet_hash(pkt, 97, "1"); + } yahoo_send_packet(yid, pkt, 0); @@ -4417,17 +4642,18 @@ void yahoo_chat_message(int id, const char *from, const char *room, void yahoo_chat_logoff(int id, const char *from) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); @@ -4439,17 +4665,18 @@ void yahoo_chat_logoff(int id, const char *from) void yahoo_buddyicon_request(int id, const char *who) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, - 0); + 0); yahoo_packet_hash(pkt, 4, yd->user); yahoo_packet_hash(pkt, 5, who); yahoo_packet_hash(pkt, 13, "1"); @@ -4459,23 +4686,24 @@ void yahoo_buddyicon_request(int id, const char *who) } void yahoo_send_picture_info(int id, const char *who, const char *url, - int checksum) + int checksum) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; char checksum_str[10]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, - 0); + 0); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 4, yd->user); yahoo_packet_hash(pkt, 5, who); @@ -4490,20 +4718,21 @@ void yahoo_send_picture_info(int id, const char *who, const char *url, void yahoo_send_picture_update(int id, const char *who, int type) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; char type_str[10]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; snprintf(type_str, sizeof(type_str), "%d", type); pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, - YPACKET_STATUS_DEFAULT, 0); + YPACKET_STATUS_DEFAULT, 0); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 5, who); yahoo_packet_hash(pkt, 206, type_str); @@ -4515,23 +4744,25 @@ void yahoo_send_picture_update(int id, const char *who, int type) void yahoo_send_picture_checksum(int id, const char *who, int checksum) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; char checksum_str[10]; - if (!yid) + if (!yid) { return; + } yd = yid->yd; snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, - YPACKET_STATUS_DEFAULT, 0); + YPACKET_STATUS_DEFAULT, 0); yahoo_packet_hash(pkt, 1, yd->user); - if (who != 0) + if (who != 0) { yahoo_packet_hash(pkt, 5, who); + } yahoo_packet_hash(pkt, 192, checksum_str); yahoo_packet_hash(pkt, 212, "1"); yahoo_send_packet(yid, pkt, 0); @@ -4542,26 +4773,28 @@ void yahoo_send_picture_checksum(int id, const char *who, int checksum) void yahoo_webcam_close_feed(int id, const char *who) { struct yahoo_input_data *yid = - find_input_by_id_and_webcam_user(id, who); + find_input_by_id_and_webcam_user(id, who); - if (yid) + if (yid) { yahoo_input_close(yid); + } } void yahoo_webcam_get_feed(int id, const char *who) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_data *yd; struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } - /* + /* * add the user to the queue. this is a dirty hack, since * the yahoo server doesn't tell us who's key it's returning, - * we have to just hope that it sends back keys in the same + * we have to just hope that it sends back keys in the same * order that we request them. * The queue is popped in yahoo_process_webcam_key */ @@ -4570,69 +4803,73 @@ void yahoo_webcam_get_feed(int id, const char *who) yd = yid->yd; pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YPACKET_STATUS_DEFAULT, - yd->session_id); + yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); - if (who != NULL) + if (who != NULL) { yahoo_packet_hash(pkt, 5, who); + } yahoo_send_packet(yid, pkt, 0); yahoo_packet_free(pkt); } void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length, - unsigned int timestamp) + unsigned int timestamp) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); + find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); unsigned char *packet; unsigned char header_len = 13; unsigned int pos = 0; - if (!yid) + if (!yid) { return; + } packet = y_new0(unsigned char, header_len); packet[pos++] = header_len; packet[pos++] = 0; - packet[pos++] = 5; /* version byte?? */ + packet[pos++] = 5; /* version byte?? */ packet[pos++] = 0; pos += yahoo_put32(packet + pos, length); - packet[pos++] = 2; /* packet type, image */ + packet[pos++] = 2; /* packet type, image */ pos += yahoo_put32(packet + pos, timestamp); yahoo_add_to_send_queue(yid, packet, header_len); FREE(packet); - if (length) + if (length) { yahoo_add_to_send_queue(yid, image, length); + } } void yahoo_webcam_accept_viewer(int id, const char *who, int accept) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); + find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); char *packet = NULL; char *data = NULL; unsigned char header_len = 13; unsigned int pos = 0; unsigned int len = 0; - if (!yid) + if (!yid) { return; + } data = strdup("u="); - data = y_string_append(data, (char *)who); + data = y_string_append(data, (char *) who); data = y_string_append(data, "\r\n"); len = strlen(data); packet = y_new0(char, header_len + len); packet[pos++] = header_len; packet[pos++] = 0; - packet[pos++] = 5; /* version byte?? */ + packet[pos++] = 5; /* version byte?? */ packet[pos++] = 0; pos += yahoo_put32(packet + pos, len); - packet[pos++] = 0; /* packet type */ + packet[pos++] = 0; /* packet type */ pos += yahoo_put32(packet + pos, accept); memcpy(packet + pos, data, len); FREE(data); @@ -4643,14 +4880,15 @@ void yahoo_webcam_accept_viewer(int id, const char *who, int accept) void yahoo_webcam_invite(int id, const char *who) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_packet *pkt; - if (!yid) + if (!yid) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, - yid->yd->session_id); + yid->yd->session_id); yahoo_packet_hash(pkt, 49, "WEBCAMINVITE"); yahoo_packet_hash(pkt, 14, " "); @@ -4663,7 +4901,7 @@ void yahoo_webcam_invite(int id, const char *who) } static void yahoo_search_internal(int id, int t, const char *text, int g, - int ar, int photo, int yahoo_only, int startpos, int total) + int ar, int photo, int yahoo_only, int startpos, int total) { struct yahoo_data *yd = find_conn_by_id(id); struct yahoo_input_data *yid; @@ -4671,8 +4909,9 @@ static void yahoo_search_internal(int id, int t, const char *text, int g, char buff[1024]; char *ctext, *p; - if (!yd) + if (!yd) { return; + } yid = y_new0(struct yahoo_input_data, 1); yid->yd = yd; @@ -4684,16 +4923,17 @@ static void yahoo_search_internal(int id, int t, const char *text, int g, */ snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total, - startpos); + startpos); ctext = strdup(text); - while ((p = strchr(ctext, ' '))) + while ((p = strchr(ctext, ' '))) { *p = '+'; + } snprintf(url, 1024, - "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s", - ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "", - startpos ? buff : ""); + "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s", + ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "", + startpos ? buff : ""); FREE(ctext); @@ -4701,22 +4941,24 @@ static void yahoo_search_internal(int id, int t, const char *text, int g, inputs = y_list_prepend(inputs, yid); yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); + _yahoo_http_connected, yid); } void yahoo_search(int id, enum yahoo_search_type t, const char *text, - enum yahoo_search_gender g, enum yahoo_search_agerange ar, int photo, - int yahoo_only) + enum yahoo_search_gender g, enum yahoo_search_agerange ar, int photo, + int yahoo_only) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_search_state *yss; - if (!yid) + if (!yid) { return; + } - if (!yid->ys) + if (!yid->ys) { yid->ys = y_new0(struct yahoo_search_state, 1); + } yss = yid->ys; @@ -4734,25 +4976,27 @@ void yahoo_search(int id, enum yahoo_search_type t, const char *text, void yahoo_search_again(int id, int start) { struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); + find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); struct yahoo_search_state *yss; - if (!yid || !yid->ys) + if (!yid || !yid->ys) { return; + } yss = yid->ys; - if (start == -1) + if (start == -1) { start = yss->lsearch_nstart + yss->lsearch_nfound; + } yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text, - yss->lsearch_gender, yss->lsearch_agerange, - yss->lsearch_photo, yss->lsearch_yahoo_only, - start, yss->lsearch_ntotal); + yss->lsearch_gender, yss->lsearch_agerange, + yss->lsearch_photo, yss->lsearch_yahoo_only, + start, yss->lsearch_ntotal); } void yahoo_send_picture(int id, const char *name, unsigned long size, - yahoo_get_fd_callback callback, void *data) + yahoo_get_fd_callback callback, void *data) { /* Not Implemented */ } @@ -4795,19 +5039,21 @@ static char *yahoo_get_random(void) out[24] = '\0'; out[23] = '$'; out[22] = '$'; - + for (i = 0; i < 22; i++) { - if(r == 0) + if (r == 0) { r = rand(); + } - c = r%61; + c = r % 61; - if(c<26) + if (c < 26) { out[i] = c + 'a'; - else if (c<52) + } else if (c < 52) { out[i] = c - 26 + 'A'; - else + } else { out[i] = c - 52 + '0'; + } r /= 61; } @@ -4818,36 +5064,39 @@ static char *yahoo_get_random(void) static int _are_same_id(const void *sfd1, const void *id) { - return strcmp(((struct send_file_data *)sfd1)->id, (char *)id); + return strcmp(((struct send_file_data *) sfd1)->id, (char *) id); } static int _are_same_yid(const void *sfd1, const void *yid) { - if(((struct send_file_data *)sfd1)->yid == yid) + if (((struct send_file_data *) sfd1)->yid == yid) { return 0; - else + } else { return 1; + } } static struct send_file_data *yahoo_get_active_transfer(char *id) { YList *l = y_list_find_custom(active_file_transfers, id, - _are_same_id); + _are_same_id); + + if (l) { + return (struct send_file_data *) l->data; + } - if(l) - return (struct send_file_data *)l->data; - return NULL; } static struct send_file_data *yahoo_get_active_transfer_with_yid(void *yid) { YList *l = y_list_find_custom(active_file_transfers, yid, - _are_same_yid); + _are_same_yid); + + if (l) { + return (struct send_file_data *) l->data; + } - if(l) - return (struct send_file_data *)l->data; - return NULL; } @@ -4858,9 +5107,10 @@ static void yahoo_add_active_transfer(struct send_file_data *sfd) static void yahoo_remove_active_transfer(struct send_file_data *sfd) { - if (sfd == NULL) + if (sfd == NULL) { return; - + } + active_file_transfers = y_list_remove(active_file_transfers, sfd); free(sfd->id); free(sfd->who); @@ -4884,12 +5134,12 @@ static void _yahoo_ft_upload_connected(int id, void *fd, int error, void *data) yid->fd = fd; yid->read_tag = - YAHOO_CALLBACK(ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); + YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, + YAHOO_INPUT_READ, yid); } static void yahoo_file_transfer_upload(struct yahoo_data *yd, - struct send_file_data *sfd) + struct send_file_data *sfd) { char url[256]; char buff[4096]; @@ -4908,14 +5158,14 @@ static void yahoo_file_transfer_upload(struct yahoo_data *yd, sender_enc = yahoo_urlencode(yd->user); recv_enc = yahoo_urlencode(sfd->who); - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); snprintf(buff, sizeof(buff), "T=%s; Y=%s", yd->cookie_t, yd->cookie_y); yahoo_http_post(yd->client_id, url, buff, sfd->size, - _yahoo_ft_upload_connected, sfd); + _yahoo_ft_upload_connected, sfd); FREE(token_enc); FREE(sender_enc); @@ -4923,7 +5173,7 @@ static void yahoo_file_transfer_upload(struct yahoo_data *yd, } static void yahoo_init_ft_recv(struct yahoo_data *yd, - struct send_file_data *sfd) + struct send_file_data *sfd) { char url[256]; char buff[1024]; @@ -4942,14 +5192,14 @@ static void yahoo_init_ft_recv(struct yahoo_data *yd, sender_enc = yahoo_urlencode(sfd->who); recv_enc = yahoo_urlencode(yd->user); - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); yahoo_http_head(yid->yd->client_id, url, buff, 0, NULL, - _yahoo_http_connected, yid); + _yahoo_http_connected, yid); FREE(token_enc); FREE(sender_enc); @@ -4957,12 +5207,12 @@ static void yahoo_init_ft_recv(struct yahoo_data *yd, } static void yahoo_file_transfer_accept(struct yahoo_input_data *yid, - struct send_file_data *sfd) + struct send_file_data *sfd) { struct yahoo_packet *pkt; pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, - YPACKET_STATUS_DEFAULT, yid->yd->session_id); + YPACKET_STATUS_DEFAULT, yid->yd->session_id); yahoo_packet_hash(pkt, 1, yid->yd->user); yahoo_packet_hash(pkt, 5, sfd->who); @@ -4979,7 +5229,7 @@ static void yahoo_file_transfer_accept(struct yahoo_input_data *yid, } static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; struct send_file_data *sfd; @@ -5015,18 +5265,17 @@ static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, sfd->token = strdup(token); yahoo_file_transfer_upload(yid->yd, sfd); - } - else { - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, - sfd ? sfd->data : NULL); + } else { + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, + sfd ? sfd->data : NULL); yahoo_remove_active_transfer(sfd); } } static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; char *id = NULL; @@ -5069,28 +5318,27 @@ static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, sfd->ip_addr = strdup(ip_addr); yahoo_file_transfer_accept(yid, sfd); - } - else { - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, - sfd ? sfd->data : NULL); + } else { + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, + sfd ? sfd->data : NULL); yahoo_remove_active_transfer(sfd); } } static void yahoo_send_filetransferinfo(struct yahoo_data *yd, - struct send_file_data *sfd) + struct send_file_data *sfd) { struct yahoo_input_data *yid; struct yahoo_packet *pkt; yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER); - sfd->ip_addr = YAHOO_CALLBACK(ext_yahoo_get_ip_addr)("relay.yahoo.com"); + sfd->ip_addr = YAHOO_CALLBACK (ext_yahoo_get_ip_addr)("relay.yahoo.com"); if (!sfd->ip_addr) { - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yd->client_id, YAHOO_FILE_TRANSFER_RELAY, sfd->data); + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yd->client_id, YAHOO_FILE_TRANSFER_RELAY, sfd->data); yahoo_remove_active_transfer(sfd); @@ -5098,7 +5346,7 @@ static void yahoo_send_filetransferinfo(struct yahoo_data *yd, } pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERINFO, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); yahoo_packet_hash(pkt, 1, yd->user); yahoo_packet_hash(pkt, 5, sfd->who); @@ -5113,7 +5361,7 @@ static void yahoo_send_filetransferinfo(struct yahoo_data *yd, } static void yahoo_process_filetransfer(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) + struct yahoo_packet *pkt) { YList *l; char *who = NULL; @@ -5166,29 +5414,27 @@ static void yahoo_process_filetransfer(struct yahoo_input_data *yid, if (action == YAHOO_FILE_TRANSFER_INIT) { /* Received a FT request from buddy */ sfd = y_new0(struct send_file_data, 1); - + sfd->client_id = yd->client_id; sfd->id = strdup(id); sfd->who = strdup(who); sfd->filename = strdup(filename); sfd->size = size; - + yahoo_add_active_transfer(sfd); - YAHOO_CALLBACK(ext_yahoo_got_file) (yd->client_id, yd->user, - who, msg, filename, size, sfd->id); - } - else { + YAHOO_CALLBACK (ext_yahoo_got_file) (yd->client_id, yd->user, + who, msg, filename, size, sfd->id); + } else { /* Response to our request */ sfd = yahoo_get_active_transfer(id); if (sfd && action == YAHOO_FILE_TRANSFER_ACCEPT) { yahoo_send_filetransferinfo(yd, sfd); - } - else if (!sfd || action == YAHOO_FILE_TRANSFER_REJECT) { - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yd->client_id, YAHOO_FILE_TRANSFER_REJECT, - sfd ? sfd->data : NULL); + } else if (!sfd || action == YAHOO_FILE_TRANSFER_REJECT) { + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yd->client_id, YAHOO_FILE_TRANSFER_REJECT, + sfd ? sfd->data : NULL); yahoo_remove_active_transfer(sfd); } @@ -5197,15 +5443,15 @@ static void yahoo_process_filetransfer(struct yahoo_input_data *yid, #if 0 void yahoo_send_file(int id, const char *who, const char *msg, - const char *name, unsigned long size, - yahoo_get_fd_callback callback, void *data) + const char *name, unsigned long size, + yahoo_get_fd_callback callback, void *data) { struct yahoo_packet *pkt = NULL; char size_str[10]; struct yahoo_input_data *yid; struct yahoo_data *yd; struct send_file_data *sfd; - + yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); yd = find_conn_by_id(id); sfd = y_new0(struct send_file_data, 1); @@ -5220,11 +5466,12 @@ void yahoo_send_file(int id, const char *who, const char *msg, yahoo_add_active_transfer(sfd); - if (!yd) + if (!yd) { return; + } pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, - YPACKET_STATUS_DEFAULT, yd->session_id); + YPACKET_STATUS_DEFAULT, yd->session_id); snprintf(size_str, sizeof(size_str), "%ld", size); @@ -5250,7 +5497,7 @@ void yahoo_send_file_transfer_response(int client_id, int response, char *id, vo struct yahoo_packet *pkt = NULL; char resp[2]; struct yahoo_input_data *yid; - + struct send_file_data *sfd = yahoo_get_active_transfer(id); sfd->data = data; @@ -5258,7 +5505,7 @@ void yahoo_send_file_transfer_response(int client_id, int response, char *id, vo yid = find_input_by_id_and_type(client_id, YAHOO_CONNECTION_PAGER); pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, - YPACKET_STATUS_DEFAULT, yid->yd->session_id); + YPACKET_STATUS_DEFAULT, yid->yd->session_id); snprintf(resp, sizeof(resp), "%d", response); @@ -5271,8 +5518,9 @@ void yahoo_send_file_transfer_response(int client_id, int response, char *id, vo yahoo_packet_free(pkt); - if(response == YAHOO_FILE_TRANSFER_REJECT) + if (response == YAHOO_FILE_TRANSFER_REJECT) { yahoo_remove_active_transfer(sfd); + } } #endif @@ -5280,7 +5528,7 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) { struct send_file_data *sfd; struct yahoo_data *yd = yid->yd; - + sfd = yahoo_get_active_transfer_with_yid(yid); if (!sfd) { @@ -5288,14 +5536,15 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) return; } - /* + /* * We want to handle only the complete data with HEAD since we don't * want a situation where both the GET and HEAD are active. * With SEND, we really can't do much with partial response */ - if ((sfd->state == FT_STATE_HEAD || sfd->state == FT_STATE_SEND) - && !over) + if ((sfd->state == FT_STATE_HEAD || sfd->state == FT_STATE_SEND) + && !over) { return; + } if (sfd->state == FT_STATE_HEAD) { /* Do a GET */ @@ -5303,12 +5552,12 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) char buff[1024]; char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; - struct yahoo_input_data *yid_ft = - y_new0(struct yahoo_input_data, 1); - + struct yahoo_input_data *yid_ft = + y_new0(struct yahoo_input_data, 1); + yid_ft->yd = yid->yd; yid_ft->type = YAHOO_CONNECTION_FT; - + inputs = y_list_prepend(inputs, yid_ft); sfd->yid = yid_ft; sfd->state = FT_STATE_RECV; @@ -5316,71 +5565,72 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) token_enc = yahoo_urlencode(sfd->token); sender_enc = yahoo_urlencode(sfd->who); recv_enc = yahoo_urlencode(yd->user); - - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); + + snprintf(url, sizeof(url), + "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, + token_enc, sender_enc, recv_enc); snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, - yd->cookie_t); + yd->cookie_t); yahoo_http_get(yd->client_id, url, buff, 1, 1, - _yahoo_http_connected, yid_ft); + _yahoo_http_connected, yid_ft); FREE(token_enc); FREE(sender_enc); FREE(recv_enc); - } - else if (sfd->state == FT_STATE_RECV || - sfd->state == FT_STATE_RECV_START) { + } else if (sfd->state == FT_STATE_RECV || + sfd->state == FT_STATE_RECV_START) { unsigned char *data_begin = NULL; - if (yid->rxlen == 0) + if (yid->rxlen == 0) { yahoo_remove_active_transfer(sfd); + } if (sfd->state != FT_STATE_RECV_START && - (data_begin = - (unsigned char *)strstr((char *)yid->rxqueue, - "\r\n\r\n"))) { + (data_begin = + (unsigned char *) strstr((char *) yid->rxqueue, + "\r\n\r\n"))) { sfd->state = FT_STATE_RECV_START; - yid->rxlen -= 4+(data_begin-yid->rxqueue)/sizeof(char); + yid->rxlen -= 4 + (data_begin - yid->rxqueue) / sizeof(char); data_begin += 4; - if (yid->rxlen > 0) - YAHOO_CALLBACK(ext_yahoo_got_ft_data) - (yd->client_id, data_begin, - yid->rxlen, sfd->data); + if (yid->rxlen > 0) { + YAHOO_CALLBACK (ext_yahoo_got_ft_data) + (yd->client_id, data_begin, + yid->rxlen, sfd->data); + } + } else if (sfd->state == FT_STATE_RECV_START) { + YAHOO_CALLBACK (ext_yahoo_got_ft_data) (yd->client_id, + yid->rxqueue, yid->rxlen, sfd->data); } - else if (sfd->state == FT_STATE_RECV_START) - YAHOO_CALLBACK(ext_yahoo_got_ft_data) (yd->client_id, - yid->rxqueue, yid->rxlen, sfd->data); FREE(yid->rxqueue); yid->rxqueue = NULL; yid->rxlen = 0; - } - else if (sfd->state == FT_STATE_SEND) { + } else if (sfd->state == FT_STATE_SEND) { /* Sent file completed */ int len = 0; - char *off = strstr((char *)yid->rxqueue, "Content-Length: "); + char *off = strstr((char *) yid->rxqueue, "Content-Length: "); if (off) { off += 16; len = atoi(off); } - if (len < sfd->size) - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yd->client_id, - YAHOO_FILE_TRANSFER_FAILED, sfd->data); - else - YAHOO_CALLBACK(ext_yahoo_file_transfer_done) - (yd->client_id, - YAHOO_FILE_TRANSFER_DONE, sfd->data); + if (len < sfd->size) { + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yd->client_id, + YAHOO_FILE_TRANSFER_FAILED, sfd->data); + } else { + YAHOO_CALLBACK (ext_yahoo_file_transfer_done) + (yd->client_id, + YAHOO_FILE_TRANSFER_DONE, sfd->data); + } yahoo_remove_active_transfer(sfd); } @@ -5392,50 +5642,65 @@ static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) enum yahoo_status yahoo_current_status(int id) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return YAHOO_STATUS_OFFLINE; + } return yd->current_status; } const YList *yahoo_get_buddylist(int id) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return NULL; + } return yd->buddies; } const YList *yahoo_get_ignorelist(int id) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return NULL; + } return yd->ignore; } const YList *yahoo_get_identities(int id) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return NULL; + } return yd->identities; } const char *yahoo_get_cookie(int id, const char *which) { struct yahoo_data *yd = find_conn_by_id(id); - if (!yd) + + if (!yd) { return NULL; - if (!strncasecmp(which, "y", 1)) + } + if (!strncasecmp(which, "y", 1)) { return yd->cookie_y; - if (!strncasecmp(which, "b", 1)) + } + if (!strncasecmp(which, "b", 1)) { return yd->cookie_b; - if (!strncasecmp(which, "t", 1)) + } + if (!strncasecmp(which, "t", 1)) { return yd->cookie_t; - if (!strncasecmp(which, "c", 1)) + } + if (!strncasecmp(which, "c", 1)) { return yd->cookie_c; - if (!strncasecmp(which, "login", 5)) + } + if (!strncasecmp(which, "login", 5)) { return yd->login_cookie; + } return NULL; } #endif diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index a736b05b..8048ef8f 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -34,28 +34,24 @@ #define BYAHOO_DEFAULT_GROUP "Buddies" /* A hack to handle removal of buddies not in the group "Buddies" correctly */ -struct byahoo_buddygroups -{ +struct byahoo_buddygroups { char *buddy; char *group; }; -struct byahoo_data -{ +struct byahoo_data { int y2_id; int current_status; gboolean logged_in; GSList *buddygroups; }; -struct byahoo_input_data -{ +struct byahoo_input_data { int h; void *d; }; -struct byahoo_conf_invitation -{ +struct byahoo_conf_invitation { char *name; struct groupchat *c; int yid; @@ -66,325 +62,321 @@ struct byahoo_conf_invitation static GSList *byahoo_inputs = NULL; static int byahoo_chat_id = 0; -static char *byahoo_strip( const char *in ) +static char *byahoo_strip(const char *in) { int len; - + /* This should get rid of the markup noise at the beginning of the string. */ - while( *in ) - { - if( g_strncasecmp( in, "<font", 5 ) == 0 || - g_strncasecmp( in, "<fade", 5 ) == 0 || - g_strncasecmp( in, "<alt", 4 ) == 0 ) - { - char *s = strchr( in, '>' ); - if( !s ) + while (*in) { + if (g_strncasecmp(in, "<font", 5) == 0 || + g_strncasecmp(in, "<fade", 5) == 0 || + g_strncasecmp(in, "<alt", 4) == 0) { + char *s = strchr(in, '>'); + if (!s) { break; - + } + in = s + 1; - } - else if( strncmp( in, "\e[", 2 ) == 0 ) - { + } else if (strncmp(in, "\e[", 2) == 0) { const char *s; - - for( s = in + 2; *s && *s != 'm'; s ++ ); - - if( *s != 'm' ) + + for (s = in + 2; *s && *s != 'm'; s++) { + ; + } + + if (*s != 'm') { break; - + } + in = s + 1; - } - else - { + } else { break; } } - + /* This is supposed to get rid of the noise at the end of the line. */ - len = strlen( in ); - while( len > 0 && ( in[len-1] == '>' || in[len-1] == 'm' ) ) - { + len = strlen(in); + while (len > 0 && (in[len - 1] == '>' || in[len - 1] == 'm')) { int blen = len; const char *search; - - if( in[len-1] == '>' ) + + if (in[len - 1] == '>') { search = "</"; - else + } else { search = "\e["; - + } + len -= 3; - while( len > 0 && strncmp( in + len, search, 2 ) != 0 ) - len --; - - if( len <= 0 && strncmp( in, search, 2 ) != 0 ) - { + while (len > 0 && strncmp(in + len, search, 2) != 0) { + len--; + } + + if (len <= 0 && strncmp(in, search, 2) != 0) { len = blen; break; } } - - return( g_strndup( in, len ) ); + + return(g_strndup(in, len)); } -static void byahoo_init( account_t *acc ) +static void byahoo_init(account_t *acc) { - set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); - + set_add(&acc->set, "mail_notifications", "false", set_eval_bool, acc); + acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE; } -static void byahoo_login( account_t *acc ) +static void byahoo_login(account_t *acc) { - struct im_connection *ic = imcb_new( acc ); - struct byahoo_data *yd = ic->proto_data = g_new0( struct byahoo_data, 1 ); + struct im_connection *ic = imcb_new(acc); + struct byahoo_data *yd = ic->proto_data = g_new0(struct byahoo_data, 1); char *s; - + yd->logged_in = FALSE; yd->current_status = YAHOO_STATUS_AVAILABLE; - - if( ( s = strchr( acc->user, '@' ) ) && g_strcasecmp( s, "@yahoo.com" ) == 0 ) - imcb_error( ic, "Your Yahoo! username should just be a username. " - "Do not include any @domain part." ); - - imcb_log( ic, "Connecting" ); - yd->y2_id = yahoo_init( acc->user, acc->pass ); - yahoo_login( yd->y2_id, yd->current_status ); + + if ((s = strchr(acc->user, '@')) && g_strcasecmp(s, "@yahoo.com") == 0) { + imcb_error(ic, "Your Yahoo! username should just be a username. " + "Do not include any @domain part."); + } + + imcb_log(ic, "Connecting"); + yd->y2_id = yahoo_init(acc->user, acc->pass); + yahoo_login(yd->y2_id, yd->current_status); } -static void byahoo_logout( struct im_connection *ic ) +static void byahoo_logout(struct im_connection *ic) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; GSList *l; - - while( ic->groupchats ) - imcb_chat_free( ic->groupchats->data ); - - for( l = yd->buddygroups; l; l = l->next ) - { + + while (ic->groupchats) { + imcb_chat_free(ic->groupchats->data); + } + + for (l = yd->buddygroups; l; l = l->next) { struct byahoo_buddygroups *bg = l->data; - - g_free( bg->buddy ); - g_free( bg->group ); - g_free( bg ); + + g_free(bg->buddy); + g_free(bg->group); + g_free(bg); } - g_slist_free( yd->buddygroups ); - - yahoo_logoff( yd->y2_id ); - - g_free( yd ); + g_slist_free(yd->buddygroups); + + yahoo_logoff(yd->y2_id); + + g_free(yd); } -static void byahoo_get_info(struct im_connection *ic, char *who) +static void byahoo_get_info(struct im_connection *ic, char *who) { /* Just make an URL and let the user fetch the info */ - imcb_log(ic, "%s\n%s: %s%s", _("User Info"), - _("For now, fetch yourself"), yahoo_get_profile_url(), - who); + imcb_log(ic, "%s\n%s: %s%s", _("User Info"), + _("For now, fetch yourself"), yahoo_get_profile_url(), + who); } -static int byahoo_buddy_msg( struct im_connection *ic, char *who, char *what, int flags ) +static int byahoo_buddy_msg(struct im_connection *ic, char *who, char *what, int flags) { struct byahoo_data *yd = ic->proto_data; - - yahoo_send_im( yd->y2_id, NULL, who, what, 1, 0 ); - + + yahoo_send_im(yd->y2_id, NULL, who, what, 1, 0); + return 1; } -static int byahoo_send_typing( struct im_connection *ic, char *who, int typing ) +static int byahoo_send_typing(struct im_connection *ic, char *who, int typing) { struct byahoo_data *yd = ic->proto_data; - - yahoo_send_typing( yd->y2_id, NULL, who, ( typing & OPT_TYPING ) != 0 ); - + + yahoo_send_typing(yd->y2_id, NULL, who, (typing & OPT_TYPING) != 0); + return 1; } -static void byahoo_set_away( struct im_connection *ic, char *state, char *msg ) +static void byahoo_set_away(struct im_connection *ic, char *state, char *msg) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - - if( state && msg == NULL ) - { + + if (state && msg == NULL) { /* Use these states only if msg doesn't contain additional info since away messages are only supported with CUSTOM. */ - if( g_strcasecmp( state, "Be Right Back" ) == 0 ) + if (g_strcasecmp(state, "Be Right Back") == 0) { yd->current_status = YAHOO_STATUS_BRB; - else if( g_strcasecmp( state, "Busy" ) == 0 ) + } else if (g_strcasecmp(state, "Busy") == 0) { yd->current_status = YAHOO_STATUS_BUSY; - else if( g_strcasecmp( state, "Not At Home" ) == 0 ) + } else if (g_strcasecmp(state, "Not At Home") == 0) { yd->current_status = YAHOO_STATUS_NOTATHOME; - else if( g_strcasecmp( state, "Not At Desk" ) == 0 ) + } else if (g_strcasecmp(state, "Not At Desk") == 0) { yd->current_status = YAHOO_STATUS_NOTATDESK; - else if( g_strcasecmp( state, "Not In Office" ) == 0 ) + } else if (g_strcasecmp(state, "Not In Office") == 0) { yd->current_status = YAHOO_STATUS_NOTINOFFICE; - else if( g_strcasecmp( state, "On Phone" ) == 0 ) + } else if (g_strcasecmp(state, "On Phone") == 0) { yd->current_status = YAHOO_STATUS_ONPHONE; - else if( g_strcasecmp( state, "On Vacation" ) == 0 ) + } else if (g_strcasecmp(state, "On Vacation") == 0) { yd->current_status = YAHOO_STATUS_ONVACATION; - else if( g_strcasecmp( state, "Out To Lunch" ) == 0 ) + } else if (g_strcasecmp(state, "Out To Lunch") == 0) { yd->current_status = YAHOO_STATUS_OUTTOLUNCH; - else if( g_strcasecmp( state, "Stepped Out" ) == 0 ) + } else if (g_strcasecmp(state, "Stepped Out") == 0) { yd->current_status = YAHOO_STATUS_STEPPEDOUT; - else if( g_strcasecmp( state, "Invisible" ) == 0 ) + } else if (g_strcasecmp(state, "Invisible") == 0) { yd->current_status = YAHOO_STATUS_INVISIBLE; - else + } else { yd->current_status = YAHOO_STATUS_CUSTOM; - } - else if( msg ) + } + } else if (msg) { yd->current_status = YAHOO_STATUS_CUSTOM; - else + } else { yd->current_status = YAHOO_STATUS_AVAILABLE; - - yahoo_set_away( yd->y2_id, yd->current_status, msg, state ? 2 : 0 ); + } + + yahoo_set_away(yd->y2_id, yd->current_status, msg, state ? 2 : 0); } -static GList *byahoo_away_states( struct im_connection *ic ) +static GList *byahoo_away_states(struct im_connection *ic) { static GList *m = NULL; - if( m == NULL ) - { - m = g_list_append( m, "Be Right Back" ); - m = g_list_append( m, "Busy" ); - m = g_list_append( m, "Not At Home" ); - m = g_list_append( m, "Not At Desk" ); - m = g_list_append( m, "Not In Office" ); - m = g_list_append( m, "On Phone" ); - m = g_list_append( m, "On Vacation" ); - m = g_list_append( m, "Out To Lunch" ); - m = g_list_append( m, "Stepped Out" ); - m = g_list_append( m, "Invisible" ); - } - + if (m == NULL) { + m = g_list_append(m, "Be Right Back"); + m = g_list_append(m, "Busy"); + m = g_list_append(m, "Not At Home"); + m = g_list_append(m, "Not At Desk"); + m = g_list_append(m, "Not In Office"); + m = g_list_append(m, "On Phone"); + m = g_list_append(m, "On Vacation"); + m = g_list_append(m, "Out To Lunch"); + m = g_list_append(m, "Stepped Out"); + m = g_list_append(m, "Invisible"); + } + return m; } -static void byahoo_keepalive( struct im_connection *ic ) +static void byahoo_keepalive(struct im_connection *ic) { struct byahoo_data *yd = ic->proto_data; - - yahoo_keepalive( yd->y2_id ); + + yahoo_keepalive(yd->y2_id); } -static void byahoo_add_buddy( struct im_connection *ic, char *who, char *group ) +static void byahoo_add_buddy(struct im_connection *ic, char *who, char *group) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; bee_user_t *bu; - - if( group && ( bu = bee_user_by_handle( ic->bee, ic, who ) ) && bu->group ) - { + + if (group && (bu = bee_user_by_handle(ic->bee, ic, who)) && bu->group) { GSList *bgl; - + /* If the person is in our list already, this is a group change. */ - yahoo_change_buddy_group( yd->y2_id, who, bu->group->name, group ); - + yahoo_change_buddy_group(yd->y2_id, who, bu->group->name, group); + /* No idea how often people have people in multiple groups and BitlBee doesn't currently support this anyway .. but keep this struct up-to-date for now. */ - for( bgl = yd->buddygroups; bgl; bgl = bgl->next ) - { + for (bgl = yd->buddygroups; bgl; bgl = bgl->next) { struct byahoo_buddygroups *bg = bgl->data; - - if( g_strcasecmp( bg->buddy, who ) == 0 && - g_strcasecmp( bg->group, bu->group->name ) == 0 ) - { - g_free( bg->group ); - bg->group = g_strdup( group ); + + if (g_strcasecmp(bg->buddy, who) == 0 && + g_strcasecmp(bg->group, bu->group->name) == 0) { + g_free(bg->group); + bg->group = g_strdup(group); } } + } else { + yahoo_add_buddy(yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP, NULL); } - else - yahoo_add_buddy( yd->y2_id, who, group ? group : BYAHOO_DEFAULT_GROUP, NULL ); } -static void byahoo_remove_buddy( struct im_connection *ic, char *who, char *group ) +static void byahoo_remove_buddy(struct im_connection *ic, char *who, char *group) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; GSList *bgl; - - yahoo_remove_buddy( yd->y2_id, who, BYAHOO_DEFAULT_GROUP ); - - for( bgl = yd->buddygroups; bgl; bgl = bgl->next ) - { + + yahoo_remove_buddy(yd->y2_id, who, BYAHOO_DEFAULT_GROUP); + + for (bgl = yd->buddygroups; bgl; bgl = bgl->next) { struct byahoo_buddygroups *bg = bgl->data; - - if( g_strcasecmp( bg->buddy, who ) == 0 ) - yahoo_remove_buddy( yd->y2_id, who, bg->group ); + + if (g_strcasecmp(bg->buddy, who) == 0) { + yahoo_remove_buddy(yd->y2_id, who, bg->group); + } } } -static void byahoo_chat_msg( struct groupchat *c, char *message, int flags ) +static void byahoo_chat_msg(struct groupchat *c, char *message, int flags) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; - - yahoo_conference_message( yd->y2_id, NULL, c->data, c->title, message, 1 ); + + yahoo_conference_message(yd->y2_id, NULL, c->data, c->title, message, 1); } -static void byahoo_chat_invite( struct groupchat *c, char *who, char *msg ) +static void byahoo_chat_invite(struct groupchat *c, char *who, char *msg) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; - - yahoo_conference_invite( yd->y2_id, NULL, c->data, c->title, msg ? msg : "" ); + + yahoo_conference_invite(yd->y2_id, NULL, c->data, c->title, msg ? msg : ""); } -static void byahoo_chat_leave( struct groupchat *c ) +static void byahoo_chat_leave(struct groupchat *c) { struct byahoo_data *yd = (struct byahoo_data *) c->ic->proto_data; - - yahoo_conference_logoff( yd->y2_id, NULL, c->data, c->title ); - imcb_chat_free( c ); + + yahoo_conference_logoff(yd->y2_id, NULL, c->data, c->title); + imcb_chat_free(c); } -static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who ) +static struct groupchat *byahoo_chat_with(struct im_connection *ic, char *who) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; struct groupchat *c; char *roomname; YList *members; - - roomname = g_strdup_printf( "%s-Bee-%d", ic->acc->user, byahoo_chat_id ); - - c = imcb_chat_new( ic, roomname ); - imcb_chat_add_buddy( c, ic->acc->user ); - + + roomname = g_strdup_printf("%s-Bee-%d", ic->acc->user, byahoo_chat_id); + + c = imcb_chat_new(ic, roomname); + imcb_chat_add_buddy(c, ic->acc->user); + /* FIXME: Free this thing when the chat's destroyed. We can't *always* do this because it's not always created here. */ - c->data = members = g_new0( YList, 1 ); - members->data = g_strdup( who ); - - yahoo_conference_invite( yd->y2_id, NULL, members, roomname, "Please join my groupchat..." ); - - g_free( roomname ); - + c->data = members = g_new0(YList, 1); + members->data = g_strdup(who); + + yahoo_conference_invite(yd->y2_id, NULL, members, roomname, "Please join my groupchat..."); + + g_free(roomname); + return c; } -static void byahoo_auth_allow( struct im_connection *ic, const char *who ) +static void byahoo_auth_allow(struct im_connection *ic, const char *who) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - - yahoo_confirm_buddy( yd->y2_id, who, 0, "" ); + + yahoo_confirm_buddy(yd->y2_id, who, 0, ""); } -static void byahoo_auth_deny( struct im_connection *ic, const char *who ) +static void byahoo_auth_deny(struct im_connection *ic, const char *who) { struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; - - yahoo_confirm_buddy( yd->y2_id, who, 1, "" ); + + yahoo_confirm_buddy(yd->y2_id, who, 1, ""); } -void byahoo_initmodule( ) +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->mms = 832; /* this guess taken from libotr UPGRADING file */ ret->init = byahoo_init; - + ret->login = byahoo_login; ret->keepalive = byahoo_keepalive; ret->logout = byahoo_logout; - + ret->buddy_msg = byahoo_buddy_msg; ret->get_info = byahoo_get_info; ret->away_states = byahoo_away_states; @@ -392,204 +384,196 @@ void byahoo_initmodule( ) ret->add_buddy = byahoo_add_buddy; ret->remove_buddy = byahoo_remove_buddy; ret->send_typing = byahoo_send_typing; - + ret->chat_msg = byahoo_chat_msg; ret->chat_invite = byahoo_chat_invite; ret->chat_leave = byahoo_chat_leave; ret->chat_with = byahoo_chat_with; ret->handle_cmp = g_strcasecmp; - + ret->auth_allow = byahoo_auth_allow; ret->auth_deny = byahoo_auth_deny; - + register_protocol(ret); } -static struct im_connection *byahoo_get_ic_by_id( int id ) +static struct im_connection *byahoo_get_ic_by_id(int id) { GSList *l; struct im_connection *ic; struct byahoo_data *yd; - - for( l = get_connections(); l; l = l->next ) - { + + for (l = get_connections(); l; l = l->next) { ic = l->data; yd = ic->proto_data; - - if( strcmp( ic->acc->prpl->name, "yahoo" ) == 0 && yd->y2_id == id ) - return( ic ); + + if (strcmp(ic->acc->prpl->name, "yahoo") == 0 && yd->y2_id == id) { + return(ic); + } } - - return( NULL ); + + return(NULL); } /* Now it's callback time! */ -struct byahoo_connect_callback_data -{ +struct byahoo_connect_callback_data { int fd; yahoo_connect_callback callback; gpointer data; int id; }; -void byahoo_connect_callback( gpointer data, gint source, b_input_condition cond ) +void byahoo_connect_callback(gpointer data, gint source, b_input_condition cond) { struct byahoo_connect_callback_data *d = data; - - if( !byahoo_get_ic_by_id( d->id ) ) - { - g_free( d ); + + if (!byahoo_get_ic_by_id(d->id)) { + g_free(d); return; } - - d->callback( NULL + d->fd, 0, d->data ); - g_free( d ); + + d->callback(NULL + d->fd, 0, d->data); + g_free(d); } -struct byahoo_read_ready_data -{ +struct byahoo_read_ready_data { int id; int fd; int tag; gpointer data; }; -gboolean byahoo_read_ready_callback( gpointer data, gint source, b_input_condition cond ) +gboolean byahoo_read_ready_callback(gpointer data, gint source, b_input_condition cond) { struct byahoo_read_ready_data *d = data; - - if( !byahoo_get_ic_by_id( d->id ) ) + + if (!byahoo_get_ic_by_id(d->id)) { /* WTF doesn't libyahoo clean this up? */ return FALSE; - - yahoo_read_ready( d->id, NULL + d->fd, d->data ); - + } + + yahoo_read_ready(d->id, NULL + d->fd, d->data); + return TRUE; } -struct byahoo_write_ready_data -{ +struct byahoo_write_ready_data { int id; int fd; int tag; gpointer data; }; -gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condition cond ) +gboolean byahoo_write_ready_callback(gpointer data, gint source, b_input_condition cond) { struct byahoo_write_ready_data *d = data; - - return yahoo_write_ready( d->id, NULL + d->fd, d->data ); + + return yahoo_write_ready(d->id, NULL + d->fd, d->data); } -void ext_yahoo_login_response( int id, int succ, const char *url ) +void ext_yahoo_login_response(int id, int succ, const char *url) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id(id); struct byahoo_data *yd = NULL; - - if( ic == NULL ) - { + + if (ic == NULL) { /* libyahoo2 seems to call this one twice when something went wrong sometimes. Don't know why. Because we clean up the connection on the first failure, the second should be ignored. */ - + return; } - + yd = (struct byahoo_data *) ic->proto_data; - - if( succ == YAHOO_LOGIN_OK ) - { - imcb_connected( ic ); - + + if (succ == YAHOO_LOGIN_OK) { + imcb_connected(ic); + yd->logged_in = TRUE; - } - else - { + } else { char *errstr; int allow_reconnect = FALSE; - + yd->logged_in = FALSE; - - if( succ == YAHOO_LOGIN_UNAME ) + + if (succ == YAHOO_LOGIN_UNAME) { errstr = "Incorrect Yahoo! username"; - else if( succ == YAHOO_LOGIN_PASSWD ) + } else if (succ == YAHOO_LOGIN_PASSWD) { errstr = "Incorrect Yahoo! password"; - else if( succ == YAHOO_LOGIN_LOCK ) + } else if (succ == YAHOO_LOGIN_LOCK) { errstr = "Yahoo! account locked"; - else if( succ == 1236 ) + } else if (succ == 1236) { errstr = "Yahoo! account locked or machine temporarily banned"; - else if( succ == YAHOO_LOGIN_DUPL ) + } else if (succ == YAHOO_LOGIN_DUPL) { errstr = "Logged in on a different machine or device"; - else if( succ == YAHOO_LOGIN_SOCK ) - { + } else if (succ == YAHOO_LOGIN_SOCK) { errstr = "Socket problem"; allow_reconnect = TRUE; - } - else + } else { errstr = "Unknown error"; - - if( url && *url ) - imcb_error( ic, "Error %d (%s). See %s for more information.", succ, errstr, url ); - else - imcb_error( ic, "Error %d (%s)", succ, errstr ); - - imc_logout( ic, allow_reconnect ); + } + + if (url && *url) { + imcb_error(ic, "Error %d (%s). See %s for more information.", succ, errstr, url); + } else { + imcb_error(ic, "Error %d (%s)", succ, errstr); + } + + imc_logout(ic, allow_reconnect); } } -void ext_yahoo_got_buddies( int id, YList *buds ) +void ext_yahoo_got_buddies(int id, YList *buds) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id(id); struct byahoo_data *yd = ic->proto_data; YList *bl = buds; - - while( bl ) - { + + while (bl) { struct yahoo_buddy *b = bl->data; struct byahoo_buddygroups *bg; - - if( strcmp( b->group, BYAHOO_DEFAULT_GROUP ) != 0 ) - { - bg = g_new0( struct byahoo_buddygroups, 1 ); - - bg->buddy = g_strdup( b->id ); - bg->group = g_strdup( b->group ); - yd->buddygroups = g_slist_append( yd->buddygroups, bg ); + + if (strcmp(b->group, BYAHOO_DEFAULT_GROUP) != 0) { + bg = g_new0(struct byahoo_buddygroups, 1); + + bg->buddy = g_strdup(b->id); + bg->group = g_strdup(b->group); + yd->buddygroups = g_slist_append(yd->buddygroups, bg); } - - imcb_add_buddy( ic, b->id, b->group ); - imcb_rename_buddy( ic, b->id, b->real_name ); - + + imcb_add_buddy(ic, b->id, b->group); + imcb_rename_buddy(ic, b->id, b->real_name); + bl = bl->next; } } -void ext_yahoo_got_identities( int id, YList *ids ) +void ext_yahoo_got_identities(int id, YList *ids) { } -void ext_yahoo_got_cookies( int id ) +void ext_yahoo_got_cookies(int id) { } -void ext_yahoo_status_changed( int id, const char *who, int stat, const char *msg, int away, int idle, int mobile ) +void ext_yahoo_status_changed(int id, const char *who, int stat, const char *msg, int away, int idle, int mobile) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id(id); char *state_string = NULL; int flags = OPT_LOGGED_IN; - - if( away ) + + if (away) { flags |= OPT_AWAY; - if( mobile ) + } + if (mobile) { flags |= OPT_MOBILE; - - switch (stat) - { + } + + switch (stat) { case YAHOO_STATUS_BRB: state_string = "Be Right Back"; break; @@ -631,382 +615,393 @@ void ext_yahoo_status_changed( int id, const char *who, int stat, const char *ms flags = 0; break; } - - imcb_buddy_status( ic, who, flags, state_string, msg ); - - if( stat == YAHOO_STATUS_IDLE ) - imcb_buddy_times( ic, who, 0, idle ); + + imcb_buddy_status(ic, who, flags, state_string, msg); + + if (stat == YAHOO_STATUS_IDLE) { + imcb_buddy_times(ic, who, 0, idle); + } } -void ext_yahoo_got_buzz( int id, const char *me, const char *who, long tm ) +void ext_yahoo_got_buzz(int id, const char *me, const char *who, long tm) { } -void ext_yahoo_got_im( int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8 ) +void ext_yahoo_got_im(int id, const char *me, const char *who, const char *msg, long tm, int stat, int utf8) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id(id); char *m; - - if( msg ) - { - m = byahoo_strip( msg ); - imcb_buddy_msg( ic, (char*) who, (char*) m, 0, 0 ); - g_free( m ); + + if (msg) { + m = byahoo_strip(msg); + imcb_buddy_msg(ic, (char *) who, (char *) m, 0, 0); + g_free(m); } } -void ext_yahoo_got_file( int id, const char *ignored, const char *who, const char *msg, - const char *fname, unsigned long fesize, char *trid ) +void ext_yahoo_got_file(int id, const char *ignored, const char *who, const char *msg, + const char *fname, unsigned long fesize, char *trid) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_log( ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_log(ic, "Got a file transfer (file = %s) from %s. Ignoring for now due to lack of support.", fname, who); } -void ext_yahoo_got_ft_data( int id, const unsigned char *in, int len, void *data ) +void ext_yahoo_got_ft_data(int id, const unsigned char *in, int len, void *data) { } -void ext_yahoo_file_transfer_done( int id, int result, void *data ) +void ext_yahoo_file_transfer_done(int id, int result, void *data) { } -void ext_yahoo_typing_notify( int id, const char *ignored, const char *who, int stat ) +void ext_yahoo_typing_notify(int id, const char *ignored, const char *who, int stat) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - if( stat == 1 ) - imcb_buddy_typing( ic, (char*) who, OPT_TYPING ); - else - imcb_buddy_typing( ic, (char*) who, 0 ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + if (stat == 1) { + imcb_buddy_typing(ic, (char *) who, OPT_TYPING); + } else { + imcb_buddy_typing(ic, (char *) who, 0); + } } -void ext_yahoo_system_message( int id, const char *me, const char *who, const char *msg ) +void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_log( ic, "Yahoo! system message: %s", msg ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_log(ic, "Yahoo! system message: %s", msg); } -void ext_yahoo_webcam_invite( int id, const char *ignored, const char *from ) +void ext_yahoo_webcam_invite(int id, const char *ignored, const char *from) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_log( ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_log(ic, "Got a webcam invitation from %s. IRC+webcams is a no-no though...", from); } -void ext_yahoo_error( int id, const char *err, int fatal, int num ) +void ext_yahoo_error(int id, const char *err, int fatal, int num) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_error( ic, "%s", err ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_error(ic, "%s", err); } /* TODO: Clear up the mess of inp and d structures */ -int ext_yahoo_add_handler( int id, void *fd_, yahoo_input_condition cond, void *data ) +int ext_yahoo_add_handler(int id, void *fd_, yahoo_input_condition cond, void *data) { - struct byahoo_input_data *inp = g_new0( struct byahoo_input_data, 1 ); + struct byahoo_input_data *inp = g_new0(struct byahoo_input_data, 1); int fd = (long) fd_; - - if( cond == YAHOO_INPUT_READ ) - { - struct byahoo_read_ready_data *d = g_new0( struct byahoo_read_ready_data, 1 ); - + + if (cond == YAHOO_INPUT_READ) { + struct byahoo_read_ready_data *d = g_new0(struct byahoo_read_ready_data, 1); + d->id = id; d->fd = fd; d->data = data; - + inp->d = d; - d->tag = inp->h = b_input_add( fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback, (gpointer) d ); - } - else if( cond == YAHOO_INPUT_WRITE ) - { - struct byahoo_write_ready_data *d = g_new0( struct byahoo_write_ready_data, 1 ); - + d->tag = inp->h = b_input_add(fd, B_EV_IO_READ, (b_event_handler) byahoo_read_ready_callback, + (gpointer) d); + } else if (cond == YAHOO_INPUT_WRITE) { + struct byahoo_write_ready_data *d = g_new0(struct byahoo_write_ready_data, 1); + d->id = id; d->fd = fd; d->data = data; - + inp->d = d; - d->tag = inp->h = b_input_add( fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback, (gpointer) d ); - } - else - { - g_free( inp ); + d->tag = inp->h = + b_input_add(fd, B_EV_IO_WRITE, (b_event_handler) byahoo_write_ready_callback, + (gpointer) d); + } else { + g_free(inp); return -1; /* Panic... */ } - - byahoo_inputs = g_slist_append( byahoo_inputs, inp ); + + byahoo_inputs = g_slist_append(byahoo_inputs, inp); return inp->h; } -void ext_yahoo_remove_handler( int id, int tag ) +void ext_yahoo_remove_handler(int id, int tag) { struct byahoo_input_data *inp; GSList *l = byahoo_inputs; - - while( l ) - { + + while (l) { inp = l->data; - if( inp->h == tag ) - { - g_free( inp->d ); - g_free( inp ); - byahoo_inputs = g_slist_remove( byahoo_inputs, inp ); + if (inp->h == tag) { + g_free(inp->d); + g_free(inp); + byahoo_inputs = g_slist_remove(byahoo_inputs, inp); break; } l = l->next; } - - b_event_remove( tag ); + + b_event_remove(tag); } -int ext_yahoo_connect_async( int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl ) +int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data, + int use_ssl) { struct byahoo_connect_callback_data *d; int fd; - - d = g_new0( struct byahoo_connect_callback_data, 1 ); - if( ( fd = proxy_connect( host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d ) ) < 0 ) - { - g_free( d ); - return( fd ); + + d = g_new0(struct byahoo_connect_callback_data, 1); + if ((fd = proxy_connect(host, port, (b_event_handler) byahoo_connect_callback, (gpointer) d)) < 0) { + g_free(d); + return(fd); } d->fd = fd; d->callback = callback; d->data = data; d->id = id; - + return fd; } -char *ext_yahoo_get_ip_addr( const char *domain ) +char *ext_yahoo_get_ip_addr(const char *domain) { return NULL; } -int ext_yahoo_write( void *fd, char *buf, int len ) +int ext_yahoo_write(void *fd, char *buf, int len) { - return write( (long) fd, buf, len ); + return write((long) fd, buf, len); } -int ext_yahoo_read( void *fd, char *buf, int len ) +int ext_yahoo_read(void *fd, char *buf, int len) { - return read( (long) fd, buf, len ); + return read((long) fd, buf, len); } -void ext_yahoo_close( void *fd ) +void ext_yahoo_close(void *fd) { - close( (long) fd ); + close((long) fd); } -void ext_yahoo_got_buddy_change_group( int id, const char *me, const char *who, - const char *old_group, const char *new_group ) +void ext_yahoo_got_buddy_change_group(int id, const char *me, const char *who, + const char *old_group, const char *new_group) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_add_buddy( ic, who, new_group ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_add_buddy(ic, who, new_group); } -static void byahoo_accept_conf( void *data ) +static void byahoo_accept_conf(void *data) { struct byahoo_conf_invitation *inv = data; struct groupchat *b = NULL; GSList *l; - - for( l = inv->ic->groupchats; l; l = l->next ) - { + + for (l = inv->ic->groupchats; l; l = l->next) { b = l->data; - if( b == inv->c ) + if (b == inv->c) { break; + } } - - if( b != NULL ) - { - yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); - imcb_chat_add_buddy( inv->c, inv->ic->acc->user ); - } - else - { - imcb_log( inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name ); + + if (b != NULL) { + yahoo_conference_logon(inv->yid, NULL, inv->members, inv->name); + imcb_chat_add_buddy(inv->c, inv->ic->acc->user); + } else { + imcb_log(inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name); } - - g_free( inv->name ); - g_free( inv ); + + g_free(inv->name); + g_free(inv); } -static void byahoo_reject_conf( void *data ) +static void byahoo_reject_conf(void *data) { struct byahoo_conf_invitation *inv = data; - - yahoo_conference_decline( inv->yid, NULL, inv->members, inv->name, "User rejected groupchat" ); - imcb_chat_free( inv->c ); - g_free( inv->name ); - g_free( inv ); + + yahoo_conference_decline(inv->yid, NULL, inv->members, inv->name, "User rejected groupchat"); + imcb_chat_free(inv->c); + g_free(inv->name); + g_free(inv); } -void ext_yahoo_got_conf_invite( int id, const char *ignored, - const char *who, const char *room, const char *msg, YList *members ) +void ext_yahoo_got_conf_invite(int id, const char *ignored, + const char *who, const char *room, const char *msg, YList *members) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); + struct im_connection *ic = byahoo_get_ic_by_id(id); struct byahoo_conf_invitation *inv; char txt[1024]; YList *m; - - if( g_strcasecmp( who, ic->acc->user ) == 0 ) + + if (g_strcasecmp(who, ic->acc->user) == 0) { /* WTF, Yahoo! seems to echo these now? */ return; - - inv = g_malloc( sizeof( struct byahoo_conf_invitation ) ); - memset( inv, 0, sizeof( struct byahoo_conf_invitation ) ); - inv->name = g_strdup( room ); - inv->c = imcb_chat_new( ic, (char*) room ); + } + + inv = g_malloc(sizeof(struct byahoo_conf_invitation)); + memset(inv, 0, sizeof(struct byahoo_conf_invitation)); + inv->name = g_strdup(room); + inv->c = imcb_chat_new(ic, (char *) room); inv->c->data = members; inv->yid = id; inv->members = members; inv->ic = ic; - - for( m = members; m; m = m->next ) - if( g_strcasecmp( m->data, ic->acc->user ) != 0 ) - imcb_chat_add_buddy( inv->c, m->data ); - - g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg ); - - imcb_ask( ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf ); + + for (m = members; m; m = m->next) { + if (g_strcasecmp(m->data, ic->acc->user) != 0) { + imcb_chat_add_buddy(inv->c, m->data); + } + } + + g_snprintf(txt, 1024, "Got an invitation to chatroom %s from %s: %s", room, who, msg); + + imcb_ask(ic, txt, inv, byahoo_accept_conf, byahoo_reject_conf); } -void ext_yahoo_conf_userdecline( int id, const char *ignored, const char *who, const char *room, const char *msg ) +void ext_yahoo_conf_userdecline(int id, const char *ignored, const char *who, const char *room, const char *msg) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_log( ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_log(ic, "Invite to chatroom %s rejected by %s: %s", room, who, msg); } -void ext_yahoo_conf_userjoin( int id, const char *ignored, const char *who, const char *room ) +void ext_yahoo_conf_userjoin(int id, const char *ignored, const char *who, const char *room) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); - - if( c ) - imcb_chat_add_buddy( c, (char*) who ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + struct groupchat *c = bee_chat_by_title(ic->bee, ic, room); + + if (c) { + imcb_chat_add_buddy(c, (char *) who); + } } -void ext_yahoo_conf_userleave( int id, const char *ignored, const char *who, const char *room ) +void ext_yahoo_conf_userleave(int id, const char *ignored, const char *who, const char *room) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); - - if( c ) - imcb_chat_remove_buddy( c, (char*) who, "" ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + struct groupchat *c = bee_chat_by_title(ic->bee, ic, room); + + if (c) { + imcb_chat_remove_buddy(c, (char *) who, ""); + } } -void ext_yahoo_conf_message( int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8 ) +void ext_yahoo_conf_message(int id, const char *ignored, const char *who, const char *room, const char *msg, int utf8) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - char *m = byahoo_strip( msg ); - struct groupchat *c = bee_chat_by_title( ic->bee, ic, room ); - - if( c ) - imcb_chat_msg( c, (char*) who, (char*) m, 0, 0 ); - g_free( m ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + char *m = byahoo_strip(msg); + struct groupchat *c = bee_chat_by_title(ic->bee, ic, room); + + if (c) { + imcb_chat_msg(c, (char *) who, (char *) m, 0, 0); + } + g_free(m); } -void ext_yahoo_chat_cat_xml( int id, const char *xml ) +void ext_yahoo_chat_cat_xml(int id, const char *xml) { } -void ext_yahoo_chat_join( int id, const char *who, const char *room, const char *topic, YList *members, void *fd ) +void ext_yahoo_chat_join(int id, const char *who, const char *room, const char *topic, YList *members, void *fd) { } -void ext_yahoo_chat_userjoin( int id, const char *me, const char *room, struct yahoo_chat_member *who ) +void ext_yahoo_chat_userjoin(int id, const char *me, const char *room, struct yahoo_chat_member *who) { free(who->id); free(who->alias); free(who->location); - free(who); + free(who); } -void ext_yahoo_chat_userleave( int id, const char *me, const char *room, const char *who ) +void ext_yahoo_chat_userleave(int id, const char *me, const char *room, const char *who) { } -void ext_yahoo_chat_message( int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, int utf8 ) +void ext_yahoo_chat_message(int id, const char *me, const char *who, const char *room, const char *msg, int msgtype, + int utf8) { } -void ext_yahoo_chat_yahoologout( int id, const char *me ) +void ext_yahoo_chat_yahoologout(int id, const char *me) { } -void ext_yahoo_chat_yahooerror( int id, const char *me ) +void ext_yahoo_chat_yahooerror(int id, const char *me) { } -void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg ) +void ext_yahoo_contact_added(int id, const char *myid, const char *who, const char *msg) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - imcb_ask_auth( ic, who, msg ); + struct im_connection *ic = byahoo_get_ic_by_id(id); + + imcb_ask_auth(ic, who, msg); } -void ext_yahoo_rejected( int id, const char *who, const char *msg ) +void ext_yahoo_rejected(int id, const char *who, const char *msg) { } -void ext_yahoo_game_notify( int id, const char *me, const char *who, int stat, const char *msg ) +void ext_yahoo_game_notify(int id, const char *me, const char *who, int stat, const char *msg) { } -void ext_yahoo_mail_notify( int id, const char *from, const char *subj, int cnt ) +void ext_yahoo_mail_notify(int id, const char *from, const char *subj, int cnt) { - struct im_connection *ic = byahoo_get_ic_by_id( id ); - - if( !set_getbool( &ic->acc->set, "mail_notifications" ) ) + struct im_connection *ic = byahoo_get_ic_by_id(id); + + if (!set_getbool(&ic->acc->set, "mail_notifications")) { ; /* The user doesn't care. */ - else if( from && subj ) - imcb_log( ic, "Received e-mail message from %s with subject `%s'", from, subj ); - else if( cnt > 0 ) - imcb_log( ic, "Received %d new e-mails", cnt ); + } else if (from && subj) { + imcb_log(ic, "Received e-mail message from %s with subject `%s'", from, subj); + } else if (cnt > 0) { + imcb_log(ic, "Received %d new e-mails", cnt); + } } -void ext_yahoo_webcam_invite_reply( int id, const char *me, const char *from, int accept ) +void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept) { } -void ext_yahoo_webcam_closed( int id, const char *who, int reason ) +void ext_yahoo_webcam_closed(int id, const char *who, int reason) { } -void ext_yahoo_got_search_result( int id, int found, int start, int total, YList *contacts ) +void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts) { } -void ext_yahoo_webcam_viewer( int id, const char *who, int connect ) +void ext_yahoo_webcam_viewer(int id, const char *who, int connect) { } -void ext_yahoo_webcam_data_request( int id, int send ) +void ext_yahoo_webcam_data_request(int id, int send) { } -int ext_yahoo_log( const char *fmt, ... ) +int ext_yahoo_log(const char *fmt, ...) { - return( 0 ); + return(0); } -void ext_yahoo_got_webcam_image( int id, const char * who, const unsigned char *image, unsigned int image_size, unsigned int real_size, unsigned int timestamp ) +void ext_yahoo_got_webcam_image(int id, const char * who, const unsigned char *image, unsigned int image_size, + unsigned int real_size, unsigned int timestamp) { } -void ext_yahoo_got_ping( int id, const char *msg ) +void ext_yahoo_got_ping(int id, const char *msg) { } -void ext_yahoo_got_buddyicon (int id, const char *me, const char *who, const char *url, int checksum) {} -void ext_yahoo_got_buddyicon_checksum (int id, const char *me,const char *who, int checksum) {} +void ext_yahoo_got_buddyicon(int id, const char *me, const char *who, const char *url, int checksum) +{ +} +void ext_yahoo_got_buddyicon_checksum(int id, const char *me, const char *who, int checksum) +{ +} -void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who){} -void ext_yahoo_buddyicon_uploaded(int id, const char *url){} +void ext_yahoo_got_buddyicon_request(int id, const char *me, const char *who) +{ +} +void ext_yahoo_buddyicon_uploaded(int id, const char *url) +{ +} diff --git a/protocols/yahoo/yahoo2.h b/protocols/yahoo/yahoo2.h index 76180cd6..464672a1 100644 --- a/protocols/yahoo/yahoo2.h +++ b/protocols/yahoo/yahoo2.h @@ -29,34 +29,34 @@ extern "C" { /* *** BitlBee: *** */ #include "bitlbee.h" #undef free -#define free( x ) g_free( x ) +#define free(x) g_free(x) #undef malloc -#define malloc( x ) g_malloc( x ) +#define malloc(x) g_malloc(x) #undef calloc -#define calloc( x, y ) g_calloc( x, y ) +#define calloc(x, y) g_calloc(x, y) #undef realloc -#define realloc( x, y ) g_realloc( x, y ) +#define realloc(x, y) g_realloc(x, y) #undef strdup -#define strdup( x ) g_strdup( x ) +#define strdup(x) g_strdup(x) #undef strndup -#define strndup( x,y ) g_strndup( x,y ) +#define strndup(x, y) g_strndup(x, y) #undef snprintf // #define snprintf( x... ) g_snprintf( x ) #undef strcasecmp -#define strcasecmp( x,y ) g_strcasecmp( x,y ) +#define strcasecmp(x, y) g_strcasecmp(x, y) #undef strncasecmp -#define strncasecmp( x,y,z ) g_strncasecmp( x,y,z ) +#define strncasecmp(x, y, z) g_strncasecmp(x, y, z) #include "yahoo2_types.h" /* returns the socket descriptor object for a given pager connection. shouldn't be needed */ - void *yahoo_get_fd(int id); +void *yahoo_get_fd(int id); /* says how much logging to do */ /* see yahoo2_types.h for the different values */ - int yahoo_set_log_level(enum yahoo_log_level level); - enum yahoo_log_level yahoo_get_log_level(void); +int yahoo_set_log_level(enum yahoo_log_level level); +enum yahoo_log_level yahoo_get_log_level(void); /* these functions should be self explanatory */ /* who always means the buddy you're acting on */ @@ -66,14 +66,14 @@ extern "C" { /* or 0 on failure */ /* you must call init before calling any other function */ /* - * The optional parameters to init are key/value pairs that specify + * The optional parameters to init are key/value pairs that specify * server settings to use. This list must be NULL terminated - even * if the list is empty. If a parameter isn't set, a default value * will be used. Parameter keys are strings, parameter values are * either strings or ints, depending on the key. Values passed in * are copied, so you can use const/auto/static/pointers/whatever * you want. Parameters are: - * NAME TYPE DEFAULT + * NAME TYPE DEFAULT * pager_host char * scs.msg.yahoo.com * pager_port int 5050 * filetransfer_host char * filetransfer.msg.yahoo.com @@ -86,158 +86,158 @@ extern "C" { * * You should set at least local_host if you intend to use webcams */ - int yahoo_init_with_attributes(const char *username, - const char *password, ...); +int yahoo_init_with_attributes(const char *username, + const char *password, ...); /* yahoo_init does the same as yahoo_init_with_attributes, assuming defaults * for all attributes */ - int yahoo_init(const char *username, const char *password); +int yahoo_init(const char *username, const char *password); /* release all resources held by this session */ /* you need to call yahoo_close for a session only if * yahoo_logoff is never called for it (ie, it was never logged in) */ - void yahoo_close(int id); +void yahoo_close(int id); /* login logs in to the server */ /* initial is of type enum yahoo_status. see yahoo2_types.h */ - void yahoo_login(int id, int initial); - void yahoo_logoff(int id); +void yahoo_login(int id, int initial); +void yahoo_logoff(int id); /* reloads status of all buddies */ - void yahoo_refresh(int id); +void yahoo_refresh(int id); /* activates/deactivates an identity */ - void yahoo_set_identity_status(int id, const char *identity, - int active); +void yahoo_set_identity_status(int id, const char *identity, + int active); /* regets the entire buddy list from the server */ - void yahoo_get_list(int id); +void yahoo_get_list(int id); /* download buddy contact information from your yahoo addressbook */ - void yahoo_get_yab(int id); +void yahoo_get_yab(int id); /* add/modify an address book entry. if yab->dbid is set, it will */ /* modify that entry else it creates a new entry */ - void yahoo_set_yab(int id, struct yab *yab); - void yahoo_keepalive(int id); - void yahoo_chat_keepalive(int id); +void yahoo_set_yab(int id, struct yab *yab); +void yahoo_keepalive(int id); +void yahoo_chat_keepalive(int id); /* from is the identity you're sending from. if NULL, the default is used */ /* utf8 is whether msg is a utf8 string or not. */ - void yahoo_send_im(int id, const char *from, const char *who, - const char *msg, int utf8, int picture); +void yahoo_send_im(int id, const char *from, const char *who, + const char *msg, int utf8, int picture); // void yahoo_send_buzz(int id, const char *from, const char *who); /* if type is true, send typing notice, else send stopped typing notice */ - void yahoo_send_typing(int id, const char *from, const char *who, - int typ); +void yahoo_send_typing(int id, const char *from, const char *who, + int typ); /* used to set away/back status. */ /* away says whether the custom message is an away message or a sig */ - void yahoo_set_away(int id, enum yahoo_status state, const char *msg, - int away); - - void yahoo_add_buddy(int id, const char *who, const char *group, - const char *msg); - void yahoo_remove_buddy(int id, const char *who, const char *group); - void yahoo_confirm_buddy(int id, const char *who, int reject, - const char *msg); - void yahoo_stealth_buddy(int id, const char *who, int unstealth); +void yahoo_set_away(int id, enum yahoo_status state, const char *msg, + int away); + +void yahoo_add_buddy(int id, const char *who, const char *group, + const char *msg); +void yahoo_remove_buddy(int id, const char *who, const char *group); +void yahoo_confirm_buddy(int id, const char *who, int reject, + const char *msg); +void yahoo_stealth_buddy(int id, const char *who, int unstealth); /* if unignore is true, unignore, else ignore */ - void yahoo_ignore_buddy(int id, const char *who, int unignore); - void yahoo_change_buddy_group(int id, const char *who, - const char *old_group, const char *new_group); - void yahoo_group_rename(int id, const char *old_group, - const char *new_group); - - void yahoo_conference_invite(int id, const char *from, YList *who, - const char *room, const char *msg); - void yahoo_conference_addinvite(int id, const char *from, - const char *who, const char *room, const YList *members, - const char *msg); - void yahoo_conference_decline(int id, const char *from, YList *who, - const char *room, const char *msg); - void yahoo_conference_message(int id, const char *from, YList *who, - const char *room, const char *msg, int utf8); - void yahoo_conference_logon(int id, const char *from, YList *who, - const char *room); - void yahoo_conference_logoff(int id, const char *from, YList *who, - const char *room); +void yahoo_ignore_buddy(int id, const char *who, int unignore); +void yahoo_change_buddy_group(int id, const char *who, + const char *old_group, const char *new_group); +void yahoo_group_rename(int id, const char *old_group, + const char *new_group); + +void yahoo_conference_invite(int id, const char *from, YList *who, + const char *room, const char *msg); +void yahoo_conference_addinvite(int id, const char *from, + const char *who, const char *room, const YList *members, + const char *msg); +void yahoo_conference_decline(int id, const char *from, YList *who, + const char *room, const char *msg); +void yahoo_conference_message(int id, const char *from, YList *who, + const char *room, const char *msg, int utf8); +void yahoo_conference_logon(int id, const char *from, YList *who, + const char *room); +void yahoo_conference_logoff(int id, const char *from, YList *who, + const char *room); /* Get a list of chatrooms */ - void yahoo_get_chatrooms(int id, int chatroomid); +void yahoo_get_chatrooms(int id, int chatroomid); /* join room with specified roomname and roomid */ - void yahoo_chat_logon(int id, const char *from, const char *room, - const char *roomid); +void yahoo_chat_logon(int id, const char *from, const char *room, + const char *roomid); /* Send message "msg" to room with specified roomname, msgtype is 1-normal message or 2-/me mesage */ - void yahoo_chat_message(int id, const char *from, const char *room, - const char *msg, const int msgtype, const int utf8); +void yahoo_chat_message(int id, const char *from, const char *room, + const char *msg, const int msgtype, const int utf8); /* Log off chat */ - void yahoo_chat_logoff(int id, const char *from); +void yahoo_chat_logoff(int id, const char *from); /* requests a webcam feed */ /* who is the person who's webcam you would like to view */ /* if who is null, then you're the broadcaster */ - void yahoo_webcam_get_feed(int id, const char *who); - void yahoo_webcam_close_feed(int id, const char *who); +void yahoo_webcam_get_feed(int id, const char *who); +void yahoo_webcam_close_feed(int id, const char *who); /* sends an image when uploading */ /* image points to a JPEG-2000 image, length is the length of the image */ /* in bytes. The timestamp is the time in milliseconds since we started the */ /* webcam. */ - void yahoo_webcam_send_image(int id, unsigned char *image, - unsigned int length, unsigned int timestamp); +void yahoo_webcam_send_image(int id, unsigned char *image, + unsigned int length, unsigned int timestamp); /* this function should be called if we want to allow a user to watch the */ /* webcam. Who is the user we want to accept. */ /* Accept user (accept = 1), decline user (accept = 0) */ - void yahoo_webcam_accept_viewer(int id, const char *who, int accept); +void yahoo_webcam_accept_viewer(int id, const char *who, int accept); /* send an invitation to a user to view your webcam */ - void yahoo_webcam_invite(int id, const char *who); +void yahoo_webcam_invite(int id, const char *who); /* will set up a connection and initiate file transfer. * callback will be called with the fd that you should write * the file data to */ - void yahoo_send_file(int id, const char *who, const char *msg, - const char *name, unsigned long size, - yahoo_get_fd_callback callback, void *data); +void yahoo_send_file(int id, const char *who, const char *msg, + const char *name, unsigned long size, + yahoo_get_fd_callback callback, void *data); /* * Respond to a file transfer request. Be sure to provide the callback data * since that is your only chance to recognize future callbacks */ - void yahoo_send_file_transfer_response(int client_id, int response, - char *id, void *data); +void yahoo_send_file_transfer_response(int client_id, int response, + char *id, void *data); /* send a search request */ - void yahoo_search(int id, enum yahoo_search_type t, const char *text, - enum yahoo_search_gender g, enum yahoo_search_agerange ar, - int photo, int yahoo_only); +void yahoo_search(int id, enum yahoo_search_type t, const char *text, + enum yahoo_search_gender g, enum yahoo_search_agerange ar, + int photo, int yahoo_only); /* continue last search * should be called if only (start+found >= total) * * where the above three are passed to ext_yahoo_got_search_result */ - void yahoo_search_again(int id, int start); +void yahoo_search_again(int id, int start); /* these should be called when input is available on a fd */ /* registered by ext_yahoo_add_handler */ /* if these return negative values, errno may be set */ - int yahoo_read_ready(int id, void *fd, void *data); - int yahoo_write_ready(int id, void *fd, void *data); +int yahoo_read_ready(int id, void *fd, void *data); +int yahoo_write_ready(int id, void *fd, void *data); /* utility functions. these do not hit the server */ - enum yahoo_status yahoo_current_status(int id); - const YList *yahoo_get_buddylist(int id); - const YList *yahoo_get_ignorelist(int id); - const YList *yahoo_get_identities(int id); +enum yahoo_status yahoo_current_status(int id); +const YList *yahoo_get_buddylist(int id); +const YList *yahoo_get_ignorelist(int id); +const YList *yahoo_get_identities(int id); /* 'which' could be y, t, c or login. This may change in later versions. */ - const char *yahoo_get_cookie(int id, const char *which); +const char *yahoo_get_cookie(int id, const char *which); /* returns the url used to get user profiles - you must append the user id */ /* as of now this is http://profiles.yahoo.com/ */ /* You'll have to do urlencoding yourself, but see yahoo_httplib.h first */ - const char *yahoo_get_profile_url(void); +const char *yahoo_get_profile_url(void); - void yahoo_buddyicon_request(int id, const char *who); +void yahoo_buddyicon_request(int id, const char *who); #include "yahoo_httplib.h" diff --git a/protocols/yahoo/yahoo2_callbacks.h b/protocols/yahoo/yahoo2_callbacks.h index 4e635cb1..740417ee 100644 --- a/protocols/yahoo/yahoo2_callbacks.h +++ b/protocols/yahoo/yahoo2_callbacks.h @@ -44,17 +44,17 @@ extern "C" { * Callback interface for libyahoo2 */ - typedef enum { - YAHOO_INPUT_READ = 1 << 0, - YAHOO_INPUT_WRITE = 1 << 1, - YAHOO_INPUT_EXCEPTION = 1 << 2 - } yahoo_input_condition; +typedef enum { + YAHOO_INPUT_READ = 1 << 0, + YAHOO_INPUT_WRITE = 1 << 1, + YAHOO_INPUT_EXCEPTION = 1 << 2 +} yahoo_input_condition; /* * A callback function called when an asynchronous connect completes. - * + * * Params: - * fd - The file descriptor object that has been connected, or NULL on + * fd - The file descriptor object that has been connected, or NULL on * error * error - The value of errno set by the call to connect or 0 if no error * Set both fd and error to 0 if the connect was cancelled by the @@ -62,8 +62,8 @@ extern "C" { * callback_data - the callback_data passed to the ext_yahoo_connect_async * function */ - typedef void (*yahoo_connect_callback) (void *fd, int error, - void *callback_data); +typedef void (*yahoo_connect_callback) (void *fd, int error, + void *callback_data); /* * The following functions need to be implemented in the client @@ -71,7 +71,7 @@ extern "C" { * event occurs. */ -/* +/* * should we use a callback structure or directly call functions * if you want the structure, you *must* define USE_STRUCT_CALLBACKS * both when you compile the library, and when you compile your code @@ -79,251 +79,252 @@ extern "C" { */ #ifdef USE_STRUCT_CALLBACKS -#define YAHOO_CALLBACK_TYPE(x) (*x) +#define YAHOO_CALLBACK_TYPE(x) (*x) struct yahoo_callbacks { #else -#define YAHOO_CALLBACK_TYPE(x) x +#define YAHOO_CALLBACK_TYPE(x) x #endif /* * Name: ext_yahoo_login_response - * Called when the login process is complete + * Called when the login process is complete * Params: - * id - the id that identifies the server connection - * succ - enum yahoo_login_status - * url - url to reactivate account if locked + * id - the id that identifies the server connection + * succ - enum yahoo_login_status + * url - url to reactivate account if locked */ void YAHOO_CALLBACK_TYPE(ext_yahoo_login_response) (int id, int succ, - const char *url); + const char *url); /* * Name: ext_yahoo_got_buddies - * Called when the contact list is got from the server + * Called when the contact list is got from the server * Params: - * id - the id that identifies the server connection - * buds - the buddy list + * id - the id that identifies the server connection + * buds - the buddy list */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddies) (int id, YList *buds); /* * Name: ext_yahoo_got_ignore - * Called when the ignore list is got from the server + * Called when the ignore list is got from the server * Params: - * id - the id that identifies the server connection - * igns - the ignore list + * id - the id that identifies the server connection + * igns - the ignore list */ // void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ignore) (int id, YList *igns); /* * Name: ext_yahoo_got_identities - * Called when the contact list is got from the server + * Called when the contact list is got from the server * Params: - * id - the id that identifies the server connection - * ids - the identity list + * id - the id that identifies the server connection + * ids - the identity list */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_identities) (int id, YList *ids); /* * Name: ext_yahoo_got_cookies - * Called when the cookie list is got from the server + * Called when the cookie list is got from the server * Params: - * id - the id that identifies the server connection + * id - the id that identifies the server connection */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_cookies) (int id); /* * Name: ext_yahoo_got_ping - * Called when the ping packet is received from the server + * Called when the ping packet is received from the server * Params: - * id - the id that identifies the server connection + * id - the id that identifies the server connection * errormsg - optional error message */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ping) (int id, - const char *errormsg); + const char *errormsg); /* * Name: ext_yahoo_status_changed - * Called when remote user's status changes. - * Params: - * id - the id that identifies the server connection - * who - the handle of the remote user - * stat - status code (enum yahoo_status) - * msg - the message if stat == YAHOO_STATUS_CUSTOM - * away - whether the contact is away or not (YAHOO_STATUS_CUSTOM) - * idle - this is the number of seconds he is idle [if he is idle] + * Called when remote user's status changes. + * Params: + * id - the id that identifies the server connection + * who - the handle of the remote user + * stat - status code (enum yahoo_status) + * msg - the message if stat == YAHOO_STATUS_CUSTOM + * away - whether the contact is away or not (YAHOO_STATUS_CUSTOM) + * idle - this is the number of seconds he is idle [if he is idle] * mobile - this is set for mobile users/buddies * TODO: add support for pager, chat, and game states */ void YAHOO_CALLBACK_TYPE(ext_yahoo_status_changed) (int id, - const char *who, int stat, const char *msg, int away, int idle, - int mobile); + const char *who, int stat, const char *msg, int away, + int idle, + int mobile); /* * Name: ext_yahoo_got_buzz - * Called when remote user sends you a buzz. + * Called when remote user sends you a buzz. * Params: - * id - the id that identifies the server connection - * me - the identity the message was sent to - * who - the handle of the remote user - * tm - timestamp of message if offline + * id - the id that identifies the server connection + * me - the identity the message was sent to + * who - the handle of the remote user + * tm - timestamp of message if offline */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buzz) (int id, const char *me, - const char *who, long tm); + const char *who, long tm); /* * Name: ext_yahoo_got_im - * Called when remote user sends you a message. - * Params: - * id - the id that identifies the server connection - * me - the identity the message was sent to - * who - the handle of the remote user - * msg - the message - NULL if stat == 2 - * tm - timestamp of message if offline - * stat - message status - 0 - * 1 - * 2 == error sending message - * 5 - * utf8 - whether the message is encoded as utf8 or not + * Called when remote user sends you a message. + * Params: + * id - the id that identifies the server connection + * me - the identity the message was sent to + * who - the handle of the remote user + * msg - the message - NULL if stat == 2 + * tm - timestamp of message if offline + * stat - message status - 0 + * 1 + * 2 == error sending message + * 5 + * utf8 - whether the message is encoded as utf8 or not */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_im) (int id, const char *me, - const char *who, const char *msg, long tm, int stat, int utf8); + const char *who, const char *msg, long tm, int stat, int utf8); /* * Name: ext_yahoo_got_conf_invite - * Called when remote user sends you a conference invitation. + * Called when remote user sends you a conference invitation. * Params: - * id - the id that identifies the server connection - * me - the identity the invitation was sent to - * who - the user inviting you - * room - the room to join - * msg - the message + * id - the id that identifies the server connection + * me - the identity the invitation was sent to + * who - the user inviting you + * room - the room to join + * msg - the message * members - the initial members of the conference (null terminated list) */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_conf_invite) (int id, - const char *me, const char *who, const char *room, - const char *msg, YList *members); + const char *me, const char *who, const char *room, + const char *msg, YList *members); /* * Name: ext_yahoo_conf_userdecline - * Called when someone declines to join the conference. + * Called when someone declines to join the conference. * Params: - * id - the id that identifies the server connection - * me - the identity in the conference - * who - the user who has declined - * room - the room - * msg - the declining message + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has declined + * room - the room + * msg - the declining message */ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userdecline) (int id, - const char *me, const char *who, const char *room, - const char *msg); + const char *me, const char *who, const char *room, + const char *msg); /* * Name: ext_yahoo_conf_userjoin - * Called when someone joins the conference. + * Called when someone joins the conference. * Params: - * id - the id that identifies the server connection - * me - the identity in the conference - * who - the user who has joined - * room - the room joined + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has joined + * room - the room joined */ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userjoin) (int id, - const char *me, const char *who, const char *room); + const char *me, const char *who, const char *room); /* * Name: ext_yahoo_conf_userleave - * Called when someone leaves the conference. + * Called when someone leaves the conference. * Params: - * id - the id that identifies the server connection - * me - the identity in the conference - * who - the user who has left - * room - the room left + * id - the id that identifies the server connection + * me - the identity in the conference + * who - the user who has left + * room - the room left */ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_userleave) (int id, - const char *me, const char *who, const char *room); + const char *me, const char *who, const char *room); /* * Name: ext_yahoo_chat_cat_xml - * Called when ? + * Called when ? * Params: - * id - the id that identifies the server connection - * xml - ? + * id - the id that identifies the server connection + * xml - ? */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_cat_xml) (int id, - const char *xml); + const char *xml); /* * Name: ext_yahoo_chat_join - * Called when joining the chatroom. - * Params: - * id - the id that identifies the server connection - * me - the identity in the chatroom - * room - the room joined, used in all other chat calls, freed by - * library after call - * topic - the topic of the room, freed by library after call - * members - the initial members of the chatroom (null terminated YList + * Called when joining the chatroom. + * Params: + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room joined, used in all other chat calls, freed by + * library after call + * topic - the topic of the room, freed by library after call + * members - the initial members of the chatroom (null terminated YList * of yahoo_chat_member's) Must be freed by the client * fd - the object where the connection is coming from (for tracking) */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_join) (int id, const char *me, - const char *room, const char *topic, YList *members, void *fd); + const char *room, const char *topic, YList *members, void *fd); /* * Name: ext_yahoo_chat_userjoin - * Called when someone joins the chatroom. + * Called when someone joins the chatroom. * Params: - * id - the id that identifies the server connection - * me - the identity in the chatroom - * room - the room joined - * who - the user who has joined, Must be freed by the client + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room joined + * who - the user who has joined, Must be freed by the client */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userjoin) (int id, - const char *me, const char *room, - struct yahoo_chat_member *who); + const char *me, const char *room, + struct yahoo_chat_member *who); /* * Name: ext_yahoo_chat_userleave - * Called when someone leaves the chatroom. + * Called when someone leaves the chatroom. * Params: - * id - the id that identifies the server connection - * me - the identity in the chatroom - * room - the room left - * who - the user who has left (Just the User ID) + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room left + * who - the user who has left (Just the User ID) */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_userleave) (int id, - const char *me, const char *room, const char *who); + const char *me, const char *room, const char *who); /* * Name: ext_yahoo_chat_message - * Called when someone messages in the chatroom. + * Called when someone messages in the chatroom. * Params: - * id - the id that identifies the server connection - * me - the identity in the chatroom - * room - the room - * who - the user who messaged (Just the user id) - * msg - the message - * msgtype - 1 = Normal message - * 2 = /me type message - * utf8 - whether the message is utf8 encoded or not + * id - the id that identifies the server connection + * me - the identity in the chatroom + * room - the room + * who - the user who messaged (Just the user id) + * msg - the message + * msgtype - 1 = Normal message + * 2 = /me type message + * utf8 - whether the message is utf8 encoded or not */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_message) (int id, - const char *me, const char *who, const char *room, - const char *msg, int msgtype, int utf8); + const char *me, const char *who, const char *room, + const char *msg, int msgtype, int utf8); /* * * Name: ext_yahoo_chat_yahoologout * called when yahoo disconnects your chat session * Note this is called whenver a disconnect happens, client or server - * requested. Care should be taken to make sure you know the origin + * requested. Care should be taken to make sure you know the origin * of the disconnect request before doing anything here (auto-join's etc) * Params: * id - the id that identifies this connection - * me - the identity in the chatroom + * me - the identity in the chatroom * Returns: * nothing. */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahoologout) (int id, - const char *me); + const char *me); /* * @@ -331,43 +332,43 @@ struct yahoo_callbacks { * called when yahoo sends back an error to you * Note this is called whenver chat message is sent into a room * in error (fd not connected, room doesn't exists etc) - * Care should be taken to make sure you know the origin + * Care should be taken to make sure you know the origin * of the error before doing anything about it. * Params: * id - the id that identifies this connection - * me - the identity in the chatroom + * me - the identity in the chatroom * Returns: * nothing. */ void YAHOO_CALLBACK_TYPE(ext_yahoo_chat_yahooerror) (int id, - const char *me); + const char *me); /* * Name: ext_yahoo_conf_message - * Called when someone messages in the conference. + * Called when someone messages in the conference. * Params: - * id - the id that identifies the server connection - * me - the identity the conf message was sent to - * who - the user who messaged - * room - the room - * msg - the message - * utf8 - whether the message is utf8 encoded or not + * id - the id that identifies the server connection + * me - the identity the conf message was sent to + * who - the user who messaged + * room - the room + * msg - the message + * utf8 - whether the message is utf8 encoded or not */ void YAHOO_CALLBACK_TYPE(ext_yahoo_conf_message) (int id, - const char *me, const char *who, const char *room, - const char *msg, int utf8); + const char *me, const char *who, const char *room, + const char *msg, int utf8); /* * Name: ext_yahoo_got_file - * Called when someone sends you a file - * Params: - * id - the id that identifies the server connection - * me - the identity the file was sent to - * who - the user who sent the file - * msg - the message - * fname- the file name if direct transfer - * fsize- the file size if direct transfer - * trid - transfer id. Unique for this transfer + * Called when someone sends you a file + * Params: + * id - the id that identifies the server connection + * me - the identity the file was sent to + * who - the user who sent the file + * msg - the message + * fname- the file name if direct transfer + * fsize- the file size if direct transfer + * trid - transfer id. Unique for this transfer * * NOTE: Subsequent callbacks for file transfer do not send all of this * information again since it is wasteful. Implementations are expected to @@ -375,158 +376,159 @@ struct yahoo_callbacks { * confirmation is sent */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file) (int id, const char *me, - const char *who, const char *msg, const char *fname, - unsigned long fesize, char *trid); + const char *who, const char *msg, const char *fname, + unsigned long fesize, char *trid); /* * Name: ext_yahoo_got_ft_data - * Called multiple times when parts of the file are received + * Called multiple times when parts of the file are received * Params: - * id - the id that identifies the server connection - * in - The data - * len - Length of the data - * data - callback data + * id - the id that identifies the server connection + * in - The data + * len - Length of the data + * data - callback data */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_ft_data) (int id, - const unsigned char *in, int len, void *data); + const unsigned char *in, int len, void *data); /* * Name: ext_yahoo_file_transfer_done - * File transfer is done + * File transfer is done * Params: - * id - the id that identifies the server connection - * result - To notify if it finished successfully or with a failure - * data - callback data + * id - the id that identifies the server connection + * result - To notify if it finished successfully or with a failure + * data - callback data */ void YAHOO_CALLBACK_TYPE(ext_yahoo_file_transfer_done) (int id, - int result, void *data); + int result, void *data); /* * Name: ext_yahoo_contact_added - * Called when a contact is added to your list + * Called when a contact is added to your list * Params: - * id - the id that identifies the server connection - * myid - the identity he was added to - * who - who was added - * msg - any message sent + * id - the id that identifies the server connection + * myid - the identity he was added to + * who - who was added + * msg - any message sent */ void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_added) (int id, - const char *myid, const char *who, const char *msg); + const char *myid, const char *who, const char *msg); /* * Name: ext_yahoo_rejected - * Called when a contact rejects your add + * Called when a contact rejects your add * Params: - * id - the id that identifies the server connection - * who - who rejected you - * msg - any message sent + * id - the id that identifies the server connection + * who - who rejected you + * msg - any message sent */ void YAHOO_CALLBACK_TYPE(ext_yahoo_rejected) (int id, const char *who, - const char *msg); + const char *msg); /* * Name: ext_yahoo_typing_notify - * Called when remote user starts or stops typing. + * Called when remote user starts or stops typing. * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the handle of the remote user - * stat - 1 if typing, 0 if stopped typing + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the handle of the remote user + * stat - 1 if typing, 0 if stopped typing */ void YAHOO_CALLBACK_TYPE(ext_yahoo_typing_notify) (int id, - const char *me, const char *who, int stat); + const char *me, const char *who, int stat); /* * Name: ext_yahoo_game_notify - * Called when remote user starts or stops a game. + * Called when remote user starts or stops a game. * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the handle of the remote user - * stat - 1 if game, 0 if stopped gaming - * msg - game description and/or other text + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the handle of the remote user + * stat - 1 if game, 0 if stopped gaming + * msg - game description and/or other text */ void YAHOO_CALLBACK_TYPE(ext_yahoo_game_notify) (int id, const char *me, - const char *who, int stat, const char *msg); + const char *who, int stat, const char *msg); /* * Name: ext_yahoo_mail_notify - * Called when you receive mail, or with number of messages + * Called when you receive mail, or with number of messages * Params: - * id - the id that identifies the server connection - * from - who the mail is from - NULL if only mail count - * subj - the subject of the mail - NULL if only mail count - * cnt - mail count - 0 if new mail notification + * id - the id that identifies the server connection + * from - who the mail is from - NULL if only mail count + * subj - the subject of the mail - NULL if only mail count + * cnt - mail count - 0 if new mail notification */ void YAHOO_CALLBACK_TYPE(ext_yahoo_mail_notify) (int id, - const char *from, const char *subj, int cnt); + const char *from, const char *subj, int cnt); /* * Name: ext_yahoo_system_message - * System message + * System message * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the source of the system message (there are different types) - * msg - the message + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the source of the system message (there are different types) + * msg - the message */ void YAHOO_CALLBACK_TYPE(ext_yahoo_system_message) (int id, - const char *me, const char *who, const char *msg); + const char *me, const char *who, const char *msg); /* * Name: ext_yahoo_got_buddyicon - * Buddy icon received + * Buddy icon received * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the person the buddy icon is for - * url - the url to use to load the icon - * checksum - the checksum of the icon content + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the person the buddy icon is for + * url - the url to use to load the icon + * checksum - the checksum of the icon content */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon) (int id, - const char *me, const char *who, const char *url, int checksum); + const char *me, const char *who, const char *url, + int checksum); /* * Name: ext_yahoo_got_buddyicon_checksum - * Buddy icon checksum received + * Buddy icon checksum received * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the yahoo id of the buddy icon checksum is for - * checksum - the checksum of the icon content + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy icon checksum is for + * checksum - the checksum of the icon content */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_checksum) (int id, - const char *me, const char *who, int checksum); + const char *me, const char *who, int checksum); /* * Name: ext_yahoo_got_buddyicon_request - * Buddy icon request received + * Buddy icon request received * Params: - * id - the id that identifies the server connection - * me - the handle of the identity the notification is sent to - * who - the yahoo id of the buddy that requested the buddy icon + * id - the id that identifies the server connection + * me - the handle of the identity the notification is sent to + * who - the yahoo id of the buddy that requested the buddy icon */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddyicon_request) (int id, - const char *me, const char *who); + const char *me, const char *who); /* * Name: ext_yahoo_got_buddyicon_request - * Buddy icon request received + * Buddy icon request received * Params: - * id - the id that identifies the server connection - * url - remote url, the uploaded buddy icon can be fetched from + * id - the id that identifies the server connection + * url - remote url, the uploaded buddy icon can be fetched from */ void YAHOO_CALLBACK_TYPE(ext_yahoo_buddyicon_uploaded) (int id, - const char *url); + const char *url); /* * Name: ext_yahoo_got_webcam_image - * Called when you get a webcam update + * Called when you get a webcam update * An update can either be receiving an image, a part of an image or * just an update with a timestamp * Params: - * id - the id that identifies the server connection - * who - the user who's webcam we're viewing + * id - the id that identifies the server connection + * who - the user who's webcam we're viewing * image - image data * image_size - length of the image in bytes * real_size - actual length of image data @@ -543,39 +545,39 @@ struct yahoo_callbacks { * a timestamp to stay in sync */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_webcam_image) (int id, - const char *who, const unsigned char *image, - unsigned int image_size, unsigned int real_size, - unsigned int timestamp); + const char *who, const unsigned char *image, + unsigned int image_size, unsigned int real_size, + unsigned int timestamp); /* * Name: ext_yahoo_webcam_invite - * Called when you get a webcam invitation + * Called when you get a webcam invitation * Params: - * id - the id that identifies the server connection - * me - identity the invitation is to - * from - who the invitation is from + * id - the id that identifies the server connection + * me - identity the invitation is to + * from - who the invitation is from */ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite) (int id, - const char *me, const char *from); + const char *me, const char *from); /* * Name: ext_yahoo_webcam_invite_reply - * Called when you get a response to a webcam invitation + * Called when you get a response to a webcam invitation * Params: - * id - the id that identifies the server connection - * me - identity the invitation response is to - * from - who the invitation response is from + * id - the id that identifies the server connection + * me - identity the invitation response is to + * from - who the invitation response is from * accept - 0 (decline), 1 (accept) */ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_invite_reply) (int id, - const char *me, const char *from, int accept); + const char *me, const char *from, int accept); /* * Name: ext_yahoo_webcam_closed - * Called when the webcam connection closed + * Called when the webcam connection closed * Params: - * id - the id that identifies the server connection - * who - the user who we where connected to + * id - the id that identifies the server connection + * who - the user who we where connected to * reason - reason why the connection closed * 1 = user stopped broadcasting * 2 = user cancelled viewing permission @@ -583,34 +585,34 @@ struct yahoo_callbacks { * 4 = user does not have webcam online */ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_closed) (int id, - const char *who, int reason); + const char *who, int reason); /* * Name: ext_yahoo_got_search_result * Called when the search result received from server * Params: - * id - the id that identifies the server connection - * found - total number of results returned in the current result set - * start - offset from where the current result set starts - * total - total number of results available (start + found <= total) - * contacts - the list of results as a YList of yahoo_found_contact - * these will be freed after this function returns, so - * if you need to use the information, make a copy + * id - the id that identifies the server connection + * found - total number of results returned in the current result set + * start - offset from where the current result set starts + * total - total number of results available (start + found <= total) + * contacts - the list of results as a YList of yahoo_found_contact + * these will be freed after this function returns, so + * if you need to use the information, make a copy */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_search_result) (int id, - int found, int start, int total, YList *contacts); + int found, int start, int total, YList *contacts); /* * Name: ext_yahoo_error - * Called on error. + * Called on error. * Params: - * id - the id that identifies the server connection - * err - the error message - * fatal- whether this error is fatal to the connection or not - * num - Which error is this + * id - the id that identifies the server connection + * err - the error message + * fatal- whether this error is fatal to the connection or not + * num - Which error is this */ void YAHOO_CALLBACK_TYPE(ext_yahoo_error) (int id, const char *err, - int fatal, int num); + int fatal, int num); /* * Name: ext_yahoo_webcam_viewer @@ -621,7 +623,7 @@ struct yahoo_callbacks { * connect - 0=disconnect 1=connect 2=request */ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_viewer) (int id, - const char *who, int connect); + const char *who, int connect); /* * Name: ext_yahoo_webcam_data_request @@ -631,137 +633,138 @@ struct yahoo_callbacks { * send - whether to send images or not */ void YAHOO_CALLBACK_TYPE(ext_yahoo_webcam_data_request) (int id, - int send); + int send); /* * Name: ext_yahoo_log - * Called to log a message. + * Called to log a message. * Params: - * fmt - the printf formatted message + * fmt - the printf formatted message * Returns: - * 0 + * 0 */ int YAHOO_CALLBACK_TYPE(ext_yahoo_log) (const char *fmt, ...); /* * Name: ext_yahoo_add_handler - * Add a listener for the fd. Must call yahoo_read_ready - * when a YAHOO_INPUT_READ fd is ready and yahoo_write_ready - * when a YAHOO_INPUT_WRITE fd is ready. - * Params: - * id - the id that identifies the server connection - * fd - the fd object on which to listen - * cond - the condition on which to call the callback - * data - callback data to pass to yahoo_*_ready - * + * Add a listener for the fd. Must call yahoo_read_ready + * when a YAHOO_INPUT_READ fd is ready and yahoo_write_ready + * when a YAHOO_INPUT_WRITE fd is ready. + * Params: + * id - the id that identifies the server connection + * fd - the fd object on which to listen + * cond - the condition on which to call the callback + * data - callback data to pass to yahoo_*_ready + * * Returns: a tag to be used when removing the handler */ int YAHOO_CALLBACK_TYPE(ext_yahoo_add_handler) (int id, void *fd, - yahoo_input_condition cond, void *data); + yahoo_input_condition cond, void *data); /* * Name: ext_yahoo_remove_handler - * Remove the listener for the fd. + * Remove the listener for the fd. * Params: - * id - the id that identifies the connection - * tag - the handler tag to remove + * id - the id that identifies the connection + * tag - the handler tag to remove */ void YAHOO_CALLBACK_TYPE(ext_yahoo_remove_handler) (int id, int tag); /* * Name: ext_yahoo_connect - * Connect to a host:port + * Connect to a host:port * Params: - * host - the host to connect to - * port - the port to connect on + * host - the host to connect to + * port - the port to connect on * Returns: - * a unix file descriptor to the socket + * a unix file descriptor to the socket */ // int YAHOO_CALLBACK_TYPE(ext_yahoo_connect) (const char *host, int port); /* * Name: ext_yahoo_connect_async - * Connect to a host:port asynchronously. This function should return - * immediately returing a tag used to identify the connection handler, - * or a pre-connect error (eg: host name lookup failure). - * Once the connect completes (successfully or unsuccessfully), callback - * should be called (see the signature for yahoo_connect_callback). - * The callback may safely be called before this function returns, but - * it should not be called twice. - * Params: - * id - the id that identifies this connection - * host - the host to connect to - * port - the port to connect on - * callback - function to call when connect completes - * callback_data - data to pass to the callback function - * use_ssl - Whether we need an SSL connection + * Connect to a host:port asynchronously. This function should return + * immediately returing a tag used to identify the connection handler, + * or a pre-connect error (eg: host name lookup failure). + * Once the connect completes (successfully or unsuccessfully), callback + * should be called (see the signature for yahoo_connect_callback). + * The callback may safely be called before this function returns, but + * it should not be called twice. + * Params: + * id - the id that identifies this connection + * host - the host to connect to + * port - the port to connect on + * callback - function to call when connect completes + * callback_data - data to pass to the callback function + * use_ssl - Whether we need an SSL connection * Returns: - * a tag signifying the connection attempt + * a tag signifying the connection attempt */ int YAHOO_CALLBACK_TYPE(ext_yahoo_connect_async) (int id, - const char *host, int port, yahoo_connect_callback callback, - void *callback_data, int use_ssl); + const char *host, int port, yahoo_connect_callback callback, + void *callback_data, int use_ssl); /* * Name: ext_yahoo_get_ip_addr - * get IP Address for a domain name + * get IP Address for a domain name * Params: - * domain - Domain name + * domain - Domain name * Returns: - * Newly allocated string containing the IP Address in IPv4 notation + * Newly allocated string containing the IP Address in IPv4 notation */ char *YAHOO_CALLBACK_TYPE(ext_yahoo_get_ip_addr) (const char *domain); /* * Name: ext_yahoo_write - * Write data from the buffer into the socket for the specified connection + * Write data from the buffer into the socket for the specified connection * Params: - * fd - the file descriptor object that identifies this connection - * buf - Buffer to write the data from - * len - Length of the data + * fd - the file descriptor object that identifies this connection + * buf - Buffer to write the data from + * len - Length of the data * Returns: - * Number of bytes written or -1 for error + * Number of bytes written or -1 for error */ int YAHOO_CALLBACK_TYPE(ext_yahoo_write) (void *fd, char *buf, int len); /* * Name: ext_yahoo_read - * Read data into a buffer from socket for the specified connection + * Read data into a buffer from socket for the specified connection * Params: - * fd - the file descriptor object that identifies this connection - * buf - Buffer to read the data into - * len - Max length to read + * fd - the file descriptor object that identifies this connection + * buf - Buffer to read the data into + * len - Max length to read * Returns: - * Number of bytes read or -1 for error + * Number of bytes read or -1 for error */ int YAHOO_CALLBACK_TYPE(ext_yahoo_read) (void *fd, char *buf, int len); /* * Name: ext_yahoo_close - * Close the file descriptor object and free its resources. Libyahoo2 will not - * use this object again. + * Close the file descriptor object and free its resources. Libyahoo2 will not + * use this object again. * Params: - * fd - the file descriptor object that identifies this connection + * fd - the file descriptor object that identifies this connection * Returns: - * Nothing + * Nothing */ void YAHOO_CALLBACK_TYPE(ext_yahoo_close) (void *fd); /* * Name: ext_yahoo_got_buddy_change_group - * Acknowledgement of buddy changing group + * Acknowledgement of buddy changing group * Params: - * id: client id - * me: The user - * who: Buddy name - * old_group: Old group name - * new_group: New group name + * id: client id + * me: The user + * who: Buddy name + * old_group: Old group name + * new_group: New group name * Returns: - * Nothing + * Nothing */ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_buddy_change_group) (int id, - const char *me, const char *who, const char *old_group, - const char *new_group); + const char *me, const char *who, + const char *old_group, + const char *new_group); #ifdef USE_STRUCT_CALLBACKS }; diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h index 62aa39d1..551670d6 100644 --- a/protocols/yahoo/yahoo2_types.h +++ b/protocols/yahoo/yahoo2_types.h @@ -28,175 +28,175 @@ extern "C" { #endif - enum yahoo_service { /* these are easier to see in hex */ - YAHOO_SERVICE_LOGON = 1, - YAHOO_SERVICE_LOGOFF, - YAHOO_SERVICE_ISAWAY, - YAHOO_SERVICE_ISBACK, - YAHOO_SERVICE_IDLE, /* 5 (placemarker) */ - YAHOO_SERVICE_MESSAGE, - YAHOO_SERVICE_IDACT, - YAHOO_SERVICE_IDDEACT, - YAHOO_SERVICE_MAILSTAT, - YAHOO_SERVICE_USERSTAT, /* 0xa */ - YAHOO_SERVICE_NEWMAIL, - YAHOO_SERVICE_CHATINVITE, - YAHOO_SERVICE_CALENDAR, - YAHOO_SERVICE_NEWPERSONALMAIL, - YAHOO_SERVICE_NEWCONTACT, - YAHOO_SERVICE_ADDIDENT, /* 0x10 */ - YAHOO_SERVICE_ADDIGNORE, - YAHOO_SERVICE_PING, - YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */ - YAHOO_SERVICE_SYSMESSAGE = 0x14, - YAHOO_SERVICE_SKINNAME = 0x15, - YAHOO_SERVICE_PASSTHROUGH2 = 0x16, - YAHOO_SERVICE_CONFINVITE = 0x18, - YAHOO_SERVICE_CONFLOGON, - YAHOO_SERVICE_CONFDECLINE, - YAHOO_SERVICE_CONFLOGOFF, - YAHOO_SERVICE_CONFADDINVITE, - YAHOO_SERVICE_CONFMSG, - YAHOO_SERVICE_CHATLOGON, - YAHOO_SERVICE_CHATLOGOFF, - YAHOO_SERVICE_CHATMSG = 0x20, - YAHOO_SERVICE_GAMELOGON = 0x28, - YAHOO_SERVICE_GAMELOGOFF, - YAHOO_SERVICE_GAMEMSG = 0x2a, - YAHOO_SERVICE_FILETRANSFER = 0x46, - YAHOO_SERVICE_VOICECHAT = 0x4A, - YAHOO_SERVICE_NOTIFY, - YAHOO_SERVICE_VERIFY, - YAHOO_SERVICE_P2PFILEXFER, - YAHOO_SERVICE_PEERTOPEER = 0x4F, /* Checks if P2P possible */ - YAHOO_SERVICE_WEBCAM, - YAHOO_SERVICE_AUTHRESP = 0x54, - YAHOO_SERVICE_LIST, - YAHOO_SERVICE_AUTH = 0x57, - YAHOO_SERVICE_AUTHBUDDY = 0x6d, - YAHOO_SERVICE_ADDBUDDY = 0x83, - YAHOO_SERVICE_REMBUDDY, - YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0 */ - YAHOO_SERVICE_REJECTCONTACT, - YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */ - YAHOO_SERVICE_Y7_PING = 0x8A, - YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1 */ - YAHOO_SERVICE_CHATGOTO, - YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */ - YAHOO_SERVICE_CHATLEAVE, - YAHOO_SERVICE_CHATEXIT = 0x9b, - YAHOO_SERVICE_CHATADDINVITE = 0x9d, - YAHOO_SERVICE_CHATLOGOUT = 0xa0, - YAHOO_SERVICE_CHATPING, - YAHOO_SERVICE_COMMENT = 0xa8, - YAHOO_SERVICE_GAME_INVITE = 0xb7, - YAHOO_SERVICE_STEALTH_PERM = 0xb9, - YAHOO_SERVICE_STEALTH_SESSION = 0xba, - YAHOO_SERVICE_AVATAR = 0xbc, - YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd, - YAHOO_SERVICE_PICTURE = 0xbe, - YAHOO_SERVICE_PICTURE_UPDATE = 0xc1, - YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2, - YAHOO_SERVICE_YAB_UPDATE = 0xc4, - YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5, /* YMSG13, key 13: 2 = invisible, 1 = visible */ - YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6, /* YMSG13 */ - YAHOO_SERVICE_PICTURE_STATUS = 0xc7, /* YMSG13, key 213: 0 = none, 1 = avatar, 2 = picture */ - YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, - YAHOO_SERVICE_AUDIBLE = 0xd0, - YAHOO_SERVICE_Y7_PHOTO_SHARING = 0xd2, - YAHOO_SERVICE_Y7_CONTACT_DETAILS = 0xd3, /* YMSG13 */ - YAHOO_SERVICE_Y7_CHAT_SESSION = 0xd4, - YAHOO_SERVICE_Y7_AUTHORIZATION = 0xd6, /* YMSG13 */ - YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc, /* YMSG13 */ - YAHOO_SERVICE_Y7_FILETRANSFERINFO, /* YMSG13 */ - YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, /* YMSG13 */ - YAHOO_SERVICE_Y7_MINGLE = 0xe1, /* YMSG13 */ - YAHOO_SERVICE_Y7_CHANGE_GROUP = 0xe7, /* YMSG13 */ - YAHOO_SERVICE_MYSTERY = 0xef, /* Don't know what this is for */ - YAHOO_SERVICE_Y8_STATUS = 0xf0, /* YMSG15 */ - YAHOO_SERVICE_Y8_LIST = 0Xf1, /* YMSG15 */ - YAHOO_SERVICE_MESSAGE_CONFIRM = 0xfb, - YAHOO_SERVICE_WEBLOGIN = 0x0226, - YAHOO_SERVICE_SMS_MSG = 0x02ea - }; - - enum yahoo_status { - YAHOO_STATUS_AVAILABLE = 0, - YAHOO_STATUS_BRB, - YAHOO_STATUS_BUSY, - YAHOO_STATUS_NOTATHOME, - YAHOO_STATUS_NOTATDESK, - YAHOO_STATUS_NOTINOFFICE, - YAHOO_STATUS_ONPHONE, - YAHOO_STATUS_ONVACATION, - YAHOO_STATUS_OUTTOLUNCH, - YAHOO_STATUS_STEPPEDOUT, - YAHOO_STATUS_INVISIBLE = 12, - YAHOO_STATUS_CUSTOM = 99, - YAHOO_STATUS_IDLE = 999, - YAHOO_STATUS_OFFLINE = 0x5a55aa56 /* don't ask */ - }; - - enum ypacket_status { - YPACKET_STATUS_DISCONNECTED = -1, - YPACKET_STATUS_DEFAULT = 0, - YPACKET_STATUS_SERVERACK = 1, - YPACKET_STATUS_GAME = 0x2, - YPACKET_STATUS_AWAY = 0x4, - YPACKET_STATUS_CONTINUED = 0x5, - YPACKET_STATUS_INVISIBLE = 12, - YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */ - YPACKET_STATUS_WEBLOGIN = 0x5a55aa55, - YPACKET_STATUS_OFFLINE = 0x5a55aa56 - }; - -#define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */ - - enum yahoo_login_status { - YAHOO_LOGIN_OK = 0, - YAHOO_LOGIN_LOGOFF = 1, - YAHOO_LOGIN_UNAME = 3, - YAHOO_LOGIN_PASSWD = 13, - YAHOO_LOGIN_LOCK = 14, - YAHOO_LOGIN_DUPL = 99, - YAHOO_LOGIN_SOCK = -1, - YAHOO_LOGIN_UNKNOWN = 999 - }; - - enum yahoo_error { - E_UNKNOWN = -1, - E_CONNECTION = -2, - E_SYSTEM = -3, - E_CUSTOM = 0, - - /* responses from ignore buddy */ - E_IGNOREDUP = 2, - E_IGNORENONE = 3, - E_IGNORECONF = 12, - - /* conference */ - E_CONFNOTAVAIL = 20 - }; - - enum yahoo_log_level { - YAHOO_LOG_NONE = 0, - YAHOO_LOG_FATAL, - YAHOO_LOG_ERR, - YAHOO_LOG_WARNING, - YAHOO_LOG_NOTICE, - YAHOO_LOG_INFO, - YAHOO_LOG_DEBUG - }; - - enum yahoo_file_transfer { - YAHOO_FILE_TRANSFER_INIT = 1, - YAHOO_FILE_TRANSFER_ACCEPT = 3, - YAHOO_FILE_TRANSFER_REJECT = 4, - YAHOO_FILE_TRANSFER_DONE = 5, - YAHOO_FILE_TRANSFER_RELAY, - YAHOO_FILE_TRANSFER_FAILED, - YAHOO_FILE_TRANSFER_UNKNOWN - }; +enum yahoo_service { /* these are easier to see in hex */ + YAHOO_SERVICE_LOGON = 1, + YAHOO_SERVICE_LOGOFF, + YAHOO_SERVICE_ISAWAY, + YAHOO_SERVICE_ISBACK, + YAHOO_SERVICE_IDLE, /* 5 (placemarker) */ + YAHOO_SERVICE_MESSAGE, + YAHOO_SERVICE_IDACT, + YAHOO_SERVICE_IDDEACT, + YAHOO_SERVICE_MAILSTAT, + YAHOO_SERVICE_USERSTAT, /* 0xa */ + YAHOO_SERVICE_NEWMAIL, + YAHOO_SERVICE_CHATINVITE, + YAHOO_SERVICE_CALENDAR, + YAHOO_SERVICE_NEWPERSONALMAIL, + YAHOO_SERVICE_NEWCONTACT, + YAHOO_SERVICE_ADDIDENT, /* 0x10 */ + YAHOO_SERVICE_ADDIGNORE, + YAHOO_SERVICE_PING, + YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */ + YAHOO_SERVICE_SYSMESSAGE = 0x14, + YAHOO_SERVICE_SKINNAME = 0x15, + YAHOO_SERVICE_PASSTHROUGH2 = 0x16, + YAHOO_SERVICE_CONFINVITE = 0x18, + YAHOO_SERVICE_CONFLOGON, + YAHOO_SERVICE_CONFDECLINE, + YAHOO_SERVICE_CONFLOGOFF, + YAHOO_SERVICE_CONFADDINVITE, + YAHOO_SERVICE_CONFMSG, + YAHOO_SERVICE_CHATLOGON, + YAHOO_SERVICE_CHATLOGOFF, + YAHOO_SERVICE_CHATMSG = 0x20, + YAHOO_SERVICE_GAMELOGON = 0x28, + YAHOO_SERVICE_GAMELOGOFF, + YAHOO_SERVICE_GAMEMSG = 0x2a, + YAHOO_SERVICE_FILETRANSFER = 0x46, + YAHOO_SERVICE_VOICECHAT = 0x4A, + YAHOO_SERVICE_NOTIFY, + YAHOO_SERVICE_VERIFY, + YAHOO_SERVICE_P2PFILEXFER, + YAHOO_SERVICE_PEERTOPEER = 0x4F, /* Checks if P2P possible */ + YAHOO_SERVICE_WEBCAM, + YAHOO_SERVICE_AUTHRESP = 0x54, + YAHOO_SERVICE_LIST, + YAHOO_SERVICE_AUTH = 0x57, + YAHOO_SERVICE_AUTHBUDDY = 0x6d, + YAHOO_SERVICE_ADDBUDDY = 0x83, + YAHOO_SERVICE_REMBUDDY, + YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0 */ + YAHOO_SERVICE_REJECTCONTACT, + YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */ + YAHOO_SERVICE_Y7_PING = 0x8A, + YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1 */ + YAHOO_SERVICE_CHATGOTO, + YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */ + YAHOO_SERVICE_CHATLEAVE, + YAHOO_SERVICE_CHATEXIT = 0x9b, + YAHOO_SERVICE_CHATADDINVITE = 0x9d, + YAHOO_SERVICE_CHATLOGOUT = 0xa0, + YAHOO_SERVICE_CHATPING, + YAHOO_SERVICE_COMMENT = 0xa8, + YAHOO_SERVICE_GAME_INVITE = 0xb7, + YAHOO_SERVICE_STEALTH_PERM = 0xb9, + YAHOO_SERVICE_STEALTH_SESSION = 0xba, + YAHOO_SERVICE_AVATAR = 0xbc, + YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd, + YAHOO_SERVICE_PICTURE = 0xbe, + YAHOO_SERVICE_PICTURE_UPDATE = 0xc1, + YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2, + YAHOO_SERVICE_YAB_UPDATE = 0xc4, + YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5, /* YMSG13, key 13: 2 = invisible, 1 = visible */ + YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6, /* YMSG13 */ + YAHOO_SERVICE_PICTURE_STATUS = 0xc7, /* YMSG13, key 213: 0 = none, 1 = avatar, 2 = picture */ + YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8, + YAHOO_SERVICE_AUDIBLE = 0xd0, + YAHOO_SERVICE_Y7_PHOTO_SHARING = 0xd2, + YAHOO_SERVICE_Y7_CONTACT_DETAILS = 0xd3, /* YMSG13 */ + YAHOO_SERVICE_Y7_CHAT_SESSION = 0xd4, + YAHOO_SERVICE_Y7_AUTHORIZATION = 0xd6, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFER = 0xdc, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFERINFO, /* YMSG13 */ + YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, /* YMSG13 */ + YAHOO_SERVICE_Y7_MINGLE = 0xe1, /* YMSG13 */ + YAHOO_SERVICE_Y7_CHANGE_GROUP = 0xe7, /* YMSG13 */ + YAHOO_SERVICE_MYSTERY = 0xef, /* Don't know what this is for */ + YAHOO_SERVICE_Y8_STATUS = 0xf0, /* YMSG15 */ + YAHOO_SERVICE_Y8_LIST = 0Xf1, /* YMSG15 */ + YAHOO_SERVICE_MESSAGE_CONFIRM = 0xfb, + YAHOO_SERVICE_WEBLOGIN = 0x0226, + YAHOO_SERVICE_SMS_MSG = 0x02ea +}; + +enum yahoo_status { + YAHOO_STATUS_AVAILABLE = 0, + YAHOO_STATUS_BRB, + YAHOO_STATUS_BUSY, + YAHOO_STATUS_NOTATHOME, + YAHOO_STATUS_NOTATDESK, + YAHOO_STATUS_NOTINOFFICE, + YAHOO_STATUS_ONPHONE, + YAHOO_STATUS_ONVACATION, + YAHOO_STATUS_OUTTOLUNCH, + YAHOO_STATUS_STEPPEDOUT, + YAHOO_STATUS_INVISIBLE = 12, + YAHOO_STATUS_CUSTOM = 99, + YAHOO_STATUS_IDLE = 999, + YAHOO_STATUS_OFFLINE = 0x5a55aa56 /* don't ask */ +}; + +enum ypacket_status { + YPACKET_STATUS_DISCONNECTED = -1, + YPACKET_STATUS_DEFAULT = 0, + YPACKET_STATUS_SERVERACK = 1, + YPACKET_STATUS_GAME = 0x2, + YPACKET_STATUS_AWAY = 0x4, + YPACKET_STATUS_CONTINUED = 0x5, + YPACKET_STATUS_INVISIBLE = 12, + YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */ + YPACKET_STATUS_WEBLOGIN = 0x5a55aa55, + YPACKET_STATUS_OFFLINE = 0x5a55aa56 +}; + +#define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */ + +enum yahoo_login_status { + YAHOO_LOGIN_OK = 0, + YAHOO_LOGIN_LOGOFF = 1, + YAHOO_LOGIN_UNAME = 3, + YAHOO_LOGIN_PASSWD = 13, + YAHOO_LOGIN_LOCK = 14, + YAHOO_LOGIN_DUPL = 99, + YAHOO_LOGIN_SOCK = -1, + YAHOO_LOGIN_UNKNOWN = 999 +}; + +enum yahoo_error { + E_UNKNOWN = -1, + E_CONNECTION = -2, + E_SYSTEM = -3, + E_CUSTOM = 0, + + /* responses from ignore buddy */ + E_IGNOREDUP = 2, + E_IGNORENONE = 3, + E_IGNORECONF = 12, + + /* conference */ + E_CONFNOTAVAIL = 20 +}; + +enum yahoo_log_level { + YAHOO_LOG_NONE = 0, + YAHOO_LOG_FATAL, + YAHOO_LOG_ERR, + YAHOO_LOG_WARNING, + YAHOO_LOG_NOTICE, + YAHOO_LOG_INFO, + YAHOO_LOG_DEBUG +}; + +enum yahoo_file_transfer { + YAHOO_FILE_TRANSFER_INIT = 1, + YAHOO_FILE_TRANSFER_ACCEPT = 3, + YAHOO_FILE_TRANSFER_REJECT = 4, + YAHOO_FILE_TRANSFER_DONE = 5, + YAHOO_FILE_TRANSFER_RELAY, + YAHOO_FILE_TRANSFER_FAILED, + YAHOO_FILE_TRANSFER_UNKNOWN +}; #define YAHOO_PROTO_VER 0x0010 @@ -221,27 +221,27 @@ extern "C" { #define YAHOO_STYLE_URLON "\033[lm" #define YAHOO_STYLE_URLOFF "\033[xlm" - enum yahoo_connection_type { - YAHOO_CONNECTION_PAGER = 0, - YAHOO_CONNECTION_FT, - YAHOO_CONNECTION_YAB, - YAHOO_CONNECTION_WEBCAM_MASTER, - YAHOO_CONNECTION_WEBCAM, - YAHOO_CONNECTION_CHATCAT, - YAHOO_CONNECTION_SEARCH, - YAHOO_CONNECTION_AUTH - }; - - enum yahoo_webcam_direction_type { - YAHOO_WEBCAM_DOWNLOAD = 0, - YAHOO_WEBCAM_UPLOAD - }; - - enum yahoo_stealth_visibility_type { - YAHOO_STEALTH_DEFAULT = 0, - YAHOO_STEALTH_ONLINE, - YAHOO_STEALTH_PERM_OFFLINE - }; +enum yahoo_connection_type { + YAHOO_CONNECTION_PAGER = 0, + YAHOO_CONNECTION_FT, + YAHOO_CONNECTION_YAB, + YAHOO_CONNECTION_WEBCAM_MASTER, + YAHOO_CONNECTION_WEBCAM, + YAHOO_CONNECTION_CHATCAT, + YAHOO_CONNECTION_SEARCH, + YAHOO_CONNECTION_AUTH +}; + +enum yahoo_webcam_direction_type { + YAHOO_WEBCAM_DOWNLOAD = 0, + YAHOO_WEBCAM_UPLOAD +}; + +enum yahoo_stealth_visibility_type { + YAHOO_STEALTH_DEFAULT = 0, + YAHOO_STEALTH_ONLINE, + YAHOO_STEALTH_PERM_OFFLINE +}; /* chat member attribs */ #define YAHOO_CHAT_MALE 0x8000 @@ -250,145 +250,145 @@ extern "C" { #define YAHOO_CHAT_DUNNO 0x400 #define YAHOO_CHAT_WEBCAM 0x10 - enum yahoo_webcam_conn_type { Y_WCM_DIALUP, Y_WCM_DSL, Y_WCM_T1 }; - - struct yahoo_webcam { - int direction; /* Uploading or downloading */ - int conn_type; /* 0=Dialup, 1=DSL/Cable, 2=T1/Lan */ - - char *user; /* user we are viewing */ - char *server; /* webcam server to connect to */ - int port; /* webcam port to connect on */ - char *key; /* key to connect to the server with */ - char *description; /* webcam description */ - char *my_ip; /* own ip number */ - }; - - struct yahoo_webcam_data { - unsigned int data_size; - unsigned int to_read; - unsigned int timestamp; - unsigned char packet_type; - }; - - struct yahoo_data { - char *user; - char *password; - - char *cookie_y; - char *cookie_t; - char *cookie_c; - char *cookie_b; - char *login_cookie; - char *crumb; - char *seed; - - YList *buddies; - YList *ignore; - YList *identities; - char *login_id; - - int current_status; - int initial_status; - int logged_in; - - int session_id; - - int client_id; - - char *rawbuddylist; - char *ignorelist; - - void *server_settings; - - struct yahoo_process_status_entry *half_user; - }; - - struct yab { - int yid; - char *id; - char *fname; - char *lname; - char *nname; - char *email; - char *hphone; - char *wphone; - char *mphone; - int dbid; - }; - - struct yahoo_buddy { - char *group; - char *id; - char *real_name; - struct yab *yab_entry; - }; - - enum yahoo_search_type { - YAHOO_SEARCH_KEYWORD = 0, - YAHOO_SEARCH_YID, - YAHOO_SEARCH_NAME - }; - - enum yahoo_search_gender { - YAHOO_GENDER_NONE = 0, - YAHOO_GENDER_MALE, - YAHOO_GENDER_FEMALE - }; - - enum yahoo_search_agerange { - YAHOO_AGERANGE_NONE = 0 - }; - - struct yahoo_found_contact { - char *id; - char *gender; - char *location; - int age; - int online; - }; +enum yahoo_webcam_conn_type { Y_WCM_DIALUP, Y_WCM_DSL, Y_WCM_T1 }; + +struct yahoo_webcam { + int direction; /* Uploading or downloading */ + int conn_type; /* 0=Dialup, 1=DSL/Cable, 2=T1/Lan */ + + char *user; /* user we are viewing */ + char *server; /* webcam server to connect to */ + int port; /* webcam port to connect on */ + char *key; /* key to connect to the server with */ + char *description; /* webcam description */ + char *my_ip; /* own ip number */ +}; + +struct yahoo_webcam_data { + unsigned int data_size; + unsigned int to_read; + unsigned int timestamp; + unsigned char packet_type; +}; + +struct yahoo_data { + char *user; + char *password; + + char *cookie_y; + char *cookie_t; + char *cookie_c; + char *cookie_b; + char *login_cookie; + char *crumb; + char *seed; + + YList *buddies; + YList *ignore; + YList *identities; + char *login_id; + + int current_status; + int initial_status; + int logged_in; + + int session_id; + + int client_id; + + char *rawbuddylist; + char *ignorelist; + + void *server_settings; + + struct yahoo_process_status_entry *half_user; +}; + +struct yab { + int yid; + char *id; + char *fname; + char *lname; + char *nname; + char *email; + char *hphone; + char *wphone; + char *mphone; + int dbid; +}; + +struct yahoo_buddy { + char *group; + char *id; + char *real_name; + struct yab *yab_entry; +}; + +enum yahoo_search_type { + YAHOO_SEARCH_KEYWORD = 0, + YAHOO_SEARCH_YID, + YAHOO_SEARCH_NAME +}; + +enum yahoo_search_gender { + YAHOO_GENDER_NONE = 0, + YAHOO_GENDER_MALE, + YAHOO_GENDER_FEMALE +}; + +enum yahoo_search_agerange { + YAHOO_AGERANGE_NONE = 0 +}; + +struct yahoo_found_contact { + char *id; + char *gender; + char *location; + int age; + int online; +}; /* * Function pointer to be passed to http get/post and send file */ - typedef void (*yahoo_get_fd_callback) (int id, void *fd, int error, - void *data); +typedef void (*yahoo_get_fd_callback) (int id, void *fd, int error, + void *data); /* * Function pointer to be passed to yahoo_get_url_handle */ - typedef void (*yahoo_get_url_handle_callback) (int id, void *fd, - int error, const char *filename, unsigned long size, - void *data); - - struct yahoo_chat_member { - char *id; - int age; - int attribs; - char *alias; - char *location; - }; - - struct yahoo_process_status_entry { - char *name; /* 7 name */ - int state; /* 10 state */ - int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ - int mobile; /* 60 mobile */ - char *msg; /* 19 custom status message */ - int away; /* 47 away (or invisible) */ - int buddy_session; /* 11 state */ - int f17; /* 17 in chat? then what about flags? */ - int idle; /* 137 seconds idle */ - int f138; /* 138 state */ - char *f184; /* 184 state */ - int f192; /* 192 state */ - int f10001; /* 10001 state */ - int f10002; /* 10002 state */ - int f198; /* 198 state */ - char *f197; /* 197 state */ - char *f205; /* 205 state */ - int f213; /* 213 state */ - }; +typedef void (*yahoo_get_url_handle_callback) (int id, void *fd, + int error, const char *filename, unsigned long size, + void *data); + +struct yahoo_chat_member { + char *id; + int age; + int attribs; + char *alias; + char *location; +}; + +struct yahoo_process_status_entry { + char *name; /* 7 name */ + int state; /* 10 state */ + int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ + int mobile; /* 60 mobile */ + char *msg; /* 19 custom status message */ + int away; /* 47 away (or invisible) */ + int buddy_session; /* 11 state */ + int f17; /* 17 in chat? then what about flags? */ + int idle; /* 137 seconds idle */ + int f138; /* 138 state */ + char *f184; /* 184 state */ + int f192; /* 192 state */ + int f10001; /* 10001 state */ + int f10002; /* 10002 state */ + int f198; /* 198 state */ + char *f197; /* 197 state */ + char *f205; /* 205 state */ + int f213; /* 213 state */ +}; #ifdef __cplusplus } diff --git a/protocols/yahoo/yahoo_debug.h b/protocols/yahoo/yahoo_debug.h index 08382d64..ddcd91c5 100644 --- a/protocols/yahoo/yahoo_debug.h +++ b/protocols/yahoo/yahoo_debug.h @@ -21,18 +21,20 @@ extern int yahoo_log_message(char *fmt, ...); -#define NOTICE(x) if(yahoo_get_log_level() >= YAHOO_LOG_NOTICE) { yahoo_log_message x; yahoo_log_message("\n"); } +#define NOTICE(x) if (yahoo_get_log_level() >= YAHOO_LOG_NOTICE) { yahoo_log_message x; yahoo_log_message("\n"); } -#define LOG(x) if(yahoo_get_log_level() >= YAHOO_LOG_INFO) { yahoo_log_message("%s:%d: ", __FILE__, __LINE__); \ - yahoo_log_message x; \ - yahoo_log_message("\n"); } +#define LOG(x) if (yahoo_get_log_level() >= YAHOO_LOG_INFO) { yahoo_log_message("%s:%d: ", __FILE__, __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } -#define WARNING(x) if(yahoo_get_log_level() >= YAHOO_LOG_WARNING) { yahoo_log_message("%s:%d: warning: ", __FILE__, __LINE__); \ - yahoo_log_message x; \ - yahoo_log_message("\n"); } +#define WARNING(x) if (yahoo_get_log_level() >= YAHOO_LOG_WARNING) { yahoo_log_message("%s:%d: warning: ", __FILE__, \ + __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } -#define DEBUG_MSG(x) if(yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { yahoo_log_message("%s:%d: debug: ", __FILE__, __LINE__); \ - yahoo_log_message x; \ - yahoo_log_message("\n"); } +#define DEBUG_MSG(x) if (yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { yahoo_log_message("%s:%d: debug: ", __FILE__, \ + __LINE__); \ + yahoo_log_message x; \ + yahoo_log_message("\n"); } diff --git a/protocols/yahoo/yahoo_httplib.c b/protocols/yahoo/yahoo_httplib.c index ec153234..968a2696 100644 --- a/protocols/yahoo/yahoo_httplib.c +++ b/protocols/yahoo/yahoo_httplib.c @@ -31,8 +31,8 @@ # endif char *strchr(), *strrchr(); # if !HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# define memmove(d, s, n) bcopy ((s), (d), (n)) +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memmove(d, s, n) bcopy((s), (d), (n)) # endif #endif @@ -52,9 +52,9 @@ char *strchr(), *strrchr(); #ifdef USE_STRUCT_CALLBACKS extern struct yahoo_callbacks *yc; -#define YAHOO_CALLBACK(x) yc->x +#define YAHOO_CALLBACK(x) yc->x #else -#define YAHOO_CALLBACK(x) x +#define YAHOO_CALLBACK(x) x #endif extern enum yahoo_log_level log_level; @@ -68,21 +68,24 @@ int yahoo_tcp_readline(char *ptr, int maxlen, void *fd) for (n = 1; n < maxlen; n++) { do { - rc = YAHOO_CALLBACK(ext_yahoo_read) (fd, &c, 1); - } while (rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */ + rc = YAHOO_CALLBACK (ext_yahoo_read) (fd, &c, 1); + } while (rc == -1 && (errno == EINTR || errno == EAGAIN)); /* this is bad - it should be done asynchronously */ if (rc == 1) { - if (c == '\r') /* get rid of \r */ + if (c == '\r') { /* get rid of \r */ continue; + } *ptr = c; - if (c == '\n') + if (c == '\n') { break; + } ptr++; } else if (rc == 0) { - if (n == 1) - return (0); /* EOF, no data */ - else - break; /* EOF, w/ data */ + if (n == 1) { + return (0); /* EOF, no data */ + } else { + break; /* EOF, w/ data */ + } } else { return -1; } @@ -94,7 +97,7 @@ int yahoo_tcp_readline(char *ptr, int maxlen, void *fd) #endif static int url_to_host_port_path(const char *url, - char *host, int *port, char *path, int *ssl) + char *host, int *port, char *path, int *ssl) { char *urlcopy = NULL; char *slash = NULL; @@ -126,10 +129,11 @@ static int url_to_host_port_path(const char *url, colon = strchr(urlcopy, ':'); if (!colon || (slash && slash < colon)) { - if (*ssl) + if (*ssl) { *port = 443; - else + } else { *port = 80; + } } else { *colon = 0; *port = atoi(colon + 1); @@ -160,14 +164,17 @@ char *yahoo_urlencode(const char *instr) char *str = NULL; int len = strlen(instr); - if (!(str = y_new(char, 3 *len + 1))) - return ""; + if (!(str = y_new(char, 3 * len + 1))) { + return ""; + } while (instr[ipos]) { - while (isurlchar(instr[ipos])) + while (isurlchar(instr[ipos])) { str[bpos++] = instr[ipos++]; - if (!instr[ipos]) + } + if (!instr[ipos]) { break; + } snprintf(&str[bpos], 4, "%%%02x", instr[ipos] & 0xff); bpos += 3; @@ -191,25 +198,29 @@ char *yahoo_urldecode(const char *instr) unsigned dec; int len = strlen(instr); - if (!(str = y_new(char, len + 1))) - return ""; + if (!(str = y_new(char, len + 1))) { + return ""; + } while (instr[ipos]) { - while (instr[ipos] && instr[ipos] != '%') + while (instr[ipos] && instr[ipos] != '%') { if (instr[ipos] == '+') { str[bpos++] = ' '; ipos++; - } else + } else { str[bpos++] = instr[ipos++]; - if (!instr[ipos]) + } + } + if (!instr[ipos]) { break; + } if (instr[ipos + 1] && instr[ipos + 2]) { ipos++; entity[0] = instr[ipos++]; entity[1] = instr[ipos++]; sscanf(entity, "%2x", &dec); - str[bpos++] = (char)dec; + str[bpos++] = (char) dec; } else { str[bpos++] = instr[ipos++]; } @@ -229,46 +240,52 @@ char *yahoo_xmldecode(const char *instr) char *str = NULL; char entity[4] = { 0, 0, 0, 0 }; char *entitymap[5][2] = { - {"amp;", "&"}, - {"quot;", "\""}, - {"lt;", "<"}, - {"gt;", "<"}, - {"nbsp;", " "} + { "amp;", "&" }, + { "quot;", "\"" }, + { "lt;", "<" }, + { "gt;", "<" }, + { "nbsp;", " " } }; unsigned dec; int len = strlen(instr); - if (!(str = y_new(char, len + 1))) - return ""; + if (!(str = y_new(char, len + 1))) { + return ""; + } while (instr[ipos]) { - while (instr[ipos] && instr[ipos] != '&') + while (instr[ipos] && instr[ipos] != '&') { if (instr[ipos] == '+') { str[bpos++] = ' '; ipos++; - } else + } else { str[bpos++] = instr[ipos++]; - if (!instr[ipos] || !instr[ipos + 1]) + } + } + if (!instr[ipos] || !instr[ipos + 1]) { break; + } ipos++; if (instr[ipos] == '#') { ipos++; epos = 0; - while (instr[ipos] != ';') + while (instr[ipos] != ';') { entity[epos++] = instr[ipos++]; + } sscanf(entity, "%u", &dec); - str[bpos++] = (char)dec; + str[bpos++] = (char) dec; ipos++; } else { int i; - for (i = 0; i < 5; i++) + for (i = 0; i < 5; i++) { if (!strncmp(instr + ipos, entitymap[i][0], - strlen(entitymap[i][0]))) { + strlen(entitymap[i][0]))) { str[bpos++] = entitymap[i][1][0]; ipos += strlen(entitymap[i][0]); break; } + } } } str[bpos] = '\0'; @@ -293,29 +310,32 @@ struct callback_data { static void connect_complete(void *fd, int error, void *data) { struct callback_data *ccd = data; - if (error == 0) - YAHOO_CALLBACK(ext_yahoo_write) (fd, ccd->request, - strlen(ccd->request)); + + if (error == 0) { + YAHOO_CALLBACK (ext_yahoo_write) (fd, ccd->request, + strlen(ccd->request)); + } free(ccd->request); ccd->callback(ccd->id, fd, error, ccd->user_data); FREE(ccd); } static void yahoo_send_http_request(int id, char *host, int port, char *request, - yahoo_get_fd_callback callback, void *data, int use_ssl) + yahoo_get_fd_callback callback, void *data, int use_ssl) { struct callback_data *ccd = y_new0(struct callback_data, 1); + ccd->callback = callback; ccd->id = id; ccd->request = strdup(request); ccd->user_data = data; - YAHOO_CALLBACK(ext_yahoo_connect_async) (id, host, port, - connect_complete, ccd, use_ssl); + YAHOO_CALLBACK (ext_yahoo_connect_async) (id, host, port, + connect_complete, ccd, use_ssl); } void yahoo_http_post(int id, const char *url, const char *cookies, - long content_length, yahoo_get_fd_callback callback, void *data) + long content_length, yahoo_get_fd_callback callback, void *data) { char host[255]; int port = 80; @@ -323,24 +343,25 @@ void yahoo_http_post(int id, const char *url, const char *cookies, char buff[1024]; int ssl = 0; - if (!url_to_host_port_path(url, host, &port, path, &ssl)) + if (!url_to_host_port_path(url, host, &port, path, &ssl)) { return; + } /* thanks to kopete dumpcap */ snprintf(buff, sizeof(buff), - "POST %s HTTP/1.1\r\n" - "Cookie: %s\r\n" - "User-Agent: Mozilla/5.0\r\n" - "Host: %s\r\n" - "Content-Length: %ld\r\n" - "Cache-Control: no-cache\r\n" - "\r\n", path, cookies, host, content_length); + "POST %s HTTP/1.1\r\n" + "Cookie: %s\r\n" + "User-Agent: Mozilla/5.0\r\n" + "Host: %s\r\n" + "Content-Length: %ld\r\n" + "Cache-Control: no-cache\r\n" + "\r\n", path, cookies, host, content_length); yahoo_send_http_request(id, host, port, buff, callback, data, ssl); } void yahoo_http_get(int id, const char *url, const char *cookies, int http11, - int keepalive, yahoo_get_fd_callback callback, void *data) + int keepalive, yahoo_get_fd_callback callback, void *data) { char host[255]; int port = 80; @@ -349,29 +370,31 @@ void yahoo_http_get(int id, const char *url, const char *cookies, int http11, char cookiebuff[1024]; int ssl = 0; - if (!url_to_host_port_path(url, host, &port, path, &ssl)) + if (!url_to_host_port_path(url, host, &port, path, &ssl)) { return; + } /* Allow cases when we don't need to send a cookie */ - if (cookies) + if (cookies) { snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", - cookies); - else + cookies); + } else { cookiebuff[0] = '\0'; + } snprintf(buff, sizeof(buff), - "GET %s HTTP/1.%s\r\n" - "%sHost: %s\r\n" - "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" - "Accept: */*\r\n" - "%s" "\r\n", path, http11?"1":"0", cookiebuff, host, - keepalive? "Connection: Keep-Alive\r\n":"Connection: close\r\n"); + "GET %s HTTP/1.%s\r\n" + "%sHost: %s\r\n" + "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" + "Accept: */*\r\n" + "%s" "\r\n", path, http11 ? "1" : "0", cookiebuff, host, + keepalive ? "Connection: Keep-Alive\r\n" : "Connection: close\r\n"); yahoo_send_http_request(id, host, port, buff, callback, data, ssl); } void yahoo_http_head(int id, const char *url, const char *cookies, int len, - char *payload, yahoo_get_fd_callback callback, void *data) + char *payload, yahoo_get_fd_callback callback, void *data) { char host[255]; int port = 80; @@ -380,26 +403,28 @@ void yahoo_http_head(int id, const char *url, const char *cookies, int len, char cookiebuff[1024]; int ssl = 0; - if (!url_to_host_port_path(url, host, &port, path, &ssl)) + if (!url_to_host_port_path(url, host, &port, path, &ssl)) { return; + } /* Allow cases when we don't need to send a cookie */ - if (cookies) + if (cookies) { snprintf(cookiebuff, sizeof(cookiebuff), "Cookie: %s\r\n", - cookies); - else + cookies); + } else { cookiebuff[0] = '\0'; + } snprintf(buff, sizeof(buff), - "HEAD %s HTTP/1.0\r\n" - "Accept: */*\r\n" - "Host: %s:%d\r\n" - "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" - "%s" - "Content-Length: %d\r\n" - "Cache-Control: no-cache\r\n" - "\r\n%s", path, host, port, cookiebuff, len, - payload?payload:""); + "HEAD %s HTTP/1.0\r\n" + "Accept: */*\r\n" + "Host: %s:%d\r\n" + "User-Agent: Mozilla/4.5 [en] (" PACKAGE "/" VERSION ")\r\n" + "%s" + "Content-Length: %d\r\n" + "Cache-Control: no-cache\r\n" + "\r\n%s", path, host, port, cookiebuff, len, + payload ? payload : ""); yahoo_send_http_request(id, host, port, buff, callback, data, ssl); } diff --git a/protocols/yahoo/yahoo_httplib.h b/protocols/yahoo/yahoo_httplib.h index 8e386717..9ee30ad6 100644 --- a/protocols/yahoo/yahoo_httplib.h +++ b/protocols/yahoo/yahoo_httplib.h @@ -28,19 +28,19 @@ extern "C" { #include "yahoo2_types.h" - char *yahoo_urlencode(const char *instr); - char *yahoo_urldecode(const char *instr); - char *yahoo_xmldecode(const char *instr); +char *yahoo_urlencode(const char *instr); +char *yahoo_urldecode(const char *instr); +char *yahoo_xmldecode(const char *instr); - int yahoo_tcp_readline(char *ptr, int maxlen, void *fd); - void yahoo_http_post(int id, const char *url, const char *cookies, - long size, yahoo_get_fd_callback callback, void *data); - void yahoo_http_get(int id, const char *url, const char *cookies, - int http11, int keepalive, yahoo_get_fd_callback callback, - void *data); - void yahoo_http_head(int id, const char *url, const char *cookies, - int size, char *payload, yahoo_get_fd_callback callback, - void *data); +int yahoo_tcp_readline(char *ptr, int maxlen, void *fd); +void yahoo_http_post(int id, const char *url, const char *cookies, + long size, yahoo_get_fd_callback callback, void *data); +void yahoo_http_get(int id, const char *url, const char *cookies, + int http11, int keepalive, yahoo_get_fd_callback callback, + void *data); +void yahoo_http_head(int id, const char *url, const char *cookies, + int size, char *payload, yahoo_get_fd_callback callback, + void *data); #ifdef __cplusplus } diff --git a/protocols/yahoo/yahoo_util.c b/protocols/yahoo/yahoo_util.c index 1b6168aa..7fc50fda 100644 --- a/protocols/yahoo/yahoo_util.c +++ b/protocols/yahoo/yahoo_util.c @@ -26,10 +26,10 @@ # define strchr index # define strrchr rindex # endif -char *strchr (), *strrchr (); +char *strchr(), *strrchr(); # if !HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# define memmove(d, s, n) bcopy ((s), (d), (n)) +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memmove(d, s, n) bcopy((s), (d), (n)) # endif #endif @@ -56,7 +56,8 @@ char *y_string_append(char *string, char *append) void y_strfreev(char ** vector) { char **v; - for(v = vector; *v; v++) { + + for (v = vector; *v; v++) { FREE(*v); } FREE(vector); @@ -66,31 +67,35 @@ char ** y_strsplit(char * str, char * sep, int nelem) { char ** vector; char *s, *p; - int i=0; + int i = 0; int l = strlen(sep); - if(nelem <= 0) { + + if (nelem <= 0) { char * s; - nelem=0; + nelem = 0; if (*str) { - for(s=strstr(str, sep); s; s=strstr(s+l, sep),nelem++) + for (s = strstr(str, sep); s; s = strstr(s + l, sep), nelem++) { ; - if(strcmp(str+strlen(str)-l, sep)) + } + if (strcmp(str + strlen(str) - l, sep)) { nelem++; + } } } vector = y_new(char *, nelem + 1); - for(p=str, s=strstr(p,sep); i<nelem && s; p=s+l, s=strstr(p,sep), i++) { - int len = s-p; - vector[i] = y_new(char, len+1); + for (p = str, s = strstr(p, sep); i < nelem && s; p = s + l, s = strstr(p, sep), i++) { + int len = s - p; + vector[i] = y_new(char, len + 1); strncpy(vector[i], p, len); vector[i][len] = '\0'; } - if(i<nelem && *str) /* str didn't end with sep, and str isn't empty */ + if (i < nelem && *str) { /* str didn't end with sep, and str isn't empty */ vector[i++] = strdup(p); - + } + vector[i] = NULL; return vector; @@ -99,8 +104,10 @@ char ** y_strsplit(char * str, char * sep, int nelem) void * y_memdup(const void * addr, int n) { void * new_chunk = malloc(n); - if(new_chunk) + + if (new_chunk) { memcpy(new_chunk, addr, n); + } return new_chunk; } diff --git a/protocols/yahoo/yahoo_util.h b/protocols/yahoo/yahoo_util.h index 6099bf8f..1a033a66 100644 --- a/protocols/yahoo/yahoo_util.h +++ b/protocols/yahoo/yahoo_util.h @@ -29,39 +29,39 @@ #if HAVE_GLIB # include <glib.h> -# define FREE(x) if(x) {g_free(x); x=NULL;} +# define FREE(x) if (x) { g_free(x); x = NULL; } -# define y_new g_new -# define y_new0 g_new0 -# define y_renew g_renew +# define y_new g_new +# define y_new0 g_new0 +# define y_renew g_renew -# define y_memdup g_memdup -# define y_strsplit g_strsplit -# define y_strfreev g_strfreev +# define y_memdup g_memdup +# define y_strsplit g_strsplit +# define y_strfreev g_strfreev # ifndef strdup -# define strdup g_strdup +# define strdup g_strdup # endif # ifndef strncasecmp -# define strncasecmp g_strncasecmp -# define strcasecmp g_strcasecmp +# define strncasecmp g_strncasecmp +# define strcasecmp g_strcasecmp # endif -# define snprintf g_snprintf +# define snprintf g_snprintf #ifdef vsnprintf #undef vsnprintf #endif -# define vsnprintf g_vsnprintf +# define vsnprintf g_vsnprintf #else # include <stdlib.h> # include <stdarg.h> -# define FREE(x) if(x) {free(x); x=NULL;} +# define FREE(x) if (x) { free(x); x = NULL; } -# define y_new(type, n) (type *)malloc(sizeof(type) * (n)) -# define y_new0(type, n) (type *)calloc((n), sizeof(type)) -# define y_renew(type, mem, n) (type *)realloc(mem, n) +# define y_new(type, n) (type *) malloc(sizeof(type) * (n)) +# define y_new0(type, n) (type *) calloc((n), sizeof(type)) +# define y_renew(type, mem, n) (type *) realloc(mem, n) void *y_memdup(const void *addr, int n); char **y_strsplit(char *str, char *sep, int nelem); @@ -86,14 +86,14 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap); #endif #ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif #ifndef MAX -#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MAX(x, y) ((x) > (y) ? (x) : (y)) #endif -/* +/* * The following three functions return newly allocated memory. * You must free it yourself */ @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -26,170 +26,172 @@ #define BITLBEE_CORE #include "bitlbee.h" -static void query_display( irc_t *irc, query_t *q ); -static query_t *query_default( irc_t *irc ); +static void query_display(irc_t *irc, query_t *q); +static query_t *query_default(irc_t *irc); -query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, - query_callback yes, query_callback no, query_callback free, - void *data ) +query_t *query_add(irc_t *irc, struct im_connection *ic, char *question, + query_callback yes, query_callback no, query_callback free, + void *data) { - query_t *q = g_new0( query_t, 1 ); - + query_t *q = g_new0(query_t, 1); + q->ic = ic; - q->question = g_strdup( question ); + q->question = g_strdup(question); q->yes = yes; q->no = no; q->free = free; q->data = data; - - if( strchr( irc->umode, 'b' ) != NULL ) - { + + if (strchr(irc->umode, 'b') != NULL) { char *s; - + /* At least for the machine-parseable version, get rid of newlines to make "parsing" easier. */ - for( s = q->question; *s; s ++ ) - if( *s == '\r' || *s == '\n' ) + for (s = q->question; *s; s++) { + if (*s == '\r' || *s == '\n') { *s = ' '; + } + } } - - if( irc->queries ) - { + + if (irc->queries) { query_t *l = irc->queries; - - while( l->next ) l = l->next; + + while (l->next) { + l = l->next; + } l->next = q; - } - else - { + } else { irc->queries = q; } - - if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "lifo" ) == 0 || irc->queries == q ) - query_display( irc, q ); - - return( q ); + + if (g_strcasecmp(set_getstr(&irc->b->set, "query_order"), "lifo") == 0 || irc->queries == q) { + query_display(irc, q); + } + + return(q); } -void query_del( irc_t *irc, query_t *q ) +void query_del(irc_t *irc, query_t *q) { query_t *l; - - if( irc->queries == q ) - { + + if (irc->queries == q) { irc->queries = q->next; - } - else - { - for( l = irc->queries; l; l = l->next ) - { - if( l->next == q ) - { + } else { + for (l = irc->queries; l; l = l->next) { + if (l->next == q) { l->next = q->next; break; } } - - if( !l ) + + if (!l) { return; /* Hrmmm... */ + } } - - g_free( q->question ); - if( q->free && q->data ) - q->free( q->data ); - g_free( q ); + + g_free(q->question); + if (q->free && q->data) { + q->free(q->data); + } + g_free(q); } -void query_del_by_conn( irc_t *irc, struct im_connection *ic ) +void query_del_by_conn(irc_t *irc, struct im_connection *ic) { query_t *q, *n, *def; int count = 0; - - if( !ic ) + + if (!ic) { return; - + } + q = irc->queries; - def = query_default( irc ); - - while( q ) - { - if( q->ic == ic ) - { + def = query_default(irc); + + while (q) { + if (q->ic == ic) { n = q->next; - query_del( irc, q ); + query_del(irc, q); q = n; - - count ++; - } - else - { + + count++; + } else { q = q->next; } } - - if( count > 0 ) - imcb_log( ic, "Flushed %d unanswered question(s) for this connection.", count ); - - q = query_default( irc ); - if( q && q != def ) - query_display( irc, q ); + + if (count > 0) { + imcb_log(ic, "Flushed %d unanswered question(s) for this connection.", count); + } + + q = query_default(irc); + if (q && q != def) { + query_display(irc, q); + } } -void query_answer( irc_t *irc, query_t *q, int ans ) +void query_answer(irc_t *irc, query_t *q, int ans) { int disp = 0; - - if( !q ) - { - q = query_default( irc ); + + if (!q) { + q = query_default(irc); disp = 1; } - if( ans ) - { - if( q->ic ) - imcb_log( q->ic, "Accepted: %s", q->question ); - else - irc_rootmsg( irc, "Accepted: %s", q->question ); - if( q->yes ) - q->yes( q->data ); - } - else - { - if( q->ic ) - imcb_log( q->ic, "Rejected: %s", q->question ); - else - irc_rootmsg( irc, "Rejected: %s", q->question ); - if( q->no ) - q->no( q->data ); + if (ans) { + if (q->ic) { + imcb_log(q->ic, "Accepted: %s", q->question); + } else { + irc_rootmsg(irc, "Accepted: %s", q->question); + } + if (q->yes) { + q->yes(q->data); + } + } else { + if (q->ic) { + imcb_log(q->ic, "Rejected: %s", q->question); + } else { + irc_rootmsg(irc, "Rejected: %s", q->question); + } + if (q->no) { + q->no(q->data); + } } q->data = NULL; - - query_del( irc, q ); - - if( disp && ( q = query_default( irc ) ) ) - query_display( irc, q ); + + query_del(irc, q); + + if (disp && (q = query_default(irc))) { + query_display(irc, q); + } } -static void query_display( irc_t *irc, query_t *q ) +static void query_display(irc_t *irc, query_t *q) { - if( q->ic ) - { - imcb_log( q->ic, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); - } - else - { - irc_rootmsg( irc, "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", q->question ); + if (q->ic) { + imcb_log(q->ic, + "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", + q->question); + } else { + irc_rootmsg(irc, + "New request: %s\nYou can use the \2yes\2/\2no\2 commands to accept/reject this request.", + q->question); } } -static query_t *query_default( irc_t *irc ) +static query_t *query_default(irc_t *irc) { query_t *q; - - if( g_strcasecmp( set_getstr( &irc->b->set, "query_order" ), "fifo" ) == 0 ) + + if (g_strcasecmp(set_getstr(&irc->b->set, "query_order"), "fifo") == 0) { q = irc->queries; - else - for( q = irc->queries; q && q->next; q = q->next ); - - return( q ); + } else { + for (q = irc->queries; q && q->next; q = q->next) { + ; + } + } + + return(q); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -26,10 +26,9 @@ #ifndef _QUERY_H #define _QUERY_H -typedef void (*query_callback) ( void *data ); +typedef void (*query_callback) (void *data); -typedef struct query -{ +typedef struct query { struct im_connection *ic; char *question; query_callback yes, no, free; @@ -37,11 +36,11 @@ typedef struct query struct query *next; } query_t; -query_t *query_add( irc_t *irc, struct im_connection *ic, char *question, - query_callback yes, query_callback no, query_callback free, - void *data ); -void query_del( irc_t *irc, query_t *q ); -void query_del_by_conn( irc_t *irc, struct im_connection *ic ); -void query_answer( irc_t *irc, query_t *q, int ans ); +query_t *query_add(irc_t *irc, struct im_connection *ic, char *question, + query_callback yes, query_callback no, query_callback free, + void *data); +void query_del(irc_t *irc, query_t *q); +void query_del_by_conn(irc_t *irc, struct im_connection *ic); +void query_answer(irc_t *irc, query_t *q, int ans); #endif diff --git a/root_commands.c b/root_commands.c index 1fa2d0ad..7e1dc2a7 100644 --- a/root_commands.c +++ b/root_commands.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -29,994 +29,891 @@ #include "help.h" #include "ipc.h" -void root_command_string( irc_t *irc, char *command ) +void root_command_string(irc_t *irc, char *command) { - root_command( irc, split_command_parts( command, 0 ) ); + root_command(irc, split_command_parts(command, 0)); } -#define MIN_ARGS( x, y... ) \ +#define MIN_ARGS(x, y ...) \ do \ { \ int blaat; \ - for( blaat = 0; blaat <= x; blaat ++ ) \ - if( cmd[blaat] == NULL ) \ + for (blaat = 0; blaat <= x; blaat++) { \ + if (cmd[blaat] == NULL) \ { \ - irc_rootmsg( irc, "Not enough parameters given (need %d).", x ); \ + irc_rootmsg(irc, "Not enough parameters given (need %d).", x); \ return y; \ - } \ - } while( 0 ) + } } \ + } while (0) -void root_command( irc_t *irc, char *cmd[] ) -{ +void root_command(irc_t *irc, char *cmd[]) +{ int i, len; - - if( !cmd[0] ) + + if (!cmd[0]) { return; - - len = strlen( cmd[0] ); - for( i = 0; root_commands[i].command; i++ ) - if( g_strncasecmp( root_commands[i].command, cmd[0], len ) == 0 ) - { - if( root_commands[i+1].command && - g_strncasecmp( root_commands[i+1].command, cmd[0], len ) == 0 ) - /* Only match on the first letters if the match is unique. */ - break; - - MIN_ARGS( root_commands[i].required_parameters ); - - root_commands[i].execute( irc, cmd ); + } + + len = strlen(cmd[0]); + for (i = 0; root_commands[i].command; i++) { + if (g_strncasecmp(root_commands[i].command, cmd[0], len) == 0) { + if (root_commands[i + 1].command && + g_strncasecmp(root_commands[i + 1].command, cmd[0], len) == 0) { + /* Only match on the first letters if the match is unique. */ + break; + } + + MIN_ARGS(root_commands[i].required_parameters); + + root_commands[i].execute(irc, cmd); return; } - - irc_rootmsg( irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", cmd[0] ); + } + + irc_rootmsg(irc, "Unknown command: %s. Please use \x02help commands\x02 to get a list of available commands.", + cmd[0]); } -static void cmd_help( irc_t *irc, char **cmd ) +static void cmd_help(irc_t *irc, char **cmd) { char param[80]; int i; char *s; - - memset( param, 0, sizeof(param) ); - for ( i = 1; (cmd[i] != NULL && ( strlen(param) < (sizeof(param)-1) ) ); i++ ) { - if ( i != 1 ) // prepend space except for the first parameter + + memset(param, 0, sizeof(param)); + for (i = 1; (cmd[i] != NULL && (strlen(param) < (sizeof(param) - 1))); i++) { + if (i != 1) { // prepend space except for the first parameter strcat(param, " "); - strncat( param, cmd[i], sizeof(param) - strlen(param) - 1 ); + } + strncat(param, cmd[i], sizeof(param) - strlen(param) - 1); } - s = help_get( &(global.help), param ); - if( !s ) s = help_get( &(global.help), "" ); - - if( s ) - { - irc_rootmsg( irc, "%s", s ); - g_free( s ); + s = help_get(&(global.help), param); + if (!s) { + s = help_get(&(global.help), ""); } - else - { - irc_rootmsg( irc, "Error opening helpfile." ); + + if (s) { + irc_rootmsg(irc, "%s", s); + g_free(s); + } else { + irc_rootmsg(irc, "Error opening helpfile."); } } -static void cmd_account( irc_t *irc, char **cmd ); -static void bitlbee_whatsnew( irc_t *irc ); +static void cmd_account(irc_t *irc, char **cmd); +static void bitlbee_whatsnew(irc_t *irc); -static void cmd_identify( irc_t *irc, char **cmd ) +static void cmd_identify(irc_t *irc, char **cmd) { storage_status_t status; gboolean load = TRUE; char *password = cmd[1]; - - if( irc->status & USTATUS_IDENTIFIED ) - { - irc_rootmsg( irc, "You're already logged in." ); + + if (irc->status & USTATUS_IDENTIFIED) { + irc_rootmsg(irc, "You're already logged in."); return; } - - if( cmd[1] == NULL ) - { - } - else if( strncmp( cmd[1], "-no", 3 ) == 0 ) - { + + if (cmd[1] == NULL) { + } else if (strncmp(cmd[1], "-no", 3) == 0) { load = FALSE; password = cmd[2]; - if( password == NULL ) + if (password == NULL) { irc->status |= OPER_HACK_IDENTIFY_NOLOAD; - } - else if( strncmp( cmd[1], "-force", 6 ) == 0 ) - { + } + } else if (strncmp(cmd[1], "-force", 6) == 0) { password = cmd[2]; - if( password == NULL ) + if (password == NULL) { irc->status |= OPER_HACK_IDENTIFY_FORCE; - } - else if( irc->b->accounts != NULL ) - { - irc_rootmsg( irc, - "You're trying to identify yourself, but already have " - "at least one IM account set up. " - "Use \x02identify -noload\x02 or \x02identify -force\x02 " - "instead (see \x02help identify\x02)." ); + } + } else if (irc->b->accounts != NULL) { + irc_rootmsg(irc, + "You're trying to identify yourself, but already have " + "at least one IM account set up. " + "Use \x02identify -noload\x02 or \x02identify -force\x02 " + "instead (see \x02help identify\x02)."); return; } - - if( password == NULL ) - { - irc_rootmsg( irc, "About to identify, use /OPER to enter the password" ); + + if (password == NULL) { + irc_rootmsg(irc, "About to identify, use /OPER to enter the password"); irc->status |= OPER_HACK_IDENTIFY; return; } - - if( load ) - status = storage_load( irc, password ); - else - status = storage_check_pass( irc->user->nick, password ); - + + if (load) { + status = storage_load(irc, password); + } else { + status = storage_check_pass(irc->user->nick, password); + } + switch (status) { case STORAGE_INVALID_PASSWORD: - irc_rootmsg( irc, "Incorrect password" ); + irc_rootmsg(irc, "Incorrect password"); break; case STORAGE_NO_SUCH_USER: - irc_rootmsg( irc, "The nick is (probably) not registered" ); + irc_rootmsg(irc, "The nick is (probably) not registered"); break; case STORAGE_OK: - irc_rootmsg( irc, "Password accepted%s", - load ? ", settings and accounts loaded" : "" ); - irc_setpass( irc, password ); + irc_rootmsg(irc, "Password accepted%s", + load ? ", settings and accounts loaded" : ""); + irc_setpass(irc, password); irc->status |= USTATUS_IDENTIFIED; - irc_umode_set( irc, "+R", 1 ); - - bitlbee_whatsnew( irc ); - + irc_umode_set(irc, "+R", 1); + + bitlbee_whatsnew(irc); + /* The following code is a bit hairy now. With takeover support, we shouldn't immediately auto_connect in case we're going to offer taking over an existing session. Do it in 200ms since that should give the parent process enough time to come back to us. */ - if( load ) - { - irc_channel_auto_joins( irc, NULL ); - if( !set_getbool( &irc->default_channel->set, "auto_join" ) ) - irc_channel_del_user( irc->default_channel, irc->user, - IRC_CDU_PART, "auto_join disabled " - "for this channel." ); - if( set_getbool( &irc->b->set, "auto_connect" ) ) - irc->login_source_id = b_timeout_add( 200, - cmd_identify_finish, irc ); + if (load) { + irc_channel_auto_joins(irc, NULL); + if (!set_getbool(&irc->default_channel->set, "auto_join")) { + irc_channel_del_user(irc->default_channel, irc->user, + IRC_CDU_PART, "auto_join disabled " + "for this channel."); + } + if (set_getbool(&irc->b->set, "auto_connect")) { + irc->login_source_id = b_timeout_add(200, + cmd_identify_finish, irc); + } } - + /* If ipc_child_identify() returns FALSE, it means we're already sure that there's no takeover target (only possible in 1-process daemon mode). Start auto_connect immediately. */ - if( !ipc_child_identify( irc ) && load ) - cmd_identify_finish( irc, 0, 0 ); - + if (!ipc_child_identify(irc) && load) { + cmd_identify_finish(irc, 0, 0); + } + break; case STORAGE_OTHER_ERROR: default: - irc_rootmsg( irc, "Unknown error while loading configuration" ); + irc_rootmsg(irc, "Unknown error while loading configuration"); break; } } -gboolean cmd_identify_finish( gpointer data, gint fd, b_input_condition cond ) +gboolean cmd_identify_finish(gpointer data, gint fd, b_input_condition cond) { char *account_on[] = { "account", "on", NULL }; irc_t *irc = data; - - if( set_getbool( &irc->b->set, "auto_connect" ) ) - cmd_account( irc, account_on ); - - b_event_remove( irc->login_source_id ); + + if (set_getbool(&irc->b->set, "auto_connect")) { + cmd_account(irc, account_on); + } + + b_event_remove(irc->login_source_id); irc->login_source_id = -1; return FALSE; } -static void cmd_register( irc_t *irc, char **cmd ) +static void cmd_register(irc_t *irc, char **cmd) { char s[16]; - - if( global.conf->authmode == AUTHMODE_REGISTERED ) - { - irc_rootmsg( irc, "This server does not allow registering new accounts" ); + + if (global.conf->authmode == AUTHMODE_REGISTERED) { + irc_rootmsg(irc, "This server does not allow registering new accounts"); return; } - - if( cmd[1] == NULL ) - { - irc_rootmsg( irc, "About to register, use /OPER to enter the password" ); + + if (cmd[1] == NULL) { + irc_rootmsg(irc, "About to register, use /OPER to enter the password"); irc->status |= OPER_HACK_REGISTER; return; } - switch( storage_save( irc, cmd[1], FALSE ) ) { - case STORAGE_ALREADY_EXISTS: - irc_rootmsg( irc, "Nick is already registered" ); - break; - - case STORAGE_OK: - irc_rootmsg( irc, "Account successfully created" ); - irc_setpass( irc, cmd[1] ); - irc->status |= USTATUS_IDENTIFIED; - irc_umode_set( irc, "+R", 1 ); - - /* Set this var now, or anyone who logs in to his/her - newly created account for the first time gets the - whatsnew story. */ - g_snprintf( s, sizeof( s ), "%d", BITLBEE_VERSION_CODE ); - set_setstr( &irc->b->set, "last_version", s ); - break; + switch (storage_save(irc, cmd[1], FALSE)) { + case STORAGE_ALREADY_EXISTS: + irc_rootmsg(irc, "Nick is already registered"); + break; - default: - irc_rootmsg( irc, "Error registering" ); - break; + case STORAGE_OK: + irc_rootmsg(irc, "Account successfully created"); + irc_setpass(irc, cmd[1]); + irc->status |= USTATUS_IDENTIFIED; + irc_umode_set(irc, "+R", 1); + + /* Set this var now, or anyone who logs in to his/her + newly created account for the first time gets the + whatsnew story. */ + g_snprintf(s, sizeof(s), "%d", BITLBEE_VERSION_CODE); + set_setstr(&irc->b->set, "last_version", s); + break; + + default: + irc_rootmsg(irc, "Error registering"); + break; } } -static void cmd_drop( irc_t *irc, char **cmd ) +static void cmd_drop(irc_t *irc, char **cmd) { storage_status_t status; - - status = storage_remove (irc->user->nick, cmd[1]); + + status = storage_remove(irc->user->nick, cmd[1]); switch (status) { case STORAGE_NO_SUCH_USER: - irc_rootmsg( irc, "That account does not exist" ); + irc_rootmsg(irc, "That account does not exist"); break; case STORAGE_INVALID_PASSWORD: - irc_rootmsg( irc, "Password invalid" ); + irc_rootmsg(irc, "Password invalid"); break; case STORAGE_OK: - irc_setpass( irc, NULL ); + irc_setpass(irc, NULL); irc->status &= ~USTATUS_IDENTIFIED; - irc_umode_set( irc, "-R", 1 ); - irc_rootmsg( irc, "Account `%s' removed", irc->user->nick ); + irc_umode_set(irc, "-R", 1); + irc_rootmsg(irc, "Account `%s' removed", irc->user->nick); break; default: - irc_rootmsg( irc, "Error: `%d'", status ); + irc_rootmsg(irc, "Error: `%d'", status); break; } } -static void cmd_save( irc_t *irc, char **cmd ) +static void cmd_save(irc_t *irc, char **cmd) { - if( ( irc->status & USTATUS_IDENTIFIED ) == 0 ) - irc_rootmsg( irc, "Please create an account first (see \x02help register\x02)" ); - else if( storage_save( irc, NULL, TRUE ) == STORAGE_OK ) - irc_rootmsg( irc, "Configuration saved" ); - else - irc_rootmsg( irc, "Configuration could not be saved!" ); + if ((irc->status & USTATUS_IDENTIFIED) == 0) { + irc_rootmsg(irc, "Please create an account first (see \x02help register\x02)"); + } else if (storage_save(irc, NULL, TRUE) == STORAGE_OK) { + irc_rootmsg(irc, "Configuration saved"); + } else { + irc_rootmsg(irc, "Configuration could not be saved!"); + } } -static void cmd_showset( irc_t *irc, set_t **head, char *key ) +static void cmd_showset(irc_t *irc, set_t **head, char *key) { set_t *set; char *val; - - if( ( val = set_getstr( head, key ) ) ) - irc_rootmsg( irc, "%s = `%s'", key, val ); - else if( !( set = set_find( head, key ) ) ) - { - irc_rootmsg( irc, "Setting `%s' does not exist.", key ); - if( *head == irc->b->set ) - irc_rootmsg( irc, "It might be an account or channel setting. " - "See \x02help account set\x02 and \x02help channel set\x02." ); + + if ((val = set_getstr(head, key))) { + irc_rootmsg(irc, "%s = `%s'", key, val); + } else if (!(set = set_find(head, key))) { + irc_rootmsg(irc, "Setting `%s' does not exist.", key); + if (*head == irc->b->set) { + irc_rootmsg(irc, "It might be an account or channel setting. " + "See \x02help account set\x02 and \x02help channel set\x02."); + } + } else if (set->flags & SET_PASSWORD) { + irc_rootmsg(irc, "%s = `********' (hidden)", key); + } else { + irc_rootmsg(irc, "%s is empty", key); } - else if( set->flags & SET_PASSWORD ) - irc_rootmsg( irc, "%s = `********' (hidden)", key ); - else - irc_rootmsg( irc, "%s is empty", key ); } -typedef set_t** (*cmd_set_findhead)( irc_t*, char* ); -typedef int (*cmd_set_checkflags)( irc_t*, set_t *set ); +typedef set_t** (*cmd_set_findhead)(irc_t*, char*); +typedef int (*cmd_set_checkflags)(irc_t*, set_t *set); -static int cmd_set_real( irc_t *irc, char **cmd, set_t **head, cmd_set_checkflags checkflags ) +static int cmd_set_real(irc_t *irc, char **cmd, set_t **head, cmd_set_checkflags checkflags) { char *set_name = NULL, *value = NULL; gboolean del = FALSE; - - if( cmd[1] && g_strncasecmp( cmd[1], "-del", 4 ) == 0 ) - { - MIN_ARGS( 2, 0 ); + + if (cmd[1] && g_strncasecmp(cmd[1], "-del", 4) == 0) { + MIN_ARGS(2, 0); set_name = cmd[2]; del = TRUE; - } - else - { + } else { set_name = cmd[1]; value = cmd[2]; } - - if( set_name && ( value || del ) ) - { - set_t *s = set_find( head, set_name ); + + if (set_name && (value || del)) { + set_t *s = set_find(head, set_name); int st; - - if( s && checkflags && checkflags( irc, s ) == 0 ) + + if (s && checkflags && checkflags(irc, s) == 0) { return 0; - - if( del ) - st = set_reset( head, set_name ); - else - st = set_setstr( head, set_name, value ); - - if( set_getstr( head, set_name ) == NULL && - set_find( head, set_name ) ) - { + } + + if (del) { + st = set_reset(head, set_name); + } else { + st = set_setstr(head, set_name, value); + } + + if (set_getstr(head, set_name) == NULL && + set_find(head, set_name)) { /* This happens when changing the passwd, for example. Showing these msgs instead gives slightly clearer feedback. */ - if( st ) - irc_rootmsg( irc, "Setting changed successfully" ); - else - irc_rootmsg( irc, "Failed to change setting" ); - } - else - { - cmd_showset( irc, head, set_name ); + if (st) { + irc_rootmsg(irc, "Setting changed successfully"); + } else { + irc_rootmsg(irc, "Failed to change setting"); + } + } else { + cmd_showset(irc, head, set_name); } - } - else if( set_name ) - { - cmd_showset( irc, head, set_name ); - } - else - { + } else if (set_name) { + cmd_showset(irc, head, set_name); + } else { set_t *s = *head; - while( s ) - { - if( set_isvisible( s ) ) - cmd_showset( irc, &s, s->key ); + while (s) { + if (set_isvisible(s)) { + cmd_showset(irc, &s, s->key); + } s = s->next; } } - + return 1; } -static int cmd_account_set_checkflags( irc_t *irc, set_t *s ) +static int cmd_account_set_checkflags(irc_t *irc, set_t *s) { account_t *a = s->data; - - if( a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY ) - { - irc_rootmsg( irc, "This setting can only be changed when the account is %s-line", "off" ); + + if (a->ic && s && s->flags & ACC_SET_OFFLINE_ONLY) { + irc_rootmsg(irc, "This setting can only be changed when the account is %s-line", "off"); return 0; - } - else if( !a->ic && s && s->flags & ACC_SET_ONLINE_ONLY ) - { - irc_rootmsg( irc, "This setting can only be changed when the account is %s-line", "on" ); + } else if (!a->ic && s && s->flags & ACC_SET_ONLINE_ONLY) { + irc_rootmsg(irc, "This setting can only be changed when the account is %s-line", "on"); return 0; } - + return 1; } -static void cmd_account( irc_t *irc, char **cmd ) +static void cmd_account(irc_t *irc, char **cmd) { account_t *a; int len; - - if( global.conf->authmode == AUTHMODE_REGISTERED && !( irc->status & USTATUS_IDENTIFIED ) ) - { - irc_rootmsg( irc, "This server only accepts registered users" ); + + if (global.conf->authmode == AUTHMODE_REGISTERED && !(irc->status & USTATUS_IDENTIFIED)) { + irc_rootmsg(irc, "This server only accepts registered users"); return; } - - len = strlen( cmd[1] ); - - if( len >= 1 && g_strncasecmp( cmd[1], "add", len ) == 0 ) - { + + len = strlen(cmd[1]); + + if (len >= 1 && g_strncasecmp(cmd[1], "add", len) == 0) { struct prpl *prpl; - - MIN_ARGS( 3 ); - - if( cmd[4] == NULL ) - { - for( a = irc->b->accounts; a; a = a->next ) - if( strcmp( a->pass, PASSWORD_PENDING ) == 0 ) - { - irc_rootmsg( irc, "Enter password for account %s " - "first (use /OPER)", a->tag ); + + MIN_ARGS(3); + + if (cmd[4] == NULL) { + for (a = irc->b->accounts; a; a = a->next) { + if (strcmp(a->pass, PASSWORD_PENDING) == 0) { + irc_rootmsg(irc, "Enter password for account %s " + "first (use /OPER)", a->tag); return; } - + } + irc->status |= OPER_HACK_ACCOUNT_PASSWORD; } - - prpl = find_protocol( cmd[2] ); - - if( prpl == NULL ) - { - irc_rootmsg( irc, "Unknown protocol" ); + + prpl = find_protocol(cmd[2]); + + if (prpl == NULL) { + irc_rootmsg(irc, "Unknown protocol"); return; } - - for( a = irc->b->accounts; a; a = a->next ) - if( a->prpl == prpl && prpl->handle_cmp( a->user, cmd[3] ) == 0 ) - irc_rootmsg( irc, "Warning: You already have an account with " - "protocol `%s' and username `%s'. Are you accidentally " - "trying to add it twice?", prpl->name, cmd[3] ); - - a = account_add( irc->b, prpl, cmd[3], cmd[4] ? cmd[4] : PASSWORD_PENDING ); - if( cmd[5] ) - { - irc_rootmsg( irc, "Warning: Passing a servername/other flags to `account add' " - "is now deprecated. Use `account set' instead." ); - set_setstr( &a->set, "server", cmd[5] ); + + for (a = irc->b->accounts; a; a = a->next) { + if (a->prpl == prpl && prpl->handle_cmp(a->user, cmd[3]) == 0) { + irc_rootmsg(irc, "Warning: You already have an account with " + "protocol `%s' and username `%s'. Are you accidentally " + "trying to add it twice?", prpl->name, cmd[3]); + } + } + + a = account_add(irc->b, prpl, cmd[3], cmd[4] ? cmd[4] : PASSWORD_PENDING); + if (cmd[5]) { + irc_rootmsg(irc, "Warning: Passing a servername/other flags to `account add' " + "is now deprecated. Use `account set' instead."); + set_setstr(&a->set, "server", cmd[5]); } - - irc_rootmsg( irc, "Account successfully added with tag %s", a->tag ); - - if( cmd[4] == NULL ) - { - set_t *oauth = set_find( &a->set, "oauth" ); - if( oauth && bool2int( set_value( oauth ) ) ) - { + + irc_rootmsg(irc, "Account successfully added with tag %s", a->tag); + + if (cmd[4] == NULL) { + set_t *oauth = set_find(&a->set, "oauth"); + if (oauth && bool2int(set_value(oauth))) { *a->pass = '\0'; - irc_rootmsg( irc, "No need to enter a password for this " - "account since it's using OAuth" ); - } - else - { - irc_rootmsg( irc, "You can now use the /OPER command to " - "enter the password" ); - if( oauth ) - irc_rootmsg( irc, "Alternatively, enable OAuth if " - "the account supports it: account %s " - "set oauth on", a->tag ); + irc_rootmsg(irc, "No need to enter a password for this " + "account since it's using OAuth"); + } else { + irc_rootmsg(irc, "You can now use the /OPER command to " + "enter the password"); + if (oauth) { + irc_rootmsg(irc, "Alternatively, enable OAuth if " + "the account supports it: account %s " + "set oauth on", a->tag); + } } } - + return; - } - else if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 ) - { + } else if (len >= 1 && g_strncasecmp(cmd[1], "list", len) == 0) { int i = 0; - - if( strchr( irc->umode, 'b' ) ) - irc_rootmsg( irc, "Account list:" ); - - for( a = irc->b->accounts; a; a = a->next ) - { + + if (strchr(irc->umode, 'b')) { + irc_rootmsg(irc, "Account list:"); + } + + for (a = irc->b->accounts; a; a = a->next) { char *con; - - if( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) + + if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { con = " (connected)"; - else if( a->ic ) + } else if (a->ic) { con = " (connecting)"; - else if( a->reconnect ) + } else if (a->reconnect) { con = " (awaiting reconnect)"; - else + } else { con = ""; - - irc_rootmsg( irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con ); - - i ++; + } + + irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); + + i++; } - irc_rootmsg( irc, "End of account list" ); - + irc_rootmsg(irc, "End of account list"); + return; - } - else if( cmd[2] ) - { + } else if (cmd[2]) { /* Try the following two only if cmd[2] == NULL */ - } - else if( len >= 2 && g_strncasecmp( cmd[1], "on", len ) == 0 ) - { - if ( irc->b->accounts ) - { - irc_rootmsg( irc, "Trying to get all accounts connected..." ); - - for( a = irc->b->accounts; a; a = a->next ) - if( !a->ic && a->auto_connect ) - { - if( strcmp( a->pass, PASSWORD_PENDING ) == 0 ) - irc_rootmsg( irc, "Enter password for account %s " - "first (use /OPER)", a->tag ); - else - account_on( irc->b, a ); + } else if (len >= 2 && g_strncasecmp(cmd[1], "on", len) == 0) { + if (irc->b->accounts) { + irc_rootmsg(irc, "Trying to get all accounts connected..."); + + for (a = irc->b->accounts; a; a = a->next) { + if (!a->ic && a->auto_connect) { + if (strcmp(a->pass, PASSWORD_PENDING) == 0) { + irc_rootmsg(irc, "Enter password for account %s " + "first (use /OPER)", a->tag); + } else { + account_on(irc->b, a); + } } - } - else - { - irc_rootmsg( irc, "No accounts known. Use `account add' to add one." ); + } + } else { + irc_rootmsg(irc, "No accounts known. Use `account add' to add one."); } - + return; - } - else if( len >= 2 && g_strncasecmp( cmd[1], "off", len ) == 0 ) - { - irc_rootmsg( irc, "Deactivating all active (re)connections..." ); - - for( a = irc->b->accounts; a; a = a->next ) - { - if( a->ic ) - account_off( irc->b, a ); - else if( a->reconnect ) - cancel_auto_reconnect( a ); + } else if (len >= 2 && g_strncasecmp(cmd[1], "off", len) == 0) { + irc_rootmsg(irc, "Deactivating all active (re)connections..."); + + for (a = irc->b->accounts; a; a = a->next) { + if (a->ic) { + account_off(irc->b, a); + } else if (a->reconnect) { + cancel_auto_reconnect(a); + } } - + return; } - - MIN_ARGS( 2 ); - len = strlen( cmd[2] ); - + + MIN_ARGS(2); + len = strlen(cmd[2]); + /* At least right now, don't accept on/off/set/del as account IDs even if they're a proper match, since people not familiar with the new syntax yet may get a confusing/nasty surprise. */ - if( g_strcasecmp( cmd[1], "on" ) == 0 || - g_strcasecmp( cmd[1], "off" ) == 0 || - g_strcasecmp( cmd[1], "set" ) == 0 || - g_strcasecmp( cmd[1], "del" ) == 0 || - ( a = account_get( irc->b, cmd[1] ) ) == NULL ) - { - irc_rootmsg( irc, "Could not find account `%s'.", cmd[1] ); - + if (g_strcasecmp(cmd[1], "on") == 0 || + g_strcasecmp(cmd[1], "off") == 0 || + g_strcasecmp(cmd[1], "set") == 0 || + g_strcasecmp(cmd[1], "del") == 0 || + (a = account_get(irc->b, cmd[1])) == NULL) { + irc_rootmsg(irc, "Could not find account `%s'.", cmd[1]); + return; } - - if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 ) - { - if( a->ic ) - { - irc_rootmsg( irc, "Account is still logged in, can't delete" ); - } - else - { - account_del( irc->b, a ); - irc_rootmsg( irc, "Account deleted" ); - } - } - else if( len >= 2 && g_strncasecmp( cmd[2], "on", len ) == 0 ) - { - if( a->ic ) - irc_rootmsg( irc, "Account already online" ); - else if( strcmp( a->pass, PASSWORD_PENDING ) == 0 ) - irc_rootmsg( irc, "Enter password for account %s " - "first (use /OPER)", a->tag ); - else - account_on( irc->b, a ); - } - else if( len >= 2 && g_strncasecmp( cmd[2], "off", len ) == 0 ) - { - if( a->ic ) - { - account_off( irc->b, a ); + + if (len >= 1 && g_strncasecmp(cmd[2], "del", len) == 0) { + if (a->ic) { + irc_rootmsg(irc, "Account is still logged in, can't delete"); + } else { + account_del(irc->b, a); + irc_rootmsg(irc, "Account deleted"); } - else if( a->reconnect ) - { - cancel_auto_reconnect( a ); - irc_rootmsg( irc, "Reconnect cancelled" ); + } else if (len >= 2 && g_strncasecmp(cmd[2], "on", len) == 0) { + if (a->ic) { + irc_rootmsg(irc, "Account already online"); + } else if (strcmp(a->pass, PASSWORD_PENDING) == 0) { + irc_rootmsg(irc, "Enter password for account %s " + "first (use /OPER)", a->tag); + } else { + account_on(irc->b, a); } - else - { - irc_rootmsg( irc, "Account already offline" ); + } else if (len >= 2 && g_strncasecmp(cmd[2], "off", len) == 0) { + if (a->ic) { + account_off(irc->b, a); + } else if (a->reconnect) { + cancel_auto_reconnect(a); + irc_rootmsg(irc, "Reconnect cancelled"); + } else { + irc_rootmsg(irc, "Account already offline"); } - } - else if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 ) - { - cmd_set_real( irc, cmd + 2, &a->set, cmd_account_set_checkflags ); - } - else - { - irc_rootmsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "account", cmd[2] ); + } else if (len >= 1 && g_strncasecmp(cmd[2], "set", len) == 0) { + cmd_set_real(irc, cmd + 2, &a->set, cmd_account_set_checkflags); + } else { + irc_rootmsg(irc, + "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "account", + cmd[2]); } } -static void cmd_channel( irc_t *irc, char **cmd ) +static void cmd_channel(irc_t *irc, char **cmd) { irc_channel_t *ic; int len; - - len = strlen( cmd[1] ); - - if( len >= 1 && g_strncasecmp( cmd[1], "list", len ) == 0 ) - { + + len = strlen(cmd[1]); + + if (len >= 1 && g_strncasecmp(cmd[1], "list", len) == 0) { GSList *l; int i = 0; - - if( strchr( irc->umode, 'b' ) ) - irc_rootmsg( irc, "Channel list:" ); - - for( l = irc->channels; l; l = l->next ) - { + + if (strchr(irc->umode, 'b')) { + irc_rootmsg(irc, "Channel list:"); + } + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - irc_rootmsg( irc, "%2d. %s, %s channel%s", i, ic->name, - set_getstr( &ic->set, "type" ), - ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : "" ); - - i ++; + + irc_rootmsg(irc, "%2d. %s, %s channel%s", i, ic->name, + set_getstr(&ic->set, "type"), + ic->flags & IRC_CHANNEL_JOINED ? " (joined)" : ""); + + i++; } - irc_rootmsg( irc, "End of channel list" ); - + irc_rootmsg(irc, "End of channel list"); + return; } - - if( ( ic = irc_channel_get( irc, cmd[1] ) ) == NULL ) - { + + if ((ic = irc_channel_get(irc, cmd[1])) == NULL) { /* If this doesn't match any channel, maybe this is the short syntax (only works when used inside a channel). */ - if( ( ic = irc->root->last_channel ) && - ( len = strlen( cmd[1] ) ) && - g_strncasecmp( cmd[1], "set", len ) == 0 ) - cmd_set_real( irc, cmd + 1, &ic->set, NULL ); - else - irc_rootmsg( irc, "Could not find channel `%s'", cmd[1] ); - + if ((ic = irc->root->last_channel) && + (len = strlen(cmd[1])) && + g_strncasecmp(cmd[1], "set", len) == 0) { + cmd_set_real(irc, cmd + 1, &ic->set, NULL); + } else { + irc_rootmsg(irc, "Could not find channel `%s'", cmd[1]); + } + return; } - - MIN_ARGS( 2 ); - len = strlen( cmd[2] ); - - if( len >= 1 && g_strncasecmp( cmd[2], "set", len ) == 0 ) - { - cmd_set_real( irc, cmd + 2, &ic->set, NULL ); - } - else if( len >= 1 && g_strncasecmp( cmd[2], "del", len ) == 0 ) - { - if( !( ic->flags & IRC_CHANNEL_JOINED ) && - ic != ic->irc->default_channel ) - { - irc_rootmsg( irc, "Channel %s deleted.", ic->name ); - irc_channel_free( ic ); + + MIN_ARGS(2); + len = strlen(cmd[2]); + + if (len >= 1 && g_strncasecmp(cmd[2], "set", len) == 0) { + cmd_set_real(irc, cmd + 2, &ic->set, NULL); + } else if (len >= 1 && g_strncasecmp(cmd[2], "del", len) == 0) { + if (!(ic->flags & IRC_CHANNEL_JOINED) && + ic != ic->irc->default_channel) { + irc_rootmsg(irc, "Channel %s deleted.", ic->name); + irc_channel_free(ic); + } else { + irc_rootmsg(irc, "Couldn't remove channel (main channel %s or " + "channels you're still in cannot be deleted).", + irc->default_channel->name); } - else - irc_rootmsg( irc, "Couldn't remove channel (main channel %s or " - "channels you're still in cannot be deleted).", - irc->default_channel->name ); - } - else - { - irc_rootmsg( irc, "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", cmd[1] ); + } else { + irc_rootmsg(irc, + "Unknown command: %s [...] %s. Please use \x02help commands\x02 to get a list of available commands.", "channel", + cmd[1]); } } -static void cmd_add( irc_t *irc, char **cmd ) +static void cmd_add(irc_t *irc, char **cmd) { account_t *a; int add_on_server = 1; char *handle = NULL, *s; - - if( g_strcasecmp( cmd[1], "-tmp" ) == 0 ) - { - MIN_ARGS( 3 ); + + if (g_strcasecmp(cmd[1], "-tmp") == 0) { + MIN_ARGS(3); add_on_server = 0; - cmd ++; + cmd++; } - - if( !( a = account_get( irc->b, cmd[1] ) ) ) - { - irc_rootmsg( irc, "Invalid account" ); + + if (!(a = account_get(irc->b, cmd[1]))) { + irc_rootmsg(irc, "Invalid account"); return; - } - else if( !( a->ic && ( a->ic->flags & OPT_LOGGED_IN ) ) ) - { - irc_rootmsg( irc, "That account is not on-line" ); + } else if (!(a->ic && (a->ic->flags & OPT_LOGGED_IN))) { + irc_rootmsg(irc, "That account is not on-line"); return; } - - if( cmd[3] ) - { - if( !nick_ok( irc, cmd[3] ) ) - { - irc_rootmsg( irc, "The requested nick `%s' is invalid", cmd[3] ); + + if (cmd[3]) { + if (!nick_ok(irc, cmd[3])) { + irc_rootmsg(irc, "The requested nick `%s' is invalid", cmd[3]); return; - } - else if( irc_user_by_name( irc, cmd[3] ) ) - { - irc_rootmsg( irc, "The requested nick `%s' already exists", cmd[3] ); + } else if (irc_user_by_name(irc, cmd[3])) { + irc_rootmsg(irc, "The requested nick `%s' already exists", cmd[3]); return; - } - else - { - nick_set_raw( a, cmd[2], cmd[3] ); + } else { + nick_set_raw(a, cmd[2], cmd[3]); } } - - if( ( a->flags & ACC_FLAG_HANDLE_DOMAINS ) && cmd[2][0] != '_' && - ( !( s = strchr( cmd[2], '@' ) ) || s[1] == '\0' ) ) - { + + if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' && + (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) { /* If there's no @ or it's the last char, append the user's domain name now. Exclude handles starting with a _ so adding _xmlconsole will keep working. */ - if( s ) + if (s) { *s = '\0'; - if( ( s = strchr( a->user, '@' ) ) ) - cmd[2] = handle = g_strconcat( cmd[2], s, NULL ); + } + if ((s = strchr(a->user, '@'))) { + cmd[2] = handle = g_strconcat(cmd[2], s, NULL); + } } - - if( add_on_server ) - { + + if (add_on_server) { irc_channel_t *ic; char *s, *group = NULL;; - - if( ( ic = irc->root->last_channel ) && - ( s = set_getstr( &ic->set, "fill_by" ) ) && - strcmp( s, "group" ) == 0 && - ( group = set_getstr( &ic->set, "group" ) ) ) - irc_rootmsg( irc, "Adding `%s' to contact list (group %s)", - cmd[2], group ); - else - irc_rootmsg( irc, "Adding `%s' to contact list", cmd[2] ); - - a->prpl->add_buddy( a->ic, cmd[2], group ); - } - else - { + + if ((ic = irc->root->last_channel) && + (s = set_getstr(&ic->set, "fill_by")) && + strcmp(s, "group") == 0 && + (group = set_getstr(&ic->set, "group"))) { + irc_rootmsg(irc, "Adding `%s' to contact list (group %s)", + cmd[2], group); + } else { + irc_rootmsg(irc, "Adding `%s' to contact list", cmd[2]); + } + + a->prpl->add_buddy(a->ic, cmd[2], group); + } else { bee_user_t *bu; irc_user_t *iu; - + /* Only for add -tmp. For regular adds, this callback will be called once the IM server confirms. */ - if( ( bu = bee_user_new( irc->b, a->ic, cmd[2], BEE_USER_LOCAL ) ) && - ( iu = bu->ui_data ) ) - irc_rootmsg( irc, "Temporarily assigned nickname `%s' " - "to contact `%s'", iu->nick, cmd[2] ); + if ((bu = bee_user_new(irc->b, a->ic, cmd[2], BEE_USER_LOCAL)) && + (iu = bu->ui_data)) { + irc_rootmsg(irc, "Temporarily assigned nickname `%s' " + "to contact `%s'", iu->nick, cmd[2]); + } } - - g_free( handle ); + + g_free(handle); } -static void cmd_remove( irc_t *irc, char **cmd ) +static void cmd_remove(irc_t *irc, char **cmd) { irc_user_t *iu; bee_user_t *bu; char *s; - - if( !( iu = irc_user_by_name( irc, cmd[1] ) ) || !( bu = iu->bu ) ) - { - irc_rootmsg( irc, "Buddy `%s' not found", cmd[1] ); + + if (!(iu = irc_user_by_name(irc, cmd[1])) || !(bu = iu->bu)) { + irc_rootmsg(irc, "Buddy `%s' not found", cmd[1]); return; } - s = g_strdup( bu->handle ); - - bu->ic->acc->prpl->remove_buddy( bu->ic, bu->handle, NULL ); - nick_del( bu ); - if( g_slist_find( irc->users, iu ) ) - bee_user_free( irc->b, bu ); - - irc_rootmsg( irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1] ); - g_free( s ); - + s = g_strdup(bu->handle); + + bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); + nick_del(bu); + if (g_slist_find(irc->users, iu)) { + bee_user_free(irc->b, bu); + } + + irc_rootmsg(irc, "Buddy `%s' (nick %s) removed from contact list", s, cmd[1]); + g_free(s); + return; } -static void cmd_info( irc_t *irc, char **cmd ) +static void cmd_info(irc_t *irc, char **cmd) { struct im_connection *ic; account_t *a; - - if( !cmd[2] ) - { - irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); - if( !iu || !iu->bu ) - { - irc_rootmsg( irc, "Nick `%s' does not exist", cmd[1] ); + + if (!cmd[2]) { + irc_user_t *iu = irc_user_by_name(irc, cmd[1]); + if (!iu || !iu->bu) { + irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); return; } ic = iu->bu->ic; cmd[2] = iu->bu->handle; - } - else if( !( a = account_get( irc->b, cmd[1] ) ) ) - { - irc_rootmsg( irc, "Invalid account" ); + } else if (!(a = account_get(irc->b, cmd[1]))) { + irc_rootmsg(irc, "Invalid account"); return; - } - else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) - { - irc_rootmsg( irc, "That account is not on-line" ); + } else if (!((ic = a->ic) && (a->ic->flags & OPT_LOGGED_IN))) { + irc_rootmsg(irc, "That account is not on-line"); return; } - - if( !ic->acc->prpl->get_info ) - { - irc_rootmsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - ic->acc->prpl->get_info( ic, cmd[2] ); + + if (!ic->acc->prpl->get_info) { + irc_rootmsg(irc, "Command `%s' not supported by this protocol", cmd[0]); + } else { + ic->acc->prpl->get_info(ic, cmd[2]); } } -static void cmd_rename( irc_t *irc, char **cmd ) +static void cmd_rename(irc_t *irc, char **cmd) { irc_user_t *iu, *old; - gboolean del = g_strcasecmp( cmd[1], "-del" ) == 0; - - iu = irc_user_by_name( irc, cmd[del ? 2 : 1] ); - - if( iu == NULL ) - { - irc_rootmsg( irc, "Nick `%s' does not exist", cmd[1] ); - } - else if( del ) - { - if( iu->bu ) - bee_irc_user_nick_reset( iu ); - irc_rootmsg( irc, "Nickname reset to `%s'", iu->nick ); - } - else if( iu == irc->user ) - { - irc_rootmsg( irc, "Use /nick to change your own nickname" ); - } - else if( !nick_ok( irc, cmd[2] ) ) - { - irc_rootmsg( irc, "Nick `%s' is invalid", cmd[2] ); - } - else if( ( old = irc_user_by_name( irc, cmd[2] ) ) && old != iu ) - { - irc_rootmsg( irc, "Nick `%s' already exists", cmd[2] ); - } - else - { - if( !irc_user_set_nick( iu, cmd[2] ) ) - { - irc_rootmsg( irc, "Error while changing nick" ); + gboolean del = g_strcasecmp(cmd[1], "-del") == 0; + + iu = irc_user_by_name(irc, cmd[del ? 2 : 1]); + + if (iu == NULL) { + irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); + } else if (del) { + if (iu->bu) { + bee_irc_user_nick_reset(iu); + } + irc_rootmsg(irc, "Nickname reset to `%s'", iu->nick); + } else if (iu == irc->user) { + irc_rootmsg(irc, "Use /nick to change your own nickname"); + } else if (!nick_ok(irc, cmd[2])) { + irc_rootmsg(irc, "Nick `%s' is invalid", cmd[2]); + } else if ((old = irc_user_by_name(irc, cmd[2])) && old != iu) { + irc_rootmsg(irc, "Nick `%s' already exists", cmd[2]); + } else { + if (!irc_user_set_nick(iu, cmd[2])) { + irc_rootmsg(irc, "Error while changing nick"); return; } - - if( iu == irc->root ) - { + + if (iu == irc->root) { /* If we're called internally (user did "set root_nick"), let's not go O(INF). :-) */ - if( strcmp( cmd[0], "set_rename" ) != 0 ) - set_setstr( &irc->b->set, "root_nick", cmd[2] ); - } - else if( iu->bu ) - { - nick_set( iu->bu, cmd[2] ); + if (strcmp(cmd[0], "set_rename") != 0) { + set_setstr(&irc->b->set, "root_nick", cmd[2]); + } + } else if (iu->bu) { + nick_set(iu->bu, cmd[2]); } - - irc_rootmsg( irc, "Nick successfully changed" ); + + irc_rootmsg(irc, "Nick successfully changed"); } } -char *set_eval_root_nick( set_t *set, char *new_nick ) +char *set_eval_root_nick(set_t *set, char *new_nick) { irc_t *irc = set->data; - - if( strcmp( irc->root->nick, new_nick ) != 0 ) - { + + if (strcmp(irc->root->nick, new_nick) != 0) { char *cmd[] = { "set_rename", irc->root->nick, new_nick, NULL }; - - cmd_rename( irc, cmd ); + + cmd_rename(irc, cmd); } - - return strcmp( irc->root->nick, new_nick ) == 0 ? new_nick : SET_INVALID; + + return strcmp(irc->root->nick, new_nick) == 0 ? new_nick : SET_INVALID; } -static void cmd_block( irc_t *irc, char **cmd ) +static void cmd_block(irc_t *irc, char **cmd) { struct im_connection *ic; account_t *a; - - if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic ) - { + + if (!cmd[2] && (a = account_get(irc->b, cmd[1])) && a->ic) { char *format; GSList *l; - - if( strchr( irc->umode, 'b' ) != NULL ) + + if (strchr(irc->umode, 'b') != NULL) { format = "%s\t%s"; - else + } else { format = "%-32.32s %-16.16s"; - - irc_rootmsg( irc, format, "Handle", "Nickname" ); - for( l = a->ic->deny; l; l = l->next ) - { - bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data ); + } + + irc_rootmsg(irc, format, "Handle", "Nickname"); + for (l = a->ic->deny; l; l = l->next) { + bee_user_t *bu = bee_user_by_handle(irc->b, a->ic, l->data); irc_user_t *iu = bu ? bu->ui_data : NULL; - irc_rootmsg( irc, format, l->data, iu ? iu->nick : "(none)" ); + irc_rootmsg(irc, format, l->data, iu ? iu->nick : "(none)"); } - irc_rootmsg( irc, "End of list." ); - + irc_rootmsg(irc, "End of list."); + return; - } - else if( !cmd[2] ) - { - irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); - if( !iu || !iu->bu ) - { - irc_rootmsg( irc, "Nick `%s' does not exist", cmd[1] ); + } else if (!cmd[2]) { + irc_user_t *iu = irc_user_by_name(irc, cmd[1]); + if (!iu || !iu->bu) { + irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); return; } ic = iu->bu->ic; cmd[2] = iu->bu->handle; - } - else if( !( a = account_get( irc->b, cmd[1] ) ) ) - { - irc_rootmsg( irc, "Invalid account" ); + } else if (!(a = account_get(irc->b, cmd[1]))) { + irc_rootmsg(irc, "Invalid account"); return; - } - else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) - { - irc_rootmsg( irc, "That account is not on-line" ); + } else if (!((ic = a->ic) && (a->ic->flags & OPT_LOGGED_IN))) { + irc_rootmsg(irc, "That account is not on-line"); return; } - - if( !ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit ) - { - irc_rootmsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - imc_rem_allow( ic, cmd[2] ); - imc_add_block( ic, cmd[2] ); - irc_rootmsg( irc, "Buddy `%s' moved from allow- to block-list", cmd[2] ); + + if (!ic->acc->prpl->add_deny || !ic->acc->prpl->rem_permit) { + irc_rootmsg(irc, "Command `%s' not supported by this protocol", cmd[0]); + } else { + imc_rem_allow(ic, cmd[2]); + imc_add_block(ic, cmd[2]); + irc_rootmsg(irc, "Buddy `%s' moved from allow- to block-list", cmd[2]); } } -static void cmd_allow( irc_t *irc, char **cmd ) +static void cmd_allow(irc_t *irc, char **cmd) { struct im_connection *ic; account_t *a; - - if( !cmd[2] && ( a = account_get( irc->b, cmd[1] ) ) && a->ic ) - { + + if (!cmd[2] && (a = account_get(irc->b, cmd[1])) && a->ic) { char *format; GSList *l; - - if( strchr( irc->umode, 'b' ) != NULL ) + + if (strchr(irc->umode, 'b') != NULL) { format = "%s\t%s"; - else + } else { format = "%-32.32s %-16.16s"; - - irc_rootmsg( irc, format, "Handle", "Nickname" ); - for( l = a->ic->permit; l; l = l->next ) - { - bee_user_t *bu = bee_user_by_handle( irc->b, a->ic, l->data ); + } + + irc_rootmsg(irc, format, "Handle", "Nickname"); + for (l = a->ic->permit; l; l = l->next) { + bee_user_t *bu = bee_user_by_handle(irc->b, a->ic, l->data); irc_user_t *iu = bu ? bu->ui_data : NULL; - irc_rootmsg( irc, format, l->data, iu ? iu->nick : "(none)" ); + irc_rootmsg(irc, format, l->data, iu ? iu->nick : "(none)"); } - irc_rootmsg( irc, "End of list." ); - + irc_rootmsg(irc, "End of list."); + return; - } - else if( !cmd[2] ) - { - irc_user_t *iu = irc_user_by_name( irc, cmd[1] ); - if( !iu || !iu->bu ) - { - irc_rootmsg( irc, "Nick `%s' does not exist", cmd[1] ); + } else if (!cmd[2]) { + irc_user_t *iu = irc_user_by_name(irc, cmd[1]); + if (!iu || !iu->bu) { + irc_rootmsg(irc, "Nick `%s' does not exist", cmd[1]); return; } ic = iu->bu->ic; cmd[2] = iu->bu->handle; - } - else if( !( a = account_get( irc->b, cmd[1] ) ) ) - { - irc_rootmsg( irc, "Invalid account" ); + } else if (!(a = account_get(irc->b, cmd[1]))) { + irc_rootmsg(irc, "Invalid account"); return; - } - else if( !( ( ic = a->ic ) && ( a->ic->flags & OPT_LOGGED_IN ) ) ) - { - irc_rootmsg( irc, "That account is not on-line" ); + } else if (!((ic = a->ic) && (a->ic->flags & OPT_LOGGED_IN))) { + irc_rootmsg(irc, "That account is not on-line"); return; } - - if( !ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit ) - { - irc_rootmsg( irc, "Command `%s' not supported by this protocol", cmd[0] ); - } - else - { - imc_rem_block( ic, cmd[2] ); - imc_add_allow( ic, cmd[2] ); - - irc_rootmsg( irc, "Buddy `%s' moved from block- to allow-list", cmd[2] ); + + if (!ic->acc->prpl->rem_deny || !ic->acc->prpl->add_permit) { + irc_rootmsg(irc, "Command `%s' not supported by this protocol", cmd[0]); + } else { + imc_rem_block(ic, cmd[2]); + imc_add_allow(ic, cmd[2]); + + irc_rootmsg(irc, "Buddy `%s' moved from block- to allow-list", cmd[2]); } } -static void cmd_yesno( irc_t *irc, char **cmd ) +static void cmd_yesno(irc_t *irc, char **cmd) { query_t *q = NULL; int numq = 0; - - if( irc->queries == NULL ) - { + + if (irc->queries == NULL) { /* Alright, alright, let's add a tiny easter egg here. */ static irc_t *last_irc = NULL; static time_t last_time = 0; @@ -1028,61 +925,57 @@ static void cmd_yesno( irc_t *irc, char **cmd ) "Yes?", "No?", }; - - if( last_irc == irc && time( NULL ) - last_time < 15 ) - { - if( ( ++times >= 3 ) ) - { - irc_rootmsg( irc, "%s", msg[rand()%(sizeof(msg)/sizeof(char*))] ); + + if (last_irc == irc && time(NULL) - last_time < 15) { + if ((++times >= 3)) { + irc_rootmsg(irc, "%s", msg[rand() % (sizeof(msg) / sizeof(char*))]); last_irc = NULL; times = 0; return; } - } - else - { - last_time = time( NULL ); + } else { + last_time = time(NULL); last_irc = irc; times = 0; } - - irc_rootmsg( irc, "Did I ask you something?" ); + + irc_rootmsg(irc, "Did I ask you something?"); return; } - + /* If there's an argument, the user seems to want to answer another question than the first/last (depending on the query_order setting) one. */ - if( cmd[1] ) - { - if( sscanf( cmd[1], "%d", &numq ) != 1 ) - { - irc_rootmsg( irc, "Invalid query number" ); + if (cmd[1]) { + if (sscanf(cmd[1], "%d", &numq) != 1) { + irc_rootmsg(irc, "Invalid query number"); return; } - - for( q = irc->queries; q; q = q->next, numq -- ) - if( numq == 0 ) + + for (q = irc->queries; q; q = q->next, numq--) { + if (numq == 0) { break; - - if( !q ) - { - irc_rootmsg( irc, "Uhm, I never asked you something like that..." ); + } + } + + if (!q) { + irc_rootmsg(irc, "Uhm, I never asked you something like that..."); return; } } - - if( g_strcasecmp( cmd[0], "yes" ) == 0 ) - query_answer( irc, q, 1 ); - else if( g_strcasecmp( cmd[0], "no" ) == 0 ) - query_answer( irc, q, 0 ); + + if (g_strcasecmp(cmd[0], "yes") == 0) { + query_answer(irc, q, 1); + } else if (g_strcasecmp(cmd[0], "no") == 0) { + query_answer(irc, q, 0); + } } -static void cmd_set( irc_t *irc, char **cmd ) +static void cmd_set(irc_t *irc, char **cmd) { - cmd_set_real( irc, cmd, &irc->b->set, NULL ); + cmd_set_real(irc, cmd, &irc->b->set, NULL); } -static void cmd_blist( irc_t *irc, char **cmd ) +static void cmd_blist(irc_t *irc, char **cmd) { int online = 0, away = 0, offline = 0, ismatch = 0; GSList *l; @@ -1091,343 +984,325 @@ static void cmd_blist( irc_t *irc, char **cmd ) char s[256]; char *format; int n_online = 0, n_away = 0, n_offline = 0; - - if( cmd[1] && g_strcasecmp( cmd[1], "all" ) == 0 ) + + if (cmd[1] && g_strcasecmp(cmd[1], "all") == 0) { online = offline = away = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "offline" ) == 0 ) + } else if (cmd[1] && g_strcasecmp(cmd[1], "offline") == 0) { offline = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "away" ) == 0 ) + } else if (cmd[1] && g_strcasecmp(cmd[1], "away") == 0) { away = 1; - else if( cmd[1] && g_strcasecmp( cmd[1], "online" ) == 0 ) + } else if (cmd[1] && g_strcasecmp(cmd[1], "online") == 0) { online = 1; - else + } else { online = away = 1; - - if( cmd[2] ) - regex = g_regex_new( cmd[2], G_REGEX_CASELESS, 0, &error ); - - if( error ) - { - irc_rootmsg( irc, error->message ); - g_error_free( error ); } - - if( strchr( irc->umode, 'b' ) != NULL ) + + if (cmd[2]) { + regex = g_regex_new(cmd[2], G_REGEX_CASELESS, 0, &error); + } + + if (error) { + irc_rootmsg(irc, error->message); + g_error_free(error); + } + + if (strchr(irc->umode, 'b') != NULL) { format = "%s\t%s\t%s"; - else + } else { format = "%-16.16s %-40.40s %s"; - - irc_rootmsg( irc, format, "Nick", "Handle/Account", "Status" ); - - if( irc->root->last_channel && - strcmp( set_getstr( &irc->root->last_channel->set, "type" ), "control" ) != 0 ) + } + + irc_rootmsg(irc, format, "Nick", "Handle/Account", "Status"); + + if (irc->root->last_channel && + strcmp(set_getstr(&irc->root->last_channel->set, "type"), "control") != 0) { irc->root->last_channel = NULL; - - for( l = irc->users; l; l = l->next ) - { + } + + for (l = irc->users; l; l = l->next) { irc_user_t *iu = l->data; bee_user_t *bu = iu->bu; - - if( !regex || g_regex_match( regex, iu->nick, 0, NULL ) ) + + if (!regex || g_regex_match(regex, iu->nick, 0, NULL)) { ismatch = 1; - else + } else { ismatch = 0; - - if( !bu || ( irc->root->last_channel && !irc_channel_wants_user( irc->root->last_channel, iu ) ) ) + } + + if (!bu || (irc->root->last_channel && !irc_channel_wants_user(irc->root->last_channel, iu))) { continue; - - if( ( bu->flags & ( BEE_USER_ONLINE | BEE_USER_AWAY ) ) == BEE_USER_ONLINE ) - { - if( ismatch == 1 && online == 1 ) - { + } + + if ((bu->flags & (BEE_USER_ONLINE | BEE_USER_AWAY)) == BEE_USER_ONLINE) { + if (ismatch == 1 && online == 1) { char st[256] = "Online"; - - if( bu->status_msg ) - g_snprintf( st, sizeof( st ) - 1, "Online (%s)", bu->status_msg ); - - g_snprintf( s, sizeof( s ) - 1, "%s %s", bu->handle, bu->ic->acc->tag ); - irc_rootmsg( irc, format, iu->nick, s, st ); + + if (bu->status_msg) { + g_snprintf(st, sizeof(st) - 1, "Online (%s)", bu->status_msg); + } + + g_snprintf(s, sizeof(s) - 1, "%s %s", bu->handle, bu->ic->acc->tag); + irc_rootmsg(irc, format, iu->nick, s, st); } - - n_online ++; + + n_online++; } - - if( ( bu->flags & BEE_USER_ONLINE ) && ( bu->flags & BEE_USER_AWAY ) ) - { - if( ismatch == 1 && away == 1 ) - { - g_snprintf( s, sizeof( s ) - 1, "%s %s", bu->handle, bu->ic->acc->tag ); - irc_rootmsg( irc, format, iu->nick, s, irc_user_get_away( iu ) ); + + if ((bu->flags & BEE_USER_ONLINE) && (bu->flags & BEE_USER_AWAY)) { + if (ismatch == 1 && away == 1) { + g_snprintf(s, sizeof(s) - 1, "%s %s", bu->handle, bu->ic->acc->tag); + irc_rootmsg(irc, format, iu->nick, s, irc_user_get_away(iu)); } - n_away ++; + n_away++; } - - if( !(bu->flags & BEE_USER_ONLINE) ) - { - if( ismatch == 1 && offline == 1 ) - { - g_snprintf( s, sizeof( s ) - 1, "%s %s", bu->handle, bu->ic->acc->tag ); - irc_rootmsg( irc, format, iu->nick, s, "Offline" ); + + if (!(bu->flags & BEE_USER_ONLINE)) { + if (ismatch == 1 && offline == 1) { + g_snprintf(s, sizeof(s) - 1, "%s %s", bu->handle, bu->ic->acc->tag); + irc_rootmsg(irc, format, iu->nick, s, "Offline"); } - n_offline ++; + n_offline++; } } - - irc_rootmsg( irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, n_away, n_offline ); - - if( regex ) - g_regex_unref( regex ); + + irc_rootmsg(irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online, + n_away, n_offline); + + if (regex) { + g_regex_unref(regex); + } } -static void cmd_qlist( irc_t *irc, char **cmd ) +static void cmd_qlist(irc_t *irc, char **cmd) { query_t *q = irc->queries; int num; - - if( !q ) - { - irc_rootmsg( irc, "There are no pending questions." ); + + if (!q) { + irc_rootmsg(irc, "There are no pending questions."); return; } - - irc_rootmsg( irc, "Pending queries:" ); - - for( num = 0; q; q = q->next, num ++ ) - if( q->ic ) /* Not necessary yet, but it might come later */ - irc_rootmsg( irc, "%d, %s: %s", num, q->ic->acc->tag, q->question ); - else - irc_rootmsg( irc, "%d, BitlBee: %s", num, q->question ); + + irc_rootmsg(irc, "Pending queries:"); + + for (num = 0; q; q = q->next, num++) { + if (q->ic) { /* Not necessary yet, but it might come later */ + irc_rootmsg(irc, "%d, %s: %s", num, q->ic->acc->tag, q->question); + } else { + irc_rootmsg(irc, "%d, BitlBee: %s", num, q->question); + } + } } -static void cmd_chat( irc_t *irc, char **cmd ) +static void cmd_chat(irc_t *irc, char **cmd) { account_t *acc; - - if( g_strcasecmp( cmd[1], "add" ) == 0 ) - { + + if (g_strcasecmp(cmd[1], "add") == 0) { char *channel, *s; struct irc_channel *ic; - - MIN_ARGS( 3 ); - - if( !( acc = account_get( irc->b, cmd[2] ) ) ) - { - irc_rootmsg( irc, "Invalid account" ); + + MIN_ARGS(3); + + if (!(acc = account_get(irc->b, cmd[2]))) { + irc_rootmsg(irc, "Invalid account"); return; - } - else if( !acc->prpl->chat_join ) - { - irc_rootmsg( irc, "Named chatrooms not supported on that account." ); + } else if (!acc->prpl->chat_join) { + irc_rootmsg(irc, "Named chatrooms not supported on that account."); return; } - - if( cmd[4] == NULL ) - { - channel = g_strdup( cmd[3] ); - if( ( s = strchr( channel, '@' ) ) ) + + if (cmd[4] == NULL) { + channel = g_strdup(cmd[3]); + if ((s = strchr(channel, '@'))) { *s = 0; + } + } else { + channel = g_strdup(cmd[4]); } - else - { - channel = g_strdup( cmd[4] ); - } - - if( strchr( CTYPES, channel[0] ) == NULL ) - { - s = g_strdup_printf( "#%s", channel ); - g_free( channel ); + + if (strchr(CTYPES, channel[0]) == NULL) { + s = g_strdup_printf("#%s", channel); + g_free(channel); channel = s; - - irc_channel_name_strip( channel ); - } - - if( ( ic = irc_channel_new( irc, channel ) ) && - set_setstr( &ic->set, "type", "chat" ) && - set_setstr( &ic->set, "chat_type", "room" ) && - set_setstr( &ic->set, "account", cmd[2] ) && - set_setstr( &ic->set, "room", cmd[3] ) ) - { - irc_rootmsg( irc, "Chatroom successfully added." ); + + irc_channel_name_strip(channel); } - else - { - if( ic ) - irc_channel_free( ic ); - - irc_rootmsg( irc, "Could not add chatroom." ); + + if ((ic = irc_channel_new(irc, channel)) && + set_setstr(&ic->set, "type", "chat") && + set_setstr(&ic->set, "chat_type", "room") && + set_setstr(&ic->set, "account", cmd[2]) && + set_setstr(&ic->set, "room", cmd[3])) { + irc_rootmsg(irc, "Chatroom successfully added."); + } else { + if (ic) { + irc_channel_free(ic); + } + + irc_rootmsg(irc, "Could not add chatroom."); } - g_free( channel ); - } - else if( g_strcasecmp( cmd[1], "with" ) == 0 ) - { + g_free(channel); + } else if (g_strcasecmp(cmd[1], "with") == 0) { irc_user_t *iu; - - MIN_ARGS( 2 ); - - if( ( iu = irc_user_by_name( irc, cmd[2] ) ) && - iu->bu && iu->bu->ic->acc->prpl->chat_with ) - { - if( !iu->bu->ic->acc->prpl->chat_with( iu->bu->ic, iu->bu->handle ) ) - { - irc_rootmsg( irc, "(Possible) failure while trying to open " - "a groupchat with %s.", iu->nick ); + + MIN_ARGS(2); + + if ((iu = irc_user_by_name(irc, cmd[2])) && + iu->bu && iu->bu->ic->acc->prpl->chat_with) { + if (!iu->bu->ic->acc->prpl->chat_with(iu->bu->ic, iu->bu->handle)) { + irc_rootmsg(irc, "(Possible) failure while trying to open " + "a groupchat with %s.", iu->nick); } + } else { + irc_rootmsg(irc, "Can't open a groupchat with %s.", cmd[2]); } - else - { - irc_rootmsg( irc, "Can't open a groupchat with %s.", cmd[2] ); - } - } - else if( g_strcasecmp( cmd[1], "list" ) == 0 || - g_strcasecmp( cmd[1], "set" ) == 0 || - g_strcasecmp( cmd[1], "del" ) == 0 ) - { - irc_rootmsg( irc, "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command." ); - cmd_channel( irc, cmd ); - } - else - { - irc_rootmsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", cmd[1] ); + } else if (g_strcasecmp(cmd[1], "list") == 0 || + g_strcasecmp(cmd[1], "set") == 0 || + g_strcasecmp(cmd[1], "del") == 0) { + irc_rootmsg(irc, + "Warning: The \002chat\002 command was mostly replaced with the \002channel\002 command."); + cmd_channel(irc, cmd); + } else { + irc_rootmsg(irc, + "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "chat", + cmd[1]); } } -static void cmd_group( irc_t *irc, char **cmd ) +static void cmd_group(irc_t *irc, char **cmd) { GSList *l; int len; - - len = strlen( cmd[1] ); - if( g_strncasecmp( cmd[1], "list", len ) == 0 ) - { + + len = strlen(cmd[1]); + if (g_strncasecmp(cmd[1], "list", len) == 0) { int n = 0; - - if( strchr( irc->umode, 'b' ) ) - irc_rootmsg( irc, "Group list:" ); - - for( l = irc->b->groups; l; l = l->next ) - { + + if (strchr(irc->umode, 'b')) { + irc_rootmsg(irc, "Group list:"); + } + + for (l = irc->b->groups; l; l = l->next) { bee_group_t *bg = l->data; - irc_rootmsg( irc, "%d. %s", n ++, bg->name ); + irc_rootmsg(irc, "%d. %s", n++, bg->name); } - irc_rootmsg( irc, "End of group list" ); - } - else if( g_strncasecmp(cmd[1], "info", len ) == 0 ) - { + irc_rootmsg(irc, "End of group list"); + } else if (g_strncasecmp(cmd[1], "info", len) == 0) { bee_group_t *bg; int n = 0; MIN_ARGS(2); - bg = bee_group_by_name( irc->b, cmd[2], FALSE ); - - if( bg ) - { - if( strchr(irc->umode, 'b') ) - irc_rootmsg( irc, "Members of %s:", cmd[2] ); - for( l = irc->b->users; l; l = l->next ) - { + bg = bee_group_by_name(irc->b, cmd[2], FALSE); + + if (bg) { + if (strchr(irc->umode, 'b')) { + irc_rootmsg(irc, "Members of %s:", cmd[2]); + } + for (l = irc->b->users; l; l = l->next) { bee_user_t *bu = l->data; - if( bu->group == bg ) - irc_rootmsg( irc, "%d. %s", n ++, bu->nick ? : bu->handle ); + if (bu->group == bg) { + irc_rootmsg(irc, "%d. %s", n++, bu->nick ? : bu->handle); + } } - irc_rootmsg( irc, "End of member list" ); + irc_rootmsg(irc, "End of member list"); + } else { + irc_rootmsg(irc, + "Unknown group: %s. Please use \x02group list\x02 to get a list of available groups.", + cmd[2]); } - else - irc_rootmsg( irc, "Unknown group: %s. Please use \x02group list\x02 to get a list of available groups.", cmd[2] ); - } - else - { - irc_rootmsg( irc, "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "group", cmd[1] ); + } else { + irc_rootmsg(irc, + "Unknown command: %s %s. Please use \x02help commands\x02 to get a list of available commands.", "group", + cmd[1]); } } -static void cmd_transfer( irc_t *irc, char **cmd ) +static void cmd_transfer(irc_t *irc, char **cmd) { GSList *files = irc->file_transfers; + enum { LIST, REJECT, CANCEL }; int subcmd = LIST; int fid; - if( !files ) - { - irc_rootmsg( irc, "No pending transfers" ); + if (!files) { + irc_rootmsg(irc, "No pending transfers"); return; } - if( cmd[1] && ( strcmp( cmd[1], "reject" ) == 0 ) ) - { + if (cmd[1] && (strcmp(cmd[1], "reject") == 0)) { subcmd = REJECT; - } - else if( cmd[1] && ( strcmp( cmd[1], "cancel" ) == 0 ) && - cmd[2] && ( sscanf( cmd[2], "%d", &fid ) == 1 ) ) - { + } else if (cmd[1] && (strcmp(cmd[1], "cancel") == 0) && + cmd[2] && (sscanf(cmd[2], "%d", &fid) == 1)) { subcmd = CANCEL; } - for( ; files; files = g_slist_next( files ) ) - { + for (; files; files = g_slist_next(files)) { file_transfer_t *file = files->data; - - switch( subcmd ) { + + switch (subcmd) { case LIST: - if ( file->status == FT_STATUS_LISTENING ) - irc_rootmsg( irc, - "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name); - else - { + if (file->status == FT_STATUS_LISTENING) { + irc_rootmsg(irc, + "Pending file(id %d): %s (Listening...)", file->local_id, file->file_name); + } else { int kb_per_s = 0; - time_t diff = time( NULL ) - file->started ? : 1; - if ( ( file->started > 0 ) && ( file->bytes_transferred > 0 ) ) + time_t diff = time(NULL) - file->started ? : 1; + if ((file->started > 0) && (file->bytes_transferred > 0)) { kb_per_s = file->bytes_transferred / 1024 / diff; - - irc_rootmsg( irc, - "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, file->file_name, - file->bytes_transferred/1024, file->file_size/1024, kb_per_s); + } + + irc_rootmsg(irc, + "Pending file(id %d): %s (%10zd/%zd kb, %d kb/s)", file->local_id, + file->file_name, + file->bytes_transferred / 1024, file->file_size / 1024, kb_per_s); } break; case REJECT: - if( file->status == FT_STATUS_LISTENING ) - { - irc_rootmsg( irc, "Rejecting file transfer for %s", file->file_name ); - imcb_file_canceled( file->ic, file, "Denied by user" ); + if (file->status == FT_STATUS_LISTENING) { + irc_rootmsg(irc, "Rejecting file transfer for %s", file->file_name); + imcb_file_canceled(file->ic, file, "Denied by user"); } break; case CANCEL: - if( file->local_id == fid ) - { - irc_rootmsg( irc, "Canceling file transfer for %s", file->file_name ); - imcb_file_canceled( file->ic, file, "Canceled by user" ); + if (file->local_id == fid) { + irc_rootmsg(irc, "Canceling file transfer for %s", file->file_name); + imcb_file_canceled(file->ic, file, "Canceled by user"); } break; } } } -static void cmd_nick( irc_t *irc, char **cmd ) +static void cmd_nick(irc_t *irc, char **cmd) { - irc_rootmsg( irc, "This command is deprecated. Try: account %s set display_name", cmd[1] ); + irc_rootmsg(irc, "This command is deprecated. Try: account %s set display_name", cmd[1]); } /* Maybe this should be a stand-alone command as well? */ -static void bitlbee_whatsnew( irc_t *irc ) +static void bitlbee_whatsnew(irc_t *irc) { - int last = set_getint( &irc->b->set, "last_version" ); + int last = set_getint(&irc->b->set, "last_version"); char s[16], *msg; - - if( last >= BITLBEE_VERSION_CODE ) + + if (last >= BITLBEE_VERSION_CODE) { return; - - msg = help_get_whatsnew( &(global.help), last ); - - if( msg ) - irc_rootmsg( irc, "%s: This seems to be your first time using this " - "this version of BitlBee. Here's a list of new " - "features you may like to know about:\n\n%s\n", - irc->user->nick, msg ); - - g_free( msg ); - - g_snprintf( s, sizeof( s ), "%d", BITLBEE_VERSION_CODE ); - set_setstr( &irc->b->set, "last_version", s ); + } + + msg = help_get_whatsnew(&(global.help), last); + + if (msg) { + irc_rootmsg(irc, "%s: This seems to be your first time using this " + "this version of BitlBee. Here's a list of new " + "features you may like to know about:\n\n%s\n", + irc->user->nick, msg); + } + + g_free(msg); + + g_snprintf(s, sizeof(s), "%d", BITLBEE_VERSION_CODE); + set_setstr(&irc->b->set, "last_version", s); } /* IMPORTANT: Keep this list sorted! The short command logic needs that. */ @@ -1442,7 +1317,7 @@ command_t root_commands[] = { { "drop", 1, cmd_drop, 0 }, { "ft", 0, cmd_transfer, 0 }, { "group", 1, cmd_group, 0 }, - { "help", 0, cmd_help, 0 }, + { "help", 0, cmd_help, 0 }, { "identify", 0, cmd_identify, 0 }, { "info", 1, cmd_info, 0 }, { "nick", 1, cmd_nick, 0 }, @@ -1467,30 +1342,31 @@ command_t root_commands[] = { { NULL }, { NULL }, }; -static const int num_root_commands = sizeof( root_commands ) / sizeof( command_t ); +static const int num_root_commands = sizeof(root_commands) / sizeof(command_t); -gboolean root_command_add( const char *command, int params, void (*func)(irc_t *, char **args), int flags ) +gboolean root_command_add(const char *command, int params, void (*func)(irc_t *, char **args), int flags) { int i; - - if( root_commands[num_root_commands-2].command ) + + if (root_commands[num_root_commands - 2].command) { /* Planning fail! List is full. */ return FALSE; - - for( i = 0; root_commands[i].command; i++ ) - { - if( g_strcasecmp( root_commands[i].command, command ) == 0 ) + } + + for (i = 0; root_commands[i].command; i++) { + if (g_strcasecmp(root_commands[i].command, command) == 0) { return FALSE; - else if( g_strcasecmp( root_commands[i].command, command ) > 0 ) + } else if (g_strcasecmp(root_commands[i].command, command) > 0) { break; + } } - memmove( root_commands + i + 1, root_commands + i, - sizeof( command_t ) * ( num_root_commands - i - 1 ) ); - - root_commands[i].command = g_strdup( command ); + memmove(root_commands + i + 1, root_commands + i, + sizeof(command_t) * (num_root_commands - i - 1)); + + root_commands[i].command = g_strdup(command); root_commands[i].required_parameters = params; root_commands[i].execute = func; root_commands[i].flags = flags; - + return TRUE; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2013 Wilmer van der Gaast and others * @@ -29,246 +29,258 @@ /* Used to use NULL for this, but NULL is actually a "valid" value. */ char *SET_INVALID = "nee"; -set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data ) +set_t *set_add(set_t **head, const char *key, const char *def, set_eval eval, void *data) { - set_t *s = set_find( head, key ); - + set_t *s = set_find(head, key); + /* Possibly the setting already exists. If it doesn't exist yet, we create it. If it does, we'll just change the default. */ - if( !s ) - { - if( ( s = *head ) ) - { + if (!s) { + if ((s = *head)) { /* Sorted insertion. Special-case insertion at the start. */ - if( strcmp( key, s->key ) < 0 ) - { - s = g_new0( set_t, 1 ); + if (strcmp(key, s->key) < 0) { + s = g_new0(set_t, 1); s->next = *head; *head = s; - } - else - { - while( s->next && strcmp( key, s->next->key ) > 0 ) + } else { + while (s->next && strcmp(key, s->next->key) > 0) { s = s->next; + } set_t *last_next = s->next; - s->next = g_new0( set_t, 1 ); + s->next = g_new0(set_t, 1); s = s->next; s->next = last_next; } + } else { + s = *head = g_new0(set_t, 1); } - else - { - s = *head = g_new0( set_t, 1 ); - } - s->key = g_strdup( key ); + s->key = g_strdup(key); } - - if( s->def ) - { - g_free( s->def ); + + if (s->def) { + g_free(s->def); s->def = NULL; } - if( def ) s->def = g_strdup( def ); - + if (def) { + s->def = g_strdup(def); + } + s->eval = eval; s->data = data; - + return s; } -set_t *set_find( set_t **head, const char *key ) +set_t *set_find(set_t **head, const char *key) { set_t *s = *head; - - while( s ) - { - if( g_strcasecmp( s->key, key ) == 0 || - ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) ) + + while (s) { + if (g_strcasecmp(s->key, key) == 0 || + (s->old_key && g_strcasecmp(s->old_key, key) == 0)) { break; + } s = s->next; } - + return s; } -char *set_getstr( set_t **head, const char *key ) +char *set_getstr(set_t **head, const char *key) { - set_t *s = set_find( head, key ); - - if( !s || ( !s->value && !s->def ) ) + set_t *s = set_find(head, key); + + if (!s || (!s->value && !s->def)) { return NULL; - - return set_value( s ); + } + + return set_value(s); } -int set_getint( set_t **head, const char *key ) +int set_getint(set_t **head, const char *key) { - char *s = set_getstr( head, key ); + char *s = set_getstr(head, key); int i = 0; - - if( !s ) + + if (!s) { return 0; - - if( sscanf( s, "%d", &i ) != 1 ) + } + + if (sscanf(s, "%d", &i) != 1) { return 0; - + } + return i; } -int set_getbool( set_t **head, const char *key ) +int set_getbool(set_t **head, const char *key) { - char *s = set_getstr( head, key ); - - if( !s ) + char *s = set_getstr(head, key); + + if (!s) { return 0; - - return bool2int( s ); + } + + return bool2int(s); } -int set_isvisible( set_t *set ) +int set_isvisible(set_t *set) { /* the default value is not stored in value, only in def */ - return !( ( set->flags & SET_HIDDEN ) || - ( ( set->flags & SET_HIDDEN_DEFAULT ) && - ( set->value == NULL ) ) ); + return !((set->flags & SET_HIDDEN) || + ((set->flags & SET_HIDDEN_DEFAULT) && + (set->value == NULL))); } -int set_setstr( set_t **head, const char *key, char *value ) +int set_setstr(set_t **head, const char *key, char *value) { - set_t *s = set_find( head, key ); + set_t *s = set_find(head, key); char *nv = value; - - if( !s ) + + if (!s) { /* Used to do this, but it never really made sense. s = set_add( head, key, NULL, NULL, NULL ); */ return 0; - - if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 ) + } + + if (value == NULL && (s->flags & SET_NULL_OK) == 0) { return 0; - + } + /* Call the evaluator. For invalid values, evaluators should now return SET_INVALID, but previously this was NULL. Try to handle that too if NULL is not an allowed value for this setting. */ - if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID || - ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) ) + if (s->eval && ((nv = s->eval(s, value)) == SET_INVALID || + ((s->flags & SET_NULL_OK) == 0 && nv == NULL))) { return 0; - - if( s->value ) - { - g_free( s->value ); + } + + if (s->value) { + g_free(s->value); s->value = NULL; } - + /* If there's a default setting and it's equal to what we're trying to set, stick with s->value = NULL. Otherwise, remember the setting. */ - if( !s->def || ( strcmp( nv, s->def ) != 0 ) ) - s->value = g_strdup( nv ); - - if( nv != value ) - g_free( nv ); - + if (!s->def || (strcmp(nv, s->def) != 0)) { + s->value = g_strdup(nv); + } + + if (nv != value) { + g_free(nv); + } + return 1; } -int set_setint( set_t **head, const char *key, int value ) +int set_setint(set_t **head, const char *key, int value) { - char *s = g_strdup_printf( "%d", value ); - int retval = set_setstr( head, key, s ); - g_free( s ); + char *s = g_strdup_printf("%d", value); + int retval = set_setstr(head, key, s); + + g_free(s); return retval; } -void set_del( set_t **head, const char *key ) +void set_del(set_t **head, const char *key) { set_t *s = *head, *t = NULL; - - while( s ) - { - if( g_strcasecmp( s->key, key ) == 0 ) + + while (s) { + if (g_strcasecmp(s->key, key) == 0) { break; - s = (t=s)->next; + } + s = (t = s)->next; } - if( s ) - { - if( t ) + if (s) { + if (t) { t->next = s->next; - else + } else { *head = s->next; - - g_free( s->key ); - g_free( s->old_key ); - g_free( s->value ); - g_free( s->def ); - g_free( s ); + } + + g_free(s->key); + g_free(s->old_key); + g_free(s->value); + g_free(s->def); + g_free(s); } } -int set_reset( set_t **head, const char *key ) +int set_reset(set_t **head, const char *key) { set_t *s; - - s = set_find( head, key ); - if( s ) - return set_setstr( head, key, s->def ); - + + s = set_find(head, key); + if (s) { + return set_setstr(head, key, s->def); + } + return 0; } -char *set_eval_int( set_t *set, char *value ) +char *set_eval_int(set_t *set, char *value) { char *s = value; - + /* Allow a minus at the first position. */ - if( *s == '-' ) - s ++; - - for( ; *s; s ++ ) - if( !g_ascii_isdigit( *s ) ) + if (*s == '-') { + s++; + } + + for (; *s; s++) { + if (!g_ascii_isdigit(*s)) { return SET_INVALID; - + } + } + return value; } -char *set_eval_bool( set_t *set, char *value ) +char *set_eval_bool(set_t *set, char *value) { - return is_bool( value ) ? value : SET_INVALID; + return is_bool(value) ? value : SET_INVALID; } -char *set_eval_list( set_t *set, char *value ) +char *set_eval_list(set_t *set, char *value) { GSList *options = set->eval_data, *opt; - - for( opt = options; opt; opt = opt->next ) - if( strcmp( value, opt->data ) == 0 ) + + for (opt = options; opt; opt = opt->next) { + if (strcmp(value, opt->data) == 0) { return value; - + } + } + /* TODO: It'd be nice to show the user a list of allowed values, but we don't have enough context here to do that. May want to fix that. */ - + return NULL; } -char *set_eval_to_char( set_t *set, char *value ) +char *set_eval_to_char(set_t *set, char *value) { - char *s = g_new( char, 3 ); - - if( *value == ' ' ) - strcpy( s, " " ); - else - sprintf( s, "%c ", *value ); - + char *s = g_new(char, 3); + + if (*value == ' ') { + strcpy(s, " "); + } else { + sprintf(s, "%c ", *value); + } + return s; } -char *set_eval_oauth( set_t *set, char *value ) +char *set_eval_oauth(set_t *set, char *value) { account_t *acc = set->data; - - if( bool2int( value ) && strcmp( acc->pass, PASSWORD_PENDING ) == 0 ) + + if (bool2int(value) && strcmp(acc->pass, PASSWORD_PENDING) == 0) { *acc->pass = '\0'; - - return set_eval_bool( set, value ); + } + + return set_eval_bool(set, value); } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2006 Wilmer van der Gaast and others * @@ -31,19 +31,18 @@ struct set; /* This used to be specific to irc_t structures, but it's more generic now (so it can also be used for account_t structs). It's pretty simple, but so far pretty useful. - + In short, it just keeps a linked list of settings/variables and it also remembers a default value for every setting. And to prevent the user from setting invalid values, you can write an evaluator function for every setting, which can check a new value and block it by returning NULL, or replace it by returning a new value. See struct set.eval. */ -typedef char *(*set_eval) ( struct set *set, char *value ); +typedef char *(*set_eval) (struct set *set, char *value); extern char *SET_INVALID; -typedef enum -{ +typedef enum { SET_NOSAVE = 0x0001, /* Don't save this setting (i.e. stored elsewhere). */ SET_NULL_OK = 0x0100, /* set->value == NULL is allowed. */ SET_HIDDEN = 0x0200, /* Don't show up in setting lists. Mostly for internal storage. */ @@ -51,11 +50,10 @@ typedef enum SET_HIDDEN_DEFAULT = 0x0800, /* Hide unless changed from default. */ } set_flags_t; -typedef struct set -{ +typedef struct set { void *data; /* Here you can save a pointer to the object this settings belongs to. */ - + char *key; char *old_key; /* Previously known as; for smooth upgrades. */ char *value; @@ -65,9 +63,9 @@ typedef struct set you read a setting, don't forget about this! In fact, you should only read values using set_getstr/int(). */ - + set_flags_t flags; /* Mostly defined per user. */ - + /* Eval: Returns SET_INVALID if the value is incorrect, exactly the passed value variable, or a corrected value. In case of the latter, set_setstr() will free() the returned string! */ @@ -76,42 +74,42 @@ typedef struct set struct set *next; } set_t; -#define set_value( set ) ((set)->value) ? ((set)->value) : ((set)->def) +#define set_value(set) ((set)->value) ? ((set)->value) : ((set)->def) /* Should be pretty clear. */ -set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data ); +set_t *set_add(set_t **head, const char *key, const char *def, set_eval eval, void *data); /* Returns the raw set_t. Might be useful sometimes. */ -set_t *set_find( set_t **head, const char *key ); +set_t *set_find(set_t **head, const char *key); /* Returns a pointer to the string value of this setting. Don't modify the returned string, and don't free() it! */ -G_MODULE_EXPORT char *set_getstr( set_t **head, const char *key ); +G_MODULE_EXPORT char *set_getstr(set_t **head, const char *key); /* Get an integer. In previous versions set_getint() was also used to read boolean values, but this SHOULD be done with set_getbool() now! */ -G_MODULE_EXPORT int set_getint( set_t **head, const char *key ); -G_MODULE_EXPORT int set_getbool( set_t **head, const char *key ); +G_MODULE_EXPORT int set_getint(set_t **head, const char *key); +G_MODULE_EXPORT int set_getbool(set_t **head, const char *key); /* set_setstr() strdup()s the given value, so after using this function you can free() it, if you want. */ -int set_setstr( set_t **head, const char *key, char *value ); -int set_setint( set_t **head, const char *key, int value ); -void set_del( set_t **head, const char *key ); -int set_reset( set_t **head, const char *key ); +int set_setstr(set_t **head, const char *key, char *value); +int set_setint(set_t **head, const char *key, int value); +void set_del(set_t **head, const char *key); +int set_reset(set_t **head, const char *key); /* returns true if a setting shall be shown to the user */ -int set_isvisible( set_t *set ); +int set_isvisible(set_t *set); /* Two very useful generic evaluators. */ -char *set_eval_int( set_t *set, char *value ); -char *set_eval_bool( set_t *set, char *value ); +char *set_eval_int(set_t *set, char *value); +char *set_eval_bool(set_t *set, char *value); /* Another more complicated one. */ -char *set_eval_list( set_t *set, char *value ); +char *set_eval_list(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_oauth( set_t *set, char *value ); +char *set_eval_to_char(set_t *set, char *value); +char *set_eval_oauth(set_t *set, char *value); #endif /* __SET_H__ */ @@ -9,4 +9,4 @@ #define sock_make_nonblocking(fd) fcntl(fd, F_SETFL, O_NONBLOCK) #define sock_make_blocking(fd) fcntl(fd, F_SETFL, 0) #define sockerr_again() (errno == EINPROGRESS || errno == EINTR) -void closesocket( int fd ); +void closesocket(int fd); @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -45,15 +45,18 @@ static storage_t *storage_init_single(const char *name) for (gl = storage_backends; gl; gl = gl->next) { st = gl->data; - if (strcmp(st->name, name) == 0) + if (strcmp(st->name, name) == 0) { break; + } } - if (gl == NULL) + if (gl == NULL) { return NULL; + } - if (st->init) + if (st->init) { st->init(); + } return st; } @@ -63,29 +66,31 @@ GList *storage_init(const char *primary, char **migrate) GList *ret = NULL; int i; storage_t *storage; - + register_storage_backend(&storage_xml); - + storage = storage_init_single(primary); - if (storage == NULL && storage->save == NULL) + if (storage == NULL && storage->save == NULL) { return NULL; + } ret = g_list_append(ret, storage); for (i = 0; migrate && migrate[i]; i++) { storage = storage_init_single(migrate[i]); - - if (storage) + + if (storage) { ret = g_list_append(ret, storage); + } } return ret; } -storage_status_t storage_check_pass (const char *nick, const char *password) +storage_status_t storage_check_pass(const char *nick, const char *password) { GList *gl; - + /* Loop until we don't get NO_SUCH_USER */ for (gl = global.storage; gl; gl = gl->next) { @@ -93,85 +98,88 @@ storage_status_t storage_check_pass (const char *nick, const char *password) storage_status_t status; status = st->check_pass(nick, password); - if (status != STORAGE_NO_SUCH_USER) + if (status != STORAGE_NO_SUCH_USER) { return status; + } } - + return STORAGE_NO_SUCH_USER; } -storage_status_t storage_load (irc_t * irc, const char *password) +storage_status_t storage_load(irc_t * irc, const char *password) { GList *gl; - - if (irc && irc->status & USTATUS_IDENTIFIED) + + if (irc && irc->status & USTATUS_IDENTIFIED) { return STORAGE_OTHER_ERROR; - + } + /* Loop until we don't get NO_SUCH_USER */ for (gl = global.storage; gl; gl = gl->next) { storage_t *st = gl->data; storage_status_t status; status = st->load(irc, password); - if (status == STORAGE_OK) - { + if (status == STORAGE_OK) { GSList *l; - for( l = irc_plugins; l; l = l->next ) - { + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->storage_load ) - p->storage_load( irc ); + if (p->storage_load) { + p->storage_load(irc); + } } return status; } - - if (status != STORAGE_NO_SUCH_USER) + + if (status != STORAGE_NO_SUCH_USER) { return status; + } } - + return STORAGE_NO_SUCH_USER; } -storage_status_t storage_save (irc_t *irc, char *password, int overwrite) +storage_status_t storage_save(irc_t *irc, char *password, int overwrite) { storage_status_t st; GSList *l; - + if (password != NULL) { /* Should only use this in the "register" command. */ - if (irc->password || overwrite) + if (irc->password || overwrite) { return STORAGE_OTHER_ERROR; - + } + irc_setpass(irc, password); } else if ((irc->status & USTATUS_IDENTIFIED) == 0) { return STORAGE_NO_SUCH_USER; } - - st = ((storage_t *)global.storage->data)->save(irc, overwrite); - - for( l = irc_plugins; l; l = l->next ) - { + + st = ((storage_t *) global.storage->data)->save(irc, overwrite); + + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->storage_save ) - p->storage_save( irc ); + if (p->storage_save) { + p->storage_save(irc); + } } - + if (password != NULL) { irc_setpass(irc, NULL); } - + return st; } -storage_status_t storage_remove (const char *nick, const char *password) +storage_status_t storage_remove(const char *nick, const char *password) { GList *gl; storage_status_t ret = STORAGE_OK; gboolean ok = FALSE; GSList *l; - - /* Remove this account from all storage backends. If this isn't - * done, the account will still be usable, it'd just be + + /* Remove this account from all storage backends. If this isn't + * done, the account will still be usable, it'd just be * loaded from a different backend. */ for (gl = global.storage; gl; gl = gl->next) { storage_t *st = gl->data; @@ -179,18 +187,20 @@ storage_status_t storage_remove (const char *nick, const char *password) status = st->remove(nick, password); ok |= status == STORAGE_OK; - if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) + if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) { ret = status; + } } - + /* If at least one succeeded, remove plugin data. */ - if( ok ) - for( l = irc_plugins; l; l = l->next ) - { + if (ok) { + for (l = irc_plugins; l; l = l->next) { irc_plugin_t *p = l->data; - if( p->storage_remove ) - p->storage_remove( nick ); + if (p->storage_remove) { + p->storage_remove(nick); + } } - + } + return ret; } @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2004 Wilmer van der Gaast and others * @@ -31,32 +31,32 @@ typedef enum { STORAGE_NO_SUCH_USER, STORAGE_INVALID_PASSWORD, STORAGE_ALREADY_EXISTS, - STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as - a database that is unreachable. log() will be + STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as + a database that is unreachable. log() will be used for the exact error message */ } storage_status_t; typedef struct { const char *name; - + /* May be set to NULL if not required */ - void (*init) (void); + void (*init)(void); - storage_status_t (*check_pass) (const char *nick, const char *password); + storage_status_t (*check_pass)(const char *nick, const char *password); - storage_status_t (*load) (irc_t *irc, const char *password); - storage_status_t (*save) (irc_t *irc, int overwrite); - storage_status_t (*remove) (const char *nick, const char *password); + storage_status_t (*load)(irc_t *irc, const char *password); + storage_status_t (*save)(irc_t *irc, int overwrite); + storage_status_t (*remove)(const char *nick, const char *password); /* May be NULL if not supported by backend */ - storage_status_t (*rename) (const char *onick, const char *nnick, const char *password); + storage_status_t (*rename)(const char *onick, const char *nnick, const char *password); } storage_t; -storage_status_t storage_check_pass (const char *nick, const char *password); +storage_status_t storage_check_pass(const char *nick, const char *password); -storage_status_t storage_load (irc_t * irc, const char *password); -storage_status_t storage_save (irc_t *irc, char *password, int overwrite); -storage_status_t storage_remove (const char *nick, const char *password); +storage_status_t storage_load(irc_t * irc, const char *password); +storage_status_t storage_save(irc_t *irc, char *password, int overwrite); +storage_status_t storage_remove(const char *nick, const char *password); void register_storage_backend(storage_t *); G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); diff --git a/storage_xml.c b/storage_xml.c index 553929e1..a1892e73 100644 --- a/storage_xml.c +++ b/storage_xml.c @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -32,8 +32,7 @@ #include <glib/gstdio.h> -typedef enum -{ +typedef enum { XML_PASS_CHECK_ONLY = -1, XML_PASS_UNKNOWN = 0, XML_PASS_WRONG, @@ -43,44 +42,47 @@ typedef enum /* To make it easier later when extending the format: */ #define XML_FORMAT_VERSION "1" -struct xml_parsedata -{ +struct xml_parsedata { irc_t *irc; - char given_nick[MAX_NICK_LENGTH+1]; + char given_nick[MAX_NICK_LENGTH + 1]; char *given_pass; }; -static void xml_init( void ) +static void xml_init(void) { - if( g_access( global.conf->configdir, F_OK ) != 0 ) - log_message( LOGLVL_WARNING, "The configuration directory `%s' does not exist. Configuration won't be saved.", global.conf->configdir ); - else if( g_access( global.conf->configdir, F_OK ) != 0 || - g_access( global.conf->configdir, W_OK ) != 0 ) - log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", global.conf->configdir ); + if (g_access(global.conf->configdir, F_OK) != 0) { + log_message(LOGLVL_WARNING, + "The configuration directory `%s' does not exist. Configuration won't be saved.", + global.conf->configdir); + } else if (g_access(global.conf->configdir, F_OK) != 0 || + g_access(global.conf->configdir, W_OK) != 0) { + log_message(LOGLVL_WARNING, "Permission problem: Can't read/write from/to `%s'.", + global.conf->configdir); + } } -static void handle_settings( struct xt_node *node, set_t **head ) +static void handle_settings(struct xt_node *node, set_t **head) { struct xt_node *c; - - for( c = node->children; ( c = xt_find_node( c, "setting" ) ); c = c->next ) - { - char *name = xt_find_attr( c, "name" ); - - if( !name ) + + for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { + char *name = xt_find_attr(c, "name"); + + if (!name) { continue; - - if( strcmp( node->name, "account" ) == 0 ) - { - set_t *s = set_find( head, name ); - if( s && ( s->flags & ACC_SET_ONLINE_ONLY ) ) + } + + if (strcmp(node->name, "account") == 0) { + set_t *s = set_find(head, name); + if (s && (s->flags & ACC_SET_ONLINE_ONLY)) { continue; /* U can't touch this! */ + } } - set_setstr( head, name, c->text ); + set_setstr(head, name, c->text); } } -static xt_status handle_account( struct xt_node *node, gpointer data ) +static xt_status handle_account(struct xt_node *node, gpointer data) { struct xml_parsedata *xd = data; char *protocol, *handle, *server, *password = NULL, *autoconnect, *tag; @@ -90,80 +92,84 @@ static xt_status handle_account( struct xt_node *node, gpointer data ) struct prpl *prpl = NULL; account_t *acc; struct xt_node *c; - - handle = xt_find_attr( node, "handle" ); - pass_b64 = xt_find_attr( node, "password" ); - server = xt_find_attr( node, "server" ); - autoconnect = xt_find_attr( node, "autoconnect" ); - tag = xt_find_attr( node, "tag" ); - - protocol = xt_find_attr( node, "protocol" ); - if( protocol ) - { - prpl = find_protocol( protocol ); - local = protocol_account_islocal( protocol ); + + handle = xt_find_attr(node, "handle"); + pass_b64 = xt_find_attr(node, "password"); + server = xt_find_attr(node, "server"); + autoconnect = xt_find_attr(node, "autoconnect"); + tag = xt_find_attr(node, "tag"); + + protocol = xt_find_attr(node, "protocol"); + if (protocol) { + prpl = find_protocol(protocol); + local = protocol_account_islocal(protocol); } - - if( !handle || !pass_b64 || !protocol || !prpl ) + + if (!handle || !pass_b64 || !protocol || !prpl) { return XT_ABORT; - else if( ( pass_len = base64_decode( pass_b64, (unsigned char**) &pass_cr ) ) && - arc_decode( pass_cr, pass_len, &password, xd->given_pass ) >= 0 ) - { - acc = account_add( xd->irc->b, prpl, handle, password ); - if( server ) - set_setstr( &acc->set, "server", server ); - if( autoconnect ) - set_setstr( &acc->set, "auto_connect", autoconnect ); - if( tag ) - set_setstr( &acc->set, "tag", tag ); - if( local ) + } else if ((pass_len = base64_decode(pass_b64, (unsigned char **) &pass_cr)) && + arc_decode(pass_cr, pass_len, &password, xd->given_pass) >= 0) { + acc = account_add(xd->irc->b, prpl, handle, password); + if (server) { + set_setstr(&acc->set, "server", server); + } + if (autoconnect) { + set_setstr(&acc->set, "auto_connect", autoconnect); + } + if (tag) { + set_setstr(&acc->set, "tag", tag); + } + if (local) { acc->flags |= ACC_FLAG_LOCAL; - } - else + } + } else { return XT_ABORT; - - g_free( pass_cr ); - g_free( password ); - - handle_settings( node, &acc->set ); - - for( c = node->children; ( c = xt_find_node( c, "buddy" ) ); c = c->next ) - { + } + + g_free(pass_cr); + g_free(password); + + handle_settings(node, &acc->set); + + for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { char *handle, *nick; - - handle = xt_find_attr( c, "handle" ); - nick = xt_find_attr( c, "nick" ); - - if( handle && nick ) - nick_set_raw( acc, handle, nick ); - else + + handle = xt_find_attr(c, "handle"); + nick = xt_find_attr(c, "nick"); + + if (handle && nick) { + nick_set_raw(acc, handle, nick); + } else { return XT_ABORT; - } + } + } return XT_HANDLED; } -static xt_status handle_channel( struct xt_node *node, gpointer data ) +static xt_status handle_channel(struct xt_node *node, gpointer data) { struct xml_parsedata *xd = data; irc_channel_t *ic; char *name, *type; - - name = xt_find_attr( node, "name" ); - type = xt_find_attr( node, "type" ); - - if( !name || !type ) + + name = xt_find_attr(node, "name"); + type = xt_find_attr(node, "type"); + + if (!name || !type) { return XT_ABORT; - + } + /* The channel may exist already, for example if it's &bitlbee. Also, it's possible that the user just reconnected and the IRC client already rejoined all channels it was in. They should still get the right settings. */ - if( ( ic = irc_channel_by_name( xd->irc, name ) ) || - ( ic = irc_channel_new( xd->irc, name ) ) ) - set_setstr( &ic->set, "type", type ); - - handle_settings( node, &ic->set ); - + if ((ic = irc_channel_by_name(xd->irc, name)) || + (ic = irc_channel_new(xd->irc, name))) { + set_setstr(&ic->set, "type", type); + } + + handle_settings(node, &ic->set); + return XT_HANDLED; } @@ -173,7 +179,7 @@ static const struct xt_handler_entry handlers[] = { { NULL, NULL, NULL, }, }; -static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const char *password, xml_pass_st action ) +static storage_status_t xml_load_real(irc_t *irc, const char *my_nick, const char *password, xml_pass_st action) { struct xml_parsedata xd[1]; char *fn, buf[2048]; @@ -181,83 +187,81 @@ static storage_status_t xml_load_real( irc_t *irc, const char *my_nick, const ch struct xt_parser *xp = NULL; struct xt_node *node; storage_status_t ret = STORAGE_OTHER_ERROR; - + xd->irc = irc; - strncpy( xd->given_nick, my_nick, MAX_NICK_LENGTH ); + strncpy(xd->given_nick, my_nick, MAX_NICK_LENGTH); xd->given_nick[MAX_NICK_LENGTH] = '\0'; - nick_lc( NULL, xd->given_nick ); - xd->given_pass = (char*) password; - - fn = g_strconcat( global.conf->configdir, xd->given_nick, ".xml", NULL ); - if( ( fd = open( fn, O_RDONLY ) ) < 0 ) - { + nick_lc(NULL, xd->given_nick); + xd->given_pass = (char *) password; + + fn = g_strconcat(global.conf->configdir, xd->given_nick, ".xml", NULL); + if ((fd = open(fn, O_RDONLY)) < 0) { ret = STORAGE_NO_SUCH_USER; goto error; } - - xp = xt_new( handlers, xd ); - while( ( st = read( fd, buf, sizeof( buf ) ) ) > 0 ) - { - st = xt_feed( xp, buf, st ); - if( st != 1 ) + + xp = xt_new(handlers, xd); + while ((st = read(fd, buf, sizeof(buf))) > 0) { + st = xt_feed(xp, buf, st); + if (st != 1) { break; + } } - close( fd ); - if( st != 0 ) + close(fd); + if (st != 0) { goto error; - + } + node = xp->root; - if( node == NULL || node->next != NULL || strcmp( node->name, "user" ) != 0 ) + if (node == NULL || node->next != NULL || strcmp(node->name, "user") != 0) { goto error; - + } + { - char *nick = xt_find_attr( node, "nick" ); - char *pass = xt_find_attr( node, "password" ); - - if( !nick || !pass ) - { + char *nick = xt_find_attr(node, "nick"); + char *pass = xt_find_attr(node, "password"); + + if (!nick || !pass) { goto error; - } - else if( ( st = md5_verify_password( xd->given_pass, pass ) ) != 0 ) - { + } else if ((st = md5_verify_password(xd->given_pass, pass)) != 0) { ret = STORAGE_INVALID_PASSWORD; goto error; } } - - if( action == XML_PASS_CHECK_ONLY ) - { + + if (action == XML_PASS_CHECK_ONLY) { ret = STORAGE_OK; goto error; } - + /* DO NOT call xt_handle() before verifying the password! */ - if( xt_handle( xp, NULL, 1 ) == XT_HANDLED ) + if (xt_handle(xp, NULL, 1) == XT_HANDLED) { ret = STORAGE_OK; - - handle_settings( node, &xd->irc->b->set ); - + } + + handle_settings(node, &xd->irc->b->set); + error: - xt_free( xp ); - g_free( fn ); + xt_free(xp); + g_free(fn); return ret; } -static storage_status_t xml_load( irc_t *irc, const char *password ) +static storage_status_t xml_load(irc_t *irc, const char *password) { - return xml_load_real( irc, irc->user->nick, password, XML_PASS_UNKNOWN ); + return xml_load_real(irc, irc->user->nick, password, XML_PASS_UNKNOWN); } -static storage_status_t xml_check_pass( const char *my_nick, const char *password ) +static storage_status_t xml_check_pass(const char *my_nick, const char *password) { - return xml_load_real( NULL, my_nick, password, XML_PASS_CHECK_ONLY ); + return xml_load_real(NULL, my_nick, password, XML_PASS_CHECK_ONLY); } -static gboolean xml_generate_nick( gpointer key, gpointer value, gpointer data ); -static void xml_generate_settings( struct xt_node *cur, set_t **head ); +static gboolean xml_generate_nick(gpointer key, gpointer value, gpointer data); +static void xml_generate_settings(struct xt_node *cur, set_t **head); -struct xt_node *xml_generate( irc_t *irc ) +struct xt_node *xml_generate(irc_t *irc) { char *pass_buf = NULL; account_t *acc; @@ -265,48 +269,48 @@ struct xt_node *xml_generate( irc_t *irc ) md5_state_t md5_state; GSList *l; struct xt_node *root, *cur; - + /* Generate a salted md5sum of the password. Use 5 bytes for the salt (to prevent dictionary lookups of passwords) to end up with a 21- byte password hash, more convenient for base64 encoding. */ - random_bytes( pass_md5 + 16, 5 ); - md5_init( &md5_state ); - md5_append( &md5_state, (md5_byte_t*) irc->password, strlen( irc->password ) ); - md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ - md5_finish( &md5_state, pass_md5 ); + random_bytes(pass_md5 + 16, 5); + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *) irc->password, strlen(irc->password)); + md5_append(&md5_state, pass_md5 + 16, 5); /* Add the salt. */ + md5_finish(&md5_state, pass_md5); /* Save the hash in base64-encoded form. */ - pass_buf = base64_encode( pass_md5, 21 ); - - root = cur = xt_new_node( "user", NULL, NULL ); - xt_add_attr( cur, "nick", irc->user->nick ); - xt_add_attr( cur, "password", pass_buf ); - xt_add_attr( cur, "version", XML_FORMAT_VERSION ); - - g_free( pass_buf ); - - xml_generate_settings( cur, &irc->b->set ); - - for( acc = irc->b->accounts; acc; acc = acc->next ) - { + pass_buf = base64_encode(pass_md5, 21); + + root = cur = xt_new_node("user", NULL, NULL); + xt_add_attr(cur, "nick", irc->user->nick); + xt_add_attr(cur, "password", pass_buf); + xt_add_attr(cur, "version", XML_FORMAT_VERSION); + + g_free(pass_buf); + + xml_generate_settings(cur, &irc->b->set); + + for (acc = irc->b->accounts; acc; acc = acc->next) { unsigned char *pass_cr; char *pass_b64; int pass_len; - - pass_len = arc_encode( acc->pass, strlen( acc->pass ), (unsigned char**) &pass_cr, irc->password, 12 ); - pass_b64 = base64_encode( pass_cr, pass_len ); - g_free( pass_cr ); - - cur = xt_new_node( "account", NULL, NULL ); - xt_add_attr( cur, "protocol", acc->prpl->name ); - xt_add_attr( cur, "handle", acc->user ); - xt_add_attr( cur, "password", pass_b64 ); - xt_add_attr( cur, "autoconnect", acc->auto_connect ? "true" : "false" ); - xt_add_attr( cur, "tag", acc->tag ); - if( acc->server && acc->server[0] ) - xt_add_attr( cur, "server", acc->server ); - - g_free( pass_b64 ); - + + pass_len = arc_encode(acc->pass, strlen(acc->pass), (unsigned char **) &pass_cr, irc->password, 12); + pass_b64 = base64_encode(pass_cr, pass_len); + g_free(pass_cr); + + cur = xt_new_node("account", NULL, NULL); + xt_add_attr(cur, "protocol", acc->prpl->name); + xt_add_attr(cur, "handle", acc->user); + xt_add_attr(cur, "password", pass_b64); + xt_add_attr(cur, "autoconnect", acc->auto_connect ? "true" : "false"); + xt_add_attr(cur, "tag", acc->tag); + if (acc->server && acc->server[0]) { + xt_add_attr(cur, "server", acc->server); + } + + g_free(pass_b64); + /* This probably looks pretty strange. g_hash_table_foreach is quite a PITA already (but it can't get much better in C without using #define, I'm afraid), and it @@ -314,127 +318,130 @@ struct xt_node *xml_generate( irc_t *irc ) errors, so instead let's use the _find function and return TRUE on write errors. Which means, if we found something, there was an error. :-) */ - g_hash_table_find( acc->nicks, xml_generate_nick, cur ); - - xml_generate_settings( cur, &acc->set ); - - xt_add_child( root, cur ); + g_hash_table_find(acc->nicks, xml_generate_nick, cur); + + xml_generate_settings(cur, &acc->set); + + xt_add_child(root, cur); } - - for( l = irc->channels; l; l = l->next ) - { + + for (l = irc->channels; l; l = l->next) { irc_channel_t *ic = l->data; - - if( ic->flags & IRC_CHANNEL_TEMP ) + + if (ic->flags & IRC_CHANNEL_TEMP) { continue; - - cur = xt_new_node( "channel", NULL, NULL ); - xt_add_attr( cur, "name", ic->name ); - xt_add_attr( cur, "type", set_getstr( &ic->set, "type" ) ); - - xml_generate_settings( cur, &ic->set ); - - xt_add_child( root, cur ); + } + + cur = xt_new_node("channel", NULL, NULL); + xt_add_attr(cur, "name", ic->name); + xt_add_attr(cur, "type", set_getstr(&ic->set, "type")); + + xml_generate_settings(cur, &ic->set); + + xt_add_child(root, cur); } - + return root; } -static gboolean xml_generate_nick( gpointer key, gpointer value, gpointer data ) +static gboolean xml_generate_nick(gpointer key, gpointer value, gpointer data) { - struct xt_node *node = xt_new_node( "buddy", NULL, NULL ); - xt_add_attr( node, "handle", key ); - xt_add_attr( node, "nick", value ); - xt_add_child( (struct xt_node *) data, node ); - + struct xt_node *node = xt_new_node("buddy", NULL, NULL); + + xt_add_attr(node, "handle", key); + xt_add_attr(node, "nick", value); + xt_add_child((struct xt_node *) data, node); + return FALSE; } -static void xml_generate_settings( struct xt_node *cur, set_t **head ) +static void xml_generate_settings(struct xt_node *cur, set_t **head) { set_t *set; - - for( set = *head; set; set = set->next ) - if( set->value && !( set->flags & SET_NOSAVE ) ) - { + + for (set = *head; set; set = set->next) { + if (set->value && !(set->flags & SET_NOSAVE)) { struct xt_node *xset; - xt_add_child( cur, xset = xt_new_node( "setting", set->value, NULL ) ); - xt_add_attr( xset, "name", set->key ); + xt_add_child(cur, xset = xt_new_node("setting", set->value, NULL)); + xt_add_attr(xset, "name", set->key); } + } } -static storage_status_t xml_save( irc_t *irc, int overwrite ) +static storage_status_t xml_save(irc_t *irc, int overwrite) { storage_status_t ret = STORAGE_OK; char path[512], *path2 = NULL, *xml = NULL; struct xt_node *tree = NULL; size_t len; int fd; - - path2 = g_strdup( irc->user->nick ); - nick_lc( NULL, path2 ); - g_snprintf( path, sizeof( path ) - 20, "%s%s%s", global.conf->configdir, path2, ".xml" ); - g_free( path2 ); - - if( !overwrite && g_access( path, F_OK ) == 0 ) + + path2 = g_strdup(irc->user->nick); + nick_lc(NULL, path2); + g_snprintf(path, sizeof(path) - 20, "%s%s%s", global.conf->configdir, path2, ".xml"); + g_free(path2); + + if (!overwrite && g_access(path, F_OK) == 0) { return STORAGE_ALREADY_EXISTS; - - strcat( path, ".XXXXXX" ); - if( ( fd = mkstemp( path ) ) < 0 ) - { - irc_rootmsg( irc, "Error while opening configuration file." ); + } + + strcat(path, ".XXXXXX"); + if ((fd = mkstemp(path)) < 0) { + irc_rootmsg(irc, "Error while opening configuration file."); return STORAGE_OTHER_ERROR; } - - tree = xml_generate( irc ); - xml = xt_to_string_i( tree ); - len = strlen( xml ); - if( write( fd, xml, len ) != len || - fsync( fd ) != 0 || /* #559 */ - close( fd ) != 0 ) + + tree = xml_generate(irc); + xml = xt_to_string_i(tree); + len = strlen(xml); + if (write(fd, xml, len) != len || + fsync(fd) != 0 || /* #559 */ + close(fd) != 0) { goto error; - - path2 = g_strndup( path, strlen( path ) - 7 ); - if( rename( path, path2 ) != 0 ) - { - g_free( path2 ); + } + + path2 = g_strndup(path, strlen(path) - 7); + if (rename(path, path2) != 0) { + g_free(path2); goto error; } - g_free( path2 ); - + g_free(path2); + goto finish; error: - irc_rootmsg( irc, "Write error. Disk full?" ); + irc_rootmsg(irc, "Write error. Disk full?"); ret = STORAGE_OTHER_ERROR; -finish: - close( fd ); - unlink( path ); - g_free( xml ); - xt_free_node( tree ); - +finish: + close(fd); + unlink(path); + g_free(xml); + xt_free_node(tree); + return ret; } -static storage_status_t xml_remove( const char *nick, const char *password ) +static storage_status_t xml_remove(const char *nick, const char *password) { char s[512], *lc; storage_status_t status; - status = xml_check_pass( nick, password ); - if( status != STORAGE_OK ) + status = xml_check_pass(nick, password); + if (status != STORAGE_OK) { return status; + } + + lc = g_strdup(nick); + nick_lc(NULL, lc); + g_snprintf(s, 511, "%s%s%s", global.conf->configdir, lc, ".xml"); + g_free(lc); - lc = g_strdup( nick ); - nick_lc( NULL, lc ); - g_snprintf( s, 511, "%s%s%s", global.conf->configdir, lc, ".xml" ); - g_free( lc ); - - if( unlink( s ) == -1 ) + if (unlink(s) == -1) { return STORAGE_OTHER_ERROR; - + } + return STORAGE_OK; } diff --git a/tests/check.c b/tests/check.c index 2e55dbc4..9b97f884 100644 --- a/tests/check.c +++ b/tests/check.c @@ -7,11 +7,12 @@ #include "bitlbee.h" #include "testsuite.h" -global_t global; /* Against global namespace pollution */ +global_t global; /* Against global namespace pollution */ gboolean g_io_channel_pair(GIOChannel **ch1, GIOChannel **ch2) { int sock[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNIX, sock) < 0) { perror("socketpair"); return FALSE; @@ -26,8 +27,10 @@ irc_t *torture_irc(void) { irc_t *irc; GIOChannel *ch1, *ch2; - if (!g_io_channel_pair(&ch1, &ch2)) + + if (!g_io_channel_pair(&ch1, &ch2)) { return NULL; + } irc = irc_new(g_io_channel_unix_get_fd(ch1)); return irc; } @@ -36,8 +39,8 @@ double gettime() { struct timeval time[1]; - gettimeofday( time, 0 ); - return( (double) time->tv_sec + (double) time->tv_usec / 1000000 ); + gettimeofday(time, 0); + return((double) time->tv_sec + (double) time->tv_usec / 1000000); } /* From check_util.c */ @@ -70,7 +73,7 @@ Suite *jabber_sasl_suite(void); /* From check_jabber_sasl.c */ Suite *jabber_util_suite(void); -int main (int argc, char **argv) +int main(int argc, char **argv) { int nf; SRunner *sr; @@ -78,16 +81,17 @@ int main (int argc, char **argv) gboolean no_fork = FALSE; gboolean verbose = FALSE; GOptionEntry options[] = { - {"no-fork", 'n', 0, G_OPTION_ARG_NONE, &no_fork, "Don't fork" }, - {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, + { "no-fork", 'n', 0, G_OPTION_ARG_NONE, &no_fork, "Don't fork" }, + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, { NULL } }; pc = g_option_context_new(""); g_option_context_add_main_entries(pc, options, NULL); - if(!g_option_context_parse(pc, &argc, &argv, NULL)) + if (!g_option_context_parse(pc, &argc, &argv, NULL)) { return 1; + } g_option_context_free(pc); @@ -96,15 +100,15 @@ int main (int argc, char **argv) setlocale(LC_CTYPE, ""); if (verbose) { - log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); + log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE); #ifdef DEBUG - log_link( LOGLVL_DEBUG, LOGOUTPUT_CONSOLE ); + log_link(LOGLVL_DEBUG, LOGOUTPUT_CONSOLE); #endif - log_link( LOGLVL_INFO, LOGOUTPUT_CONSOLE ); - log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); + log_link(LOGLVL_INFO, LOGOUTPUT_CONSOLE); + log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE); } - global.conf = conf_load( 0, NULL); + global.conf = conf_load(0, NULL); global.conf->runmode = RUNMODE_DAEMON; sr = srunner_create(util_suite()); @@ -117,9 +121,10 @@ int main (int argc, char **argv) srunner_add_suite(sr, set_suite()); srunner_add_suite(sr, jabber_sasl_suite()); srunner_add_suite(sr, jabber_util_suite()); - if (no_fork) + if (no_fork) { srunner_set_fork_status(sr, CK_NOFORK); - srunner_run_all (sr, verbose?CK_VERBOSE:CK_NORMAL); + } + srunner_run_all(sr, verbose ? CK_VERBOSE : CK_NORMAL); nf = srunner_ntests_failed(sr); srunner_free(sr); return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/check_arc.c b/tests/check_arc.c index e9e7d382..9fcd4b25 100644 --- a/tests/check_arc.c +++ b/tests/check_arc.c @@ -20,27 +20,25 @@ char *clear_tests[] = static void check_codec(int l) { int i; - - for( i = 0; clear_tests[i]; i++ ) - { - tcase_fn_start (clear_tests[i], __FILE__, __LINE__); + + for (i = 0; clear_tests[i]; i++) { + tcase_fn_start(clear_tests[i], __FILE__, __LINE__); unsigned char *crypted; char *decrypted; int len; - - len = arc_encode( clear_tests[i], 0, &crypted, password, 12 ); - len = arc_decode( crypted, len, &decrypted, password ); - - fail_if( strcmp( clear_tests[i], decrypted ) != 0, - "%s didn't decrypt back properly", clear_tests[i] ); - - g_free( crypted ); - g_free( decrypted ); + + len = arc_encode(clear_tests[i], 0, &crypted, password, 12); + len = arc_decode(crypted, len, &decrypted, password); + + fail_if(strcmp(clear_tests[i], decrypted) != 0, + "%s didn't decrypt back properly", clear_tests[i]); + + g_free(crypted); + g_free(decrypted); } } -struct -{ +struct { unsigned char crypted[30]; int len; char *decrypted; @@ -52,7 +50,7 @@ struct 0xb1, 0x31, 0xc9, 0xdb, 0xf9, 0xaa }, 18, "short pass" }, - + /* Two blocks with padding. */ { { @@ -77,31 +75,31 @@ struct static void check_decod(int l) { int i; - - for( i = 0; decrypt_tests[i].len; i++ ) - { - tcase_fn_start (decrypt_tests[i].decrypted, __FILE__, __LINE__); + + for (i = 0; decrypt_tests[i].len; i++) { + tcase_fn_start(decrypt_tests[i].decrypted, __FILE__, __LINE__); char *decrypted; int len; - - len = arc_decode( decrypt_tests[i].crypted, decrypt_tests[i].len, - &decrypted, password ); - - fail_if( len == -1, - "`%s' didn't decrypt properly", decrypt_tests[i].decrypted ); - fail_if( strcmp( decrypt_tests[i].decrypted, decrypted ) != 0, - "`%s' didn't decrypt properly", decrypt_tests[i].decrypted ); - - g_free( decrypted ); + + len = arc_decode(decrypt_tests[i].crypted, decrypt_tests[i].len, + &decrypted, password); + + fail_if(len == -1, + "`%s' didn't decrypt properly", decrypt_tests[i].decrypted); + fail_if(strcmp(decrypt_tests[i].decrypted, decrypted) != 0, + "`%s' didn't decrypt properly", decrypt_tests[i].decrypted); + + g_free(decrypted); } } -Suite *arc_suite (void) +Suite *arc_suite(void) { Suite *s = suite_create("ArcFour"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, check_codec); - tcase_add_test (tc_core, check_decod); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, check_codec); + tcase_add_test(tc_core, check_decod); return s; } diff --git a/tests/check_help.c b/tests/check_help.c index a6c127ea..92d7c28f 100644 --- a/tests/check_help.c +++ b/tests/check_help.c @@ -7,28 +7,29 @@ #include "help.h" START_TEST(test_help_initfree) - help_t *h, *r; - r = help_init(&h, "/dev/null"); - fail_if(r == NULL); - fail_if(r != h); +help_t * h, *r; +r = help_init(&h, "/dev/null"); +fail_if(r == NULL); +fail_if(r != h); - help_free(&h); - fail_if(h != NULL); +help_free(&h); +fail_if(h != NULL); END_TEST START_TEST(test_help_nonexistent) - help_t *h, *r; - r = help_init(&h, "/dev/null"); - fail_unless(help_get(&h, "nonexistent") == NULL); - fail_if(r == NULL); +help_t * h, *r; +r = help_init(&h, "/dev/null"); +fail_unless(help_get(&h, "nonexistent") == NULL); +fail_if(r == NULL); END_TEST -Suite *help_suite (void) +Suite *help_suite(void) { Suite *s = suite_create("Help"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_help_initfree); - tcase_add_test (tc_core, test_help_nonexistent); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, test_help_initfree); + tcase_add_test(tc_core, test_help_nonexistent); return s; } diff --git a/tests/check_irc.c b/tests/check_irc.c index a4b9a1e9..5c940729 100644 --- a/tests/check_irc.c +++ b/tests/check_irc.c @@ -8,57 +8,58 @@ #include "testsuite.h" START_TEST(test_connect) - GIOChannel *ch1, *ch2; - irc_t *irc; - char *raw; - fail_unless(g_io_channel_pair(&ch1, &ch2)); +GIOChannel * ch1, *ch2; +irc_t *irc; +char *raw; +fail_unless(g_io_channel_pair(&ch1, &ch2)); - irc = irc_new(g_io_channel_unix_get_fd(ch1)); +irc = irc_new(g_io_channel_unix_get_fd(ch1)); - irc_free(irc); +irc_free(irc); - fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); - - fail_if(strcmp(raw, "") != 0); +fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); - g_free(raw); +fail_if(strcmp(raw, "") != 0); + +g_free(raw); END_TEST START_TEST(test_login) - GIOChannel *ch1, *ch2; - irc_t *irc; - char *raw; - fail_unless(g_io_channel_pair(&ch1, &ch2)); +GIOChannel * ch1, *ch2; +irc_t *irc; +char *raw; +fail_unless(g_io_channel_pair(&ch1, &ch2)); + +g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL); +g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL); - g_io_channel_set_flags(ch1, G_IO_FLAG_NONBLOCK, NULL); - g_io_channel_set_flags(ch2, G_IO_FLAG_NONBLOCK, NULL); +irc = irc_new(g_io_channel_unix_get_fd(ch1)); - irc = irc_new(g_io_channel_unix_get_fd(ch1)); +fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\r\n" + "USER a a a a\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL); +fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL); - fail_unless(g_io_channel_write_chars(ch2, "NICK bla\r\r\n" - "USER a a a a\n", -1, NULL, NULL) == G_IO_STATUS_NORMAL); - fail_unless(g_io_channel_flush(ch2, NULL) == G_IO_STATUS_NORMAL); +g_main_iteration(FALSE); +irc_free(irc); - g_main_iteration(FALSE); - irc_free(irc); +fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); - fail_unless(g_io_channel_read_to_end(ch2, &raw, NULL, NULL) == G_IO_STATUS_NORMAL); - - fail_unless(strstr(raw, "001") != NULL); - fail_unless(strstr(raw, "002") != NULL); - fail_unless(strstr(raw, "003") != NULL); - fail_unless(strstr(raw, "004") != NULL); - fail_unless(strstr(raw, "005") != NULL); +fail_unless(strstr(raw, "001") != NULL); +fail_unless(strstr(raw, "002") != NULL); +fail_unless(strstr(raw, "003") != NULL); +fail_unless(strstr(raw, "004") != NULL); +fail_unless(strstr(raw, "005") != NULL); - g_free(raw); +g_free(raw); END_TEST -Suite *irc_suite (void) +Suite *irc_suite(void) { Suite *s = suite_create("IRC"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_connect); - tcase_add_test (tc_core, test_login); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, test_connect); + tcase_add_test(tc_core, test_login); return s; } diff --git a/tests/check_jabber_sasl.c b/tests/check_jabber_sasl.c index 81fc60aa..e7ea8a75 100644 --- a/tests/check_jabber_sasl.c +++ b/tests/check_jabber_sasl.c @@ -5,17 +5,16 @@ #include <string.h> #include <stdio.h> -char *sasl_get_part( char *data, char *field ); +char *sasl_get_part(char *data, char *field); #define challenge1 "nonce=\"1669585310\",qop=\"auth\",charset=utf-8,algorithm=md5-sess," \ - "something=\"Not \\\"standardized\\\"\"" + "something=\"Not \\\"standardized\\\"\"" #define challenge2 "realm=\"quadpoint.org\", nonce=\"NPotlQpQf9RNYodOwierkQ==\", " \ - "qop=\"auth, auth-int\", charset=utf-8, algorithm=md5-sess" + "qop=\"auth, auth-int\", charset=utf-8, algorithm=md5-sess" #define challenge3 ", realm=\"localhost\", nonce=\"LlBV2txnO8RbB5hgs3KgiQ==\", " \ - "qop=\"auth, auth-int, \", ,\n, charset=utf-8, algorithm=md5-sess," + "qop=\"auth, auth-int, \", ,\n, charset=utf-8, algorithm=md5-sess," -struct -{ +struct { char *challenge; char *key; char *value; @@ -81,35 +80,36 @@ struct static void check_get_part(int l) { int i; - - for( i = 0; get_part_tests[i].key; i++ ) - { - tcase_fn_start( get_part_tests[i].key, __FILE__, i ); + + for (i = 0; get_part_tests[i].key; i++) { + tcase_fn_start(get_part_tests[i].key, __FILE__, i); char *res; - - res = sasl_get_part( get_part_tests[i].challenge, - get_part_tests[i].key ); - - if( get_part_tests[i].value == NULL ) - fail_if( res != NULL, "Found key %s in %s while it shouldn't be there!", - get_part_tests[i].key, get_part_tests[i].challenge ); - else if( res ) - fail_unless( strcmp( res, get_part_tests[i].value ) == 0, - "Incorrect value for key %s in %s: %s", - get_part_tests[i].key, get_part_tests[i].challenge, res ); - else - fail( "Could not find key %s in %s", - get_part_tests[i].key, get_part_tests[i].challenge ); - - g_free( res ); + + res = sasl_get_part(get_part_tests[i].challenge, + get_part_tests[i].key); + + if (get_part_tests[i].value == NULL) { + fail_if(res != NULL, "Found key %s in %s while it shouldn't be there!", + get_part_tests[i].key, get_part_tests[i].challenge); + } else if (res) { + fail_unless(strcmp(res, get_part_tests[i].value) == 0, + "Incorrect value for key %s in %s: %s", + get_part_tests[i].key, get_part_tests[i].challenge, res); + } else { + fail("Could not find key %s in %s", + get_part_tests[i].key, get_part_tests[i].challenge); + } + + g_free(res); } } -Suite *jabber_sasl_suite (void) +Suite *jabber_sasl_suite(void) { Suite *s = suite_create("jabber/sasl"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, check_get_part); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, check_get_part); return s; } diff --git a/tests/check_jabber_util.c b/tests/check_jabber_util.c index 966b5230..2a708300 100644 --- a/tests/check_jabber_util.c +++ b/tests/check_jabber_util.c @@ -11,114 +11,114 @@ static struct im_connection *ic; static void check_buddy_add(int l) { struct jabber_buddy *budw1, *budw2, *budw3, *budn, *bud; - - budw1 = jabber_buddy_add( ic, "wilmer@gaast.net/BitlBee" ); - budw1->last_msg = time( NULL ) - 100; - budw2 = jabber_buddy_add( ic, "WILMER@gaast.net/Telepathy" ); + + budw1 = jabber_buddy_add(ic, "wilmer@gaast.net/BitlBee"); + budw1->last_msg = time(NULL) - 100; + budw2 = jabber_buddy_add(ic, "WILMER@gaast.net/Telepathy"); budw2->priority = 2; - budw2->last_msg = time( NULL ); - budw3 = jabber_buddy_add( ic, "wilmer@GAAST.NET/bitlbee" ); - budw3->last_msg = time( NULL ) - 200; + budw2->last_msg = time(NULL); + budw3 = jabber_buddy_add(ic, "wilmer@GAAST.NET/bitlbee"); + budw3->last_msg = time(NULL) - 200; budw3->priority = 4; /* TODO(wilmer): Shouldn't this just return budw3? */ - fail_if( jabber_buddy_add( ic, "wilmer@gaast.net/Telepathy" ) != NULL ); - - budn = jabber_buddy_add( ic, "nekkid@lamejab.net" ); + fail_if(jabber_buddy_add(ic, "wilmer@gaast.net/Telepathy") != NULL); + + budn = jabber_buddy_add(ic, "nekkid@lamejab.net"); /* Shouldn't be allowed if there's already a bare JID. */ - fail_if( jabber_buddy_add( ic, "nekkid@lamejab.net/Illegal" ) ); - + fail_if(jabber_buddy_add(ic, "nekkid@lamejab.net/Illegal")); + /* Case sensitivity: Case only matters after the / */ - fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net/BitlBee", 0 ) == - jabber_buddy_by_jid( ic, "wilmer@gaast.net/bitlbee", 0 ) ); - fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net/telepathy", 0 ) ); - - fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net/BitlBee", 0 ) == budw1 ); - fail_unless( jabber_buddy_by_jid( ic, "WILMER@GAAST.NET/BitlBee", GET_BUDDY_EXACT ) == budw1 ); - fail_unless( jabber_buddy_by_jid( ic, "wilmer@GAAST.NET/BitlBee", GET_BUDDY_CREAT ) == budw1 ); + fail_if(jabber_buddy_by_jid(ic, "wilmer@gaast.net/BitlBee", 0) == + jabber_buddy_by_jid(ic, "wilmer@gaast.net/bitlbee", 0)); + fail_if(jabber_buddy_by_jid(ic, "wilmer@gaast.net/telepathy", 0)); + + fail_unless(jabber_buddy_by_jid(ic, "wilmer@gaast.net/BitlBee", 0) == budw1); + fail_unless(jabber_buddy_by_jid(ic, "WILMER@GAAST.NET/BitlBee", GET_BUDDY_EXACT) == budw1); + fail_unless(jabber_buddy_by_jid(ic, "wilmer@GAAST.NET/BitlBee", GET_BUDDY_CREAT) == budw1); - fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_EXACT ) ); - fail_unless( jabber_buddy_by_jid( ic, "WILMER@gaast.net", 0 ) == budw3 ); + fail_if(jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_EXACT)); + fail_unless(jabber_buddy_by_jid(ic, "WILMER@gaast.net", 0) == budw3); /* Check O_FIRST and see if it's indeed the first item from the list. */ - fail_unless( ( bud = jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_FIRST ) ) == budw1 ); - fail_unless( bud->next == budw2 && bud->next->next == budw3 && bud->next->next->next == NULL ); - + fail_unless((bud = jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_FIRST)) == budw1); + fail_unless(bud->next == budw2 && bud->next->next == budw3 && bud->next->next->next == NULL); + /* Change the resource_select setting, now we should get a different resource. */ - set_setstr( &ic->acc->set, "resource_select", "activity" ); - fail_unless( jabber_buddy_by_jid( ic, "wilmer@GAAST.NET", 0 ) == budw2 ); - + set_setstr(&ic->acc->set, "resource_select", "activity"); + fail_unless(jabber_buddy_by_jid(ic, "wilmer@GAAST.NET", 0) == budw2); + /* Some testing of bare JID handling (which is horrible). */ - fail_if( jabber_buddy_by_jid( ic, "nekkid@lamejab.net/Illegal", 0 ) ); - fail_if( jabber_buddy_by_jid( ic, "NEKKID@LAMEJAB.NET/Illegal", GET_BUDDY_CREAT ) ); - fail_unless( jabber_buddy_by_jid( ic, "nekkid@lamejab.net", 0 ) == budn ); - fail_unless( jabber_buddy_by_jid( ic, "NEKKID@lamejab.net", GET_BUDDY_EXACT ) == budn ); - fail_unless( jabber_buddy_by_jid( ic, "nekkid@LAMEJAB.NET", GET_BUDDY_CREAT ) == budn ); - + fail_if(jabber_buddy_by_jid(ic, "nekkid@lamejab.net/Illegal", 0)); + fail_if(jabber_buddy_by_jid(ic, "NEKKID@LAMEJAB.NET/Illegal", GET_BUDDY_CREAT)); + fail_unless(jabber_buddy_by_jid(ic, "nekkid@lamejab.net", 0) == budn); + fail_unless(jabber_buddy_by_jid(ic, "NEKKID@lamejab.net", GET_BUDDY_EXACT) == budn); + fail_unless(jabber_buddy_by_jid(ic, "nekkid@LAMEJAB.NET", GET_BUDDY_CREAT) == budn); + /* More case sensitivity testing, and see if remove works properly. */ - fail_if( jabber_buddy_remove( ic, "wilmer@gaast.net/telepathy" ) ); - fail_if( jabber_buddy_by_jid( ic, "wilmer@GAAST.NET/telepathy", GET_BUDDY_CREAT ) == budw2 ); - fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/Telepathy" ) ); - fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/telepathy" ) ); - + fail_if(jabber_buddy_remove(ic, "wilmer@gaast.net/telepathy")); + fail_if(jabber_buddy_by_jid(ic, "wilmer@GAAST.NET/telepathy", GET_BUDDY_CREAT) == budw2); + fail_unless(jabber_buddy_remove(ic, "wilmer@gaast.net/Telepathy")); + fail_unless(jabber_buddy_remove(ic, "wilmer@gaast.net/telepathy")); + /* Test activity_timeout and GET_BUDDY_BARE_OK. */ - fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) == budw1 ); + fail_unless(jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK) == budw1); budw1->last_msg -= 50; - fail_unless( ( bud = jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) ) != NULL ); - fail_unless( strcmp( bud->full_jid, "wilmer@gaast.net" ) == 0 ); - - fail_if( jabber_buddy_remove( ic, "wilmer@gaast.net" ) ); - fail_unless( jabber_buddy_by_jid( ic, "wilmer@gaast.net", 0 ) == budw1 ); - - fail_if( jabber_buddy_remove( ic, "wilmer@gaast.net" ) ); - fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/bitlbee" ) ); - fail_unless( jabber_buddy_remove( ic, "wilmer@gaast.net/BitlBee" ) ); - fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK ) ); - + fail_unless((bud = jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK)) != NULL); + fail_unless(strcmp(bud->full_jid, "wilmer@gaast.net") == 0); + + fail_if(jabber_buddy_remove(ic, "wilmer@gaast.net")); + fail_unless(jabber_buddy_by_jid(ic, "wilmer@gaast.net", 0) == budw1); + + fail_if(jabber_buddy_remove(ic, "wilmer@gaast.net")); + fail_unless(jabber_buddy_remove(ic, "wilmer@gaast.net/bitlbee")); + fail_unless(jabber_buddy_remove(ic, "wilmer@gaast.net/BitlBee")); + fail_if(jabber_buddy_by_jid(ic, "wilmer@gaast.net", GET_BUDDY_BARE_OK)); + /* Check if remove_bare() indeed gets rid of all. */ /* disable this one for now. fail_unless( jabber_buddy_remove_bare( ic, "wilmer@gaast.net" ) ); fail_if( jabber_buddy_by_jid( ic, "wilmer@gaast.net", 0 ) ); */ - fail_if( jabber_buddy_remove( ic, "nekkid@lamejab.net/Illegal" ) ); - fail_unless( jabber_buddy_remove( ic, "nekkid@lamejab.net" ) ); - fail_if( jabber_buddy_by_jid( ic, "nekkid@lamejab.net", 0 ) ); - + fail_if(jabber_buddy_remove(ic, "nekkid@lamejab.net/Illegal")); + fail_unless(jabber_buddy_remove(ic, "nekkid@lamejab.net")); + fail_if(jabber_buddy_by_jid(ic, "nekkid@lamejab.net", 0)); + /* Fixing a bug in this branch that caused information to get lost when removing the first full JID from a list. */ - jabber_buddy_add( ic, "bugtest@google.com/A" ); - jabber_buddy_add( ic, "bugtest@google.com/B" ); - jabber_buddy_add( ic, "bugtest@google.com/C" ); - fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/A" ) ); - fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/B" ) ); - fail_unless( jabber_buddy_remove( ic, "bugtest@google.com/C" ) ); + jabber_buddy_add(ic, "bugtest@google.com/A"); + jabber_buddy_add(ic, "bugtest@google.com/B"); + jabber_buddy_add(ic, "bugtest@google.com/C"); + fail_unless(jabber_buddy_remove(ic, "bugtest@google.com/A")); + fail_unless(jabber_buddy_remove(ic, "bugtest@google.com/B")); + fail_unless(jabber_buddy_remove(ic, "bugtest@google.com/C")); } static void check_compareJID(int l) { - fail_unless( jabber_compare_jid( "bugtest@google.com/B", "bugtest@google.com/A" ) ); - fail_if( jabber_compare_jid( "bugtest1@google.com/B", "bugtest@google.com/A" ) ); - fail_if( jabber_compare_jid( "bugtest@google.com/B", "bugtest1@google.com/A" ) ); - fail_if( jabber_compare_jid( "bugtest1@google.com/B", "bugtest2@google.com/A" ) ); - fail_unless( jabber_compare_jid( "bugtest@google.com/A", "bugtest@google.com/A" ) ); - fail_if( jabber_compare_jid( "", "bugtest@google.com/A" ) ); + fail_unless(jabber_compare_jid("bugtest@google.com/B", "bugtest@google.com/A")); + fail_if(jabber_compare_jid("bugtest1@google.com/B", "bugtest@google.com/A")); + fail_if(jabber_compare_jid("bugtest@google.com/B", "bugtest1@google.com/A")); + fail_if(jabber_compare_jid("bugtest1@google.com/B", "bugtest2@google.com/A")); + fail_unless(jabber_compare_jid("bugtest@google.com/A", "bugtest@google.com/A")); + fail_if(jabber_compare_jid("", "bugtest@google.com/A")); } -Suite *jabber_util_suite (void) +Suite *jabber_util_suite(void) { Suite *s = suite_create("jabber/util"); TCase *tc_core = tcase_create("Buddy"); struct jabber_data *jd; - - ic = g_new0( struct im_connection, 1 ); - ic->acc = g_new0( account_t, 1 ); - ic->proto_data = jd = g_new0( struct jabber_data, 1 ); - jd->buddies = g_hash_table_new( g_str_hash, g_str_equal ); - set_add( &ic->acc->set, "resource_select", "priority", NULL, ic->acc ); - set_add( &ic->acc->set, "activity_timeout", "120", NULL, ic->acc ); - - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, check_buddy_add); - tcase_add_test (tc_core, check_compareJID); + + ic = g_new0(struct im_connection, 1); + ic->acc = g_new0(account_t, 1); + ic->proto_data = jd = g_new0(struct jabber_data, 1); + jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); + set_add(&ic->acc->set, "resource_select", "priority", NULL, ic->acc); + set_add(&ic->acc->set, "activity_timeout", "120", NULL, ic->acc); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, check_buddy_add); + tcase_add_test(tc_core, check_compareJID); return s; } diff --git a/tests/check_md5.c b/tests/check_md5.c index a9c31f4f..a68df687 100644 --- a/tests/check_md5.c +++ b/tests/check_md5.c @@ -11,20 +11,20 @@ struct md5_test { const char *str; md5_byte_t expected[16]; } tests[] = { - { "", - { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, { "a", - { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, - { "abc", - { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, - { "message digest", - { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, - { "abcdefghijklmnopqrstuvwxyz", - { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, { NULL }, }; @@ -32,24 +32,26 @@ struct md5_test { static void check_sums(int l) { int i; + for (i = 0; tests[i].str; i++) { md5_byte_t sum[16]; - tcase_fn_start (tests[i].str, __FILE__, __LINE__); + tcase_fn_start(tests[i].str, __FILE__, __LINE__); md5_state_t state; md5_init(&state); - md5_append(&state, (const md5_byte_t *)tests[i].str, strlen(tests[i].str)); + md5_append(&state, (const md5_byte_t *) tests[i].str, strlen(tests[i].str)); md5_finish(&state, sum); fail_if(memcmp(tests[i].expected, sum, 16) != 0, "%s failed", tests[i].str); } } -Suite *md5_suite (void) +Suite *md5_suite(void) { Suite *s = suite_create("MD5"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, check_sums); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, check_sums); return s; } diff --git a/tests/check_nick.c b/tests/check_nick.c index 3c11810e..ca5e5111 100644 --- a/tests/check_nick.c +++ b/tests/check_nick.c @@ -8,33 +8,32 @@ #include "misc.h" #include "bitlbee.h" -START_TEST(test_nick_strip) -{ +START_TEST(test_nick_strip){ int i; - const char *get[] = { "test:", "test", "test\n", - "thisisaveryveryveryverylongnick", - "thisisave:ryveryveryverylongnick", - "t::::est", - "test123", - "123test", - "123", - NULL }; - const char *expected[] = { "test", "test", "test", - "thisisaveryveryveryveryl", - "thisisaveryveryveryveryl", - "test", - "test123", - "_123test", - "_123", - NULL }; + const char *get[] = { "test:", "test", "test\n", + "thisisaveryveryveryverylongnick", + "thisisave:ryveryveryverylongnick", + "t::::est", + "test123", + "123test", + "123", + NULL }; + const char *expected[] = { "test", "test", "test", + "thisisaveryveryveryveryl", + "thisisaveryveryveryveryl", + "test", + "test123", + "_123test", + "_123", + NULL }; for (i = 0; get[i]; i++) { char copy[60]; strcpy(copy, get[i]); nick_strip(NULL, copy); - fail_unless (strcmp(copy, expected[i]) == 0, - "(%d) nick_strip broken: %s -> %s (expected: %s)", - i, get[i], copy, expected[i]); + fail_unless(strcmp(copy, expected[i]) == 0, + "(%d) nick_strip broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); } } END_TEST @@ -42,12 +41,12 @@ END_TEST START_TEST(test_nick_ok_ok) { const char *nicks[] = { "foo", "bar123", "bla[", "blie]", "BreEZaH", - "\\od^~", "_123", "_123test", NULL }; + "\\od^~", "_123", "_123test", NULL }; int i; for (i = 0; nicks[i]; i++) { - fail_unless (nick_ok(NULL, nicks[i]) == 1, - "nick_ok() failed: %s", nicks[i]); + fail_unless(nick_ok(NULL, nicks[i]) == 1, + "nick_ok() failed: %s", nicks[i]); } } END_TEST @@ -55,23 +54,24 @@ END_TEST START_TEST(test_nick_ok_notok) { const char *nicks[] = { "thisisaveryveryveryveryveryveryverylongnick", - "\nillegalchar", "", "nick%", "123test", NULL }; + "\nillegalchar", "", "nick%", "123test", NULL }; int i; for (i = 0; nicks[i]; i++) { - fail_unless (nick_ok(NULL, nicks[i]) == 0, - "nick_ok() succeeded for invalid: %s", nicks[i]); + fail_unless(nick_ok(NULL, nicks[i]) == 0, + "nick_ok() succeeded for invalid: %s", nicks[i]); } } END_TEST -Suite *nick_suite (void) +Suite *nick_suite(void) { Suite *s = suite_create("Nick"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_nick_ok_ok); - tcase_add_test (tc_core, test_nick_ok_notok); - tcase_add_test (tc_core, test_nick_strip); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, test_nick_ok_ok); + tcase_add_test(tc_core, test_nick_ok_notok); + tcase_add_test(tc_core, test_nick_strip); return s; } diff --git a/tests/check_set.c b/tests/check_set.c index 5df63270..6f8b39b5 100644 --- a/tests/check_set.c +++ b/tests/check_set.c @@ -7,116 +7,117 @@ #include "testsuite.h" START_TEST(test_set_add) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "default", NULL, data); - fail_unless(s == t); - fail_unless(t->data == data); - fail_unless(strcmp(t->def, "default") == 0); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "default", NULL, data); +fail_unless(s == t); +fail_unless(t->data == data); +fail_unless(strcmp(t->def, "default") == 0); END_TEST START_TEST(test_set_add_existing) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "default", NULL, data); - t = set_add(&s, "name", "newdefault", NULL, data); - fail_unless(s == t); - fail_unless(strcmp(t->def, "newdefault") == 0); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "default", NULL, data); +t = set_add(&s, "name", "newdefault", NULL, data); +fail_unless(s == t); +fail_unless(strcmp(t->def, "newdefault") == 0); END_TEST START_TEST(test_set_find_unknown) - set_t *s = NULL; - fail_unless (set_find(&s, "foo") == NULL); +set_t * s = NULL; +fail_unless(set_find(&s, "foo") == NULL); END_TEST START_TEST(test_set_find) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "default", NULL, data); - fail_unless(s == t); - fail_unless(set_find(&s, "name") == t); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "default", NULL, data); +fail_unless(s == t); +fail_unless(set_find(&s, "name") == t); END_TEST START_TEST(test_set_get_str_default) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "default", NULL, data); - fail_unless(s == t); - fail_unless(strcmp(set_getstr(&s, "name"), "default") == 0); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "default", NULL, data); +fail_unless(s == t); +fail_unless(strcmp(set_getstr(&s, "name"), "default") == 0); END_TEST START_TEST(test_set_get_bool_default) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "true", NULL, data); - fail_unless(s == t); - fail_unless(set_getbool(&s, "name")); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "true", NULL, data); +fail_unless(s == t); +fail_unless(set_getbool(&s, "name")); END_TEST START_TEST(test_set_get_bool_integer) - void *data = "data"; - set_t *s = NULL, *t; - t = set_add(&s, "name", "3", NULL, data); - fail_unless(s == t); - fail_unless(set_getbool(&s, "name") == 3); +void *data = "data"; +set_t *s = NULL, *t; +t = set_add(&s, "name", "3", NULL, data); +fail_unless(s == t); +fail_unless(set_getbool(&s, "name") == 3); END_TEST START_TEST(test_set_get_bool_unknown) - set_t *s = NULL; - fail_unless(set_getbool(&s, "name") == 0); +set_t * s = NULL; +fail_unless(set_getbool(&s, "name") == 0); END_TEST START_TEST(test_set_get_str_value) - void *data = "data"; - set_t *s = NULL; - set_add(&s, "name", "default", NULL, data); - set_setstr(&s, "name", "foo"); - fail_unless(strcmp(set_getstr(&s, "name"), "foo") == 0); +void *data = "data"; +set_t *s = NULL; +set_add(&s, "name", "default", NULL, data); +set_setstr(&s, "name", "foo"); +fail_unless(strcmp(set_getstr(&s, "name"), "foo") == 0); END_TEST START_TEST(test_set_get_str_unknown) - set_t *s = NULL; - fail_unless(set_getstr(&s, "name") == NULL); +set_t * s = NULL; +fail_unless(set_getstr(&s, "name") == NULL); END_TEST START_TEST(test_setint) - void *data = "data"; - set_t *s = NULL; - set_add(&s, "name", "10", NULL, data); - set_setint(&s, "name", 3); - fail_unless(set_getint(&s, "name") == 3); +void *data = "data"; +set_t *s = NULL; +set_add(&s, "name", "10", NULL, data); +set_setint(&s, "name", 3); +fail_unless(set_getint(&s, "name") == 3); END_TEST START_TEST(test_setstr) - void *data = "data"; - set_t *s = NULL; - set_add(&s, "name", "foo", NULL, data); - set_setstr(&s, "name", "bloe"); - fail_unless(strcmp(set_getstr(&s, "name"), "bloe") == 0); +void *data = "data"; +set_t *s = NULL; +set_add(&s, "name", "foo", NULL, data); +set_setstr(&s, "name", "bloe"); +fail_unless(strcmp(set_getstr(&s, "name"), "bloe") == 0); END_TEST START_TEST(test_set_get_int_unknown) - set_t *s = NULL; - fail_unless(set_getint(&s, "foo") == 0); +set_t * s = NULL; +fail_unless(set_getint(&s, "foo") == 0); END_TEST -Suite *set_suite (void) +Suite *set_suite(void) { Suite *s = suite_create("Set"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_set_add); - tcase_add_test (tc_core, test_set_add_existing); - tcase_add_test (tc_core, test_set_find_unknown); - tcase_add_test (tc_core, test_set_find); - tcase_add_test (tc_core, test_set_get_str_default); - tcase_add_test (tc_core, test_set_get_str_value); - tcase_add_test (tc_core, test_set_get_str_unknown); - tcase_add_test (tc_core, test_set_get_bool_default); - tcase_add_test (tc_core, test_set_get_bool_integer); - tcase_add_test (tc_core, test_set_get_bool_unknown); - tcase_add_test (tc_core, test_set_get_int_unknown); - tcase_add_test (tc_core, test_setint); - tcase_add_test (tc_core, test_setstr); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, test_set_add); + tcase_add_test(tc_core, test_set_add_existing); + tcase_add_test(tc_core, test_set_find_unknown); + tcase_add_test(tc_core, test_set_find); + tcase_add_test(tc_core, test_set_get_str_default); + tcase_add_test(tc_core, test_set_get_str_value); + tcase_add_test(tc_core, test_set_get_str_unknown); + tcase_add_test(tc_core, test_set_get_bool_default); + tcase_add_test(tc_core, test_set_get_bool_integer); + tcase_add_test(tc_core, test_set_get_bool_unknown); + tcase_add_test(tc_core, test_set_get_int_unknown); + tcase_add_test(tc_core, test_setint); + tcase_add_test(tc_core, test_setstr); return s; } diff --git a/tests/check_user.c b/tests/check_user.c index c4d8bf5f..6fa15203 100644 --- a/tests/check_user.c +++ b/tests/check_user.c @@ -8,70 +8,71 @@ #if 0 START_TEST(test_user_add) - irc_t *irc = torture_irc(); - user_t *user; - user = user_add(irc, "foo"); - fail_if(user == NULL); - fail_if(strcmp(user->nick, "foo") != 0); - fail_unless(user_find(irc, "foo") == user); +irc_t * irc = torture_irc(); +user_t *user; +user = user_add(irc, "foo"); +fail_if(user == NULL); +fail_if(strcmp(user->nick, "foo") != 0); +fail_unless(user_find(irc, "foo") == user); END_TEST START_TEST(test_user_add_exists) - irc_t *irc = torture_irc(); - user_t *user; - user = user_add(irc, "foo"); - fail_if(user == NULL); - user = user_add(irc, "foo"); - fail_unless(user == NULL); +irc_t * irc = torture_irc(); +user_t *user; +user = user_add(irc, "foo"); +fail_if(user == NULL); +user = user_add(irc, "foo"); +fail_unless(user == NULL); END_TEST START_TEST(test_user_add_invalid) - irc_t *irc = torture_irc(); - user_t *user; - user = user_add(irc, ":foo"); - fail_unless(user == NULL); +irc_t * irc = torture_irc(); +user_t *user; +user = user_add(irc, ":foo"); +fail_unless(user == NULL); END_TEST START_TEST(test_user_del_invalid) - irc_t *irc = torture_irc(); - fail_unless(user_del(irc, ":foo") == 0); +irc_t * irc = torture_irc(); +fail_unless(user_del(irc, ":foo") == 0); END_TEST START_TEST(test_user_del) - irc_t *irc = torture_irc(); - user_t *user; - user = user_add(irc, "foo"); - fail_unless(user_del(irc, "foo") == 1); - fail_unless(user_find(irc, "foo") == NULL); +irc_t * irc = torture_irc(); +user_t *user; +user = user_add(irc, "foo"); +fail_unless(user_del(irc, "foo") == 1); +fail_unless(user_find(irc, "foo") == NULL); END_TEST START_TEST(test_user_del_nonexistant) - irc_t *irc = torture_irc(); - fail_unless(user_del(irc, "foo") == 0); +irc_t * irc = torture_irc(); +fail_unless(user_del(irc, "foo") == 0); END_TEST START_TEST(test_user_rename) - irc_t *irc = torture_irc(); - user_t *user; - user = user_add(irc, "foo"); - user_rename(irc, "foo", "bar"); - fail_unless(user_find(irc, "foo") == NULL); - fail_if(user_find(irc, "bar") == NULL); +irc_t * irc = torture_irc(); +user_t *user; +user = user_add(irc, "foo"); +user_rename(irc, "foo", "bar"); +fail_unless(user_find(irc, "foo") == NULL); +fail_if(user_find(irc, "bar") == NULL); END_TEST #endif -Suite *user_suite (void) +Suite *user_suite(void) { Suite *s = suite_create("User"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); + + suite_add_tcase(s, tc_core); #if 0 - tcase_add_test (tc_core, test_user_add); - tcase_add_test (tc_core, test_user_add_invalid); - tcase_add_test (tc_core, test_user_add_exists); - tcase_add_test (tc_core, test_user_del_invalid); - tcase_add_test (tc_core, test_user_del_nonexistant); - tcase_add_test (tc_core, test_user_del); - tcase_add_test (tc_core, test_user_rename); + tcase_add_test(tc_core, test_user_add); + tcase_add_test(tc_core, test_user_add_invalid); + tcase_add_test(tc_core, test_user_add_exists); + tcase_add_test(tc_core, test_user_del_invalid); + tcase_add_test(tc_core, test_user_del_nonexistant); + tcase_add_test(tc_core, test_user_del); + tcase_add_test(tc_core, test_user_rename); #endif return s; } diff --git a/tests/check_util.c b/tests/check_util.c index dc73d644..006ad02a 100644 --- a/tests/check_util.c +++ b/tests/check_util.c @@ -8,8 +8,7 @@ #include "misc.h" #include "url.h" -START_TEST(test_strip_linefeed) -{ +START_TEST(test_strip_linefeed){ int i; const char *get[] = { "Test", "Test\r", "Test\rX\r", NULL }; const char *expected[] = { "Test", "Test", "TestX", NULL }; @@ -18,9 +17,9 @@ START_TEST(test_strip_linefeed) char copy[20]; strcpy(copy, get[i]); strip_linefeed(copy); - fail_unless (strcmp(copy, expected[i]) == 0, - "(%d) strip_linefeed broken: %s -> %s (expected: %s)", - i, get[i], copy, expected[i]); + fail_unless(strcmp(copy, expected[i]) == 0, + "(%d) strip_linefeed broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); } } END_TEST @@ -35,76 +34,75 @@ START_TEST(test_strip_newlines) char copy[20], *ret; strcpy(copy, get[i]); ret = strip_newlines(copy); - fail_unless (strcmp(copy, expected[i]) == 0, - "(%d) strip_newlines broken: %s -> %s (expected: %s)", - i, get[i], copy, expected[i]); - fail_unless (copy == ret, "Original string not returned"); + fail_unless(strcmp(copy, expected[i]) == 0, + "(%d) strip_newlines broken: %s -> %s (expected: %s)", + i, get[i], copy, expected[i]); + fail_unless(copy == ret, "Original string not returned"); } } END_TEST START_TEST(test_set_url_http) - url_t url; - - fail_if (0 == url_set(&url, "http://host/")); - fail_unless (!strcmp(url.host, "host")); - fail_unless (!strcmp(url.file, "/")); - fail_unless (!strcmp(url.user, "")); - fail_unless (!strcmp(url.pass, "")); - fail_unless (url.proto == PROTO_HTTP); - fail_unless (url.port == 80); +url_t url; + +fail_if(0 == url_set(&url, "http://host/")); +fail_unless(!strcmp(url.host, "host")); +fail_unless(!strcmp(url.file, "/")); +fail_unless(!strcmp(url.user, "")); +fail_unless(!strcmp(url.pass, "")); +fail_unless(url.proto == PROTO_HTTP); +fail_unless(url.port == 80); END_TEST START_TEST(test_set_url_https) - url_t url; - - fail_if (0 == url_set(&url, "https://ahost/AimeeMann")); - fail_unless (!strcmp(url.host, "ahost")); - fail_unless (!strcmp(url.file, "/AimeeMann")); - fail_unless (!strcmp(url.user, "")); - fail_unless (!strcmp(url.pass, "")); - fail_unless (url.proto == PROTO_HTTPS); - fail_unless (url.port == 443); +url_t url; + +fail_if(0 == url_set(&url, "https://ahost/AimeeMann")); +fail_unless(!strcmp(url.host, "ahost")); +fail_unless(!strcmp(url.file, "/AimeeMann")); +fail_unless(!strcmp(url.user, "")); +fail_unless(!strcmp(url.pass, "")); +fail_unless(url.proto == PROTO_HTTPS); +fail_unless(url.port == 443); END_TEST START_TEST(test_set_url_port) - url_t url; - - fail_if (0 == url_set(&url, "https://ahost:200/Lost/In/Space")); - fail_unless (!strcmp(url.host, "ahost")); - fail_unless (!strcmp(url.file, "/Lost/In/Space")); - fail_unless (!strcmp(url.user, "")); - fail_unless (!strcmp(url.pass, "")); - fail_unless (url.proto == PROTO_HTTPS); - fail_unless (url.port == 200); +url_t url; + +fail_if(0 == url_set(&url, "https://ahost:200/Lost/In/Space")); +fail_unless(!strcmp(url.host, "ahost")); +fail_unless(!strcmp(url.file, "/Lost/In/Space")); +fail_unless(!strcmp(url.user, "")); +fail_unless(!strcmp(url.pass, "")); +fail_unless(url.proto == PROTO_HTTPS); +fail_unless(url.port == 200); END_TEST START_TEST(test_set_url_username) - url_t url; - - fail_if (0 == url_set(&url, "socks4://user@ahost/Space")); - fail_unless (!strcmp(url.host, "ahost")); - fail_unless (!strcmp(url.file, "/Space")); - fail_unless (!strcmp(url.user, "user")); - fail_unless (!strcmp(url.pass, "")); - fail_unless (url.proto == PROTO_SOCKS4); - fail_unless (url.port == 1080); +url_t url; + +fail_if(0 == url_set(&url, "socks4://user@ahost/Space")); +fail_unless(!strcmp(url.host, "ahost")); +fail_unless(!strcmp(url.file, "/Space")); +fail_unless(!strcmp(url.user, "user")); +fail_unless(!strcmp(url.pass, "")); +fail_unless(url.proto == PROTO_SOCKS4); +fail_unless(url.port == 1080); END_TEST START_TEST(test_set_url_username_pwd) - url_t url; - - fail_if (0 == url_set(&url, "socks5://user:pass@ahost/")); - fail_unless (!strcmp(url.host, "ahost")); - fail_unless (!strcmp(url.file, "/")); - fail_unless (!strcmp(url.user, "user")); - fail_unless (!strcmp(url.pass, "pass")); - fail_unless (url.proto == PROTO_SOCKS5); - fail_unless (url.port == 1080); +url_t url; + +fail_if(0 == url_set(&url, "socks5://user:pass@ahost/")); +fail_unless(!strcmp(url.host, "ahost")); +fail_unless(!strcmp(url.file, "/")); +fail_unless(!strcmp(url.user, "user")); +fail_unless(!strcmp(url.pass, "pass")); +fail_unless(url.proto == PROTO_SOCKS5); +fail_unless(url.port == 1080); END_TEST -struct -{ +struct { char *orig; int line_len; char *wrapped; @@ -145,87 +143,87 @@ struct }; START_TEST(test_word_wrap) - int i; - - for( i = 0; word_wrap_tests[i].orig && *word_wrap_tests[i].orig; i ++ ) - { - char *wrapped = word_wrap( word_wrap_tests[i].orig, word_wrap_tests[i].line_len ); - - fail_unless( strcmp( word_wrap_tests[i].wrapped, wrapped ) == 0, - "%s (line_len = %d) should wrap to `%s', not to `%s'", - word_wrap_tests[i].orig, word_wrap_tests[i].line_len, - word_wrap_tests[i].wrapped, wrapped ); - - g_free( wrapped ); - } +int i; + +for (i = 0; word_wrap_tests[i].orig && *word_wrap_tests[i].orig; i++) { + char *wrapped = word_wrap(word_wrap_tests[i].orig, word_wrap_tests[i].line_len); + + fail_unless(strcmp(word_wrap_tests[i].wrapped, wrapped) == 0, + "%s (line_len = %d) should wrap to `%s', not to `%s'", + word_wrap_tests[i].orig, word_wrap_tests[i].line_len, + word_wrap_tests[i].wrapped, wrapped); + + g_free(wrapped); +} END_TEST START_TEST(test_http_encode) - char s[80]; - - strcpy( s, "ee\xc3""\xab""ee!!..." ); - http_encode( s ); - fail_unless( strcmp( s, "ee%C3%ABee%21%21..." ) == 0 ); +char s[80]; + +strcpy(s, "ee\xc3" "\xab" "ee!!..."); +http_encode(s); +fail_unless(strcmp(s, "ee%C3%ABee%21%21...") == 0); END_TEST struct { int limit; char *command; - char *expected[IRC_MAX_ARGS+1]; + char *expected[IRC_MAX_ARGS + 1]; } split_tests[] = { { 0, "account add etc \"user name with spaces\" 'pass\\ word'", - {"account", "add", "etc", "user name with spaces", "pass\\ word", NULL}, + { "account", "add", "etc", "user name with spaces", "pass\\ word", NULL }, }, { 0, "channel set group Close\\ friends", - {"channel", "set", "group", "Close friends", NULL}, + { "channel", "set", "group", "Close friends", NULL }, }, { 2, "reply wilmer \"testing in C is a PITA\", you said.", - {"reply", "wilmer", "\"testing in C is a PITA\", you said.", NULL}, + { "reply", "wilmer", "\"testing in C is a PITA\", you said.", NULL }, }, { 4, "one space two spaces limit limit", - {"one", "space", "two", "spaces", "limit limit", NULL}, + { "one", "space", "two", "spaces", "limit limit", NULL }, }, { 0, NULL, - {NULL} + { NULL } }, }; START_TEST(test_split_command_parts) - int i; - for (i = 0; split_tests[i].command; i++) { - char *cmd = g_strdup(split_tests[i].command); - char **split = split_command_parts(cmd, split_tests[i].limit); - char **expected = split_tests[i].expected; - - int j; - for (j = 0; split[j] && expected[j]; j++) { - fail_unless (strcmp(split[j], expected[j]) == 0, - "(%d) split_command_parts broken: split(\"%s\")[%d] -> %s (expected: %s)", - i, split_tests[i].command, j, split[j], expected[j]); - } - g_free(cmd); +int i; +for (i = 0; split_tests[i].command; i++) { + char *cmd = g_strdup(split_tests[i].command); + char **split = split_command_parts(cmd, split_tests[i].limit); + char **expected = split_tests[i].expected; + + int j; + for (j = 0; split[j] && expected[j]; j++) { + fail_unless(strcmp(split[j], expected[j]) == 0, + "(%d) split_command_parts broken: split(\"%s\")[%d] -> %s (expected: %s)", + i, split_tests[i].command, j, split[j], expected[j]); } + g_free(cmd); +} END_TEST -Suite *util_suite (void) +Suite *util_suite(void) { Suite *s = suite_create("Util"); TCase *tc_core = tcase_create("Core"); - suite_add_tcase (s, tc_core); - tcase_add_test (tc_core, test_strip_linefeed); - tcase_add_test (tc_core, test_strip_newlines); - tcase_add_test (tc_core, test_set_url_http); - tcase_add_test (tc_core, test_set_url_https); - tcase_add_test (tc_core, test_set_url_port); - tcase_add_test (tc_core, test_set_url_username); - tcase_add_test (tc_core, test_set_url_username_pwd); - tcase_add_test (tc_core, test_word_wrap); - tcase_add_test (tc_core, test_http_encode); - tcase_add_test (tc_core, test_split_command_parts); + + suite_add_tcase(s, tc_core); + tcase_add_test(tc_core, test_strip_linefeed); + tcase_add_test(tc_core, test_strip_newlines); + tcase_add_test(tc_core, test_set_url_http); + tcase_add_test(tc_core, test_set_url_https); + tcase_add_test(tc_core, test_set_url_port); + tcase_add_test(tc_core, test_set_url_username); + tcase_add_test(tc_core, test_set_url_username_pwd); + tcase_add_test(tc_core, test_word_wrap); + tcase_add_test(tc_core, test_http_encode); + tcase_add_test(tc_core, test_split_command_parts); return s; } diff --git a/tests/testsuite.h b/tests/testsuite.h index 0b169198..35c77682 100644 --- a/tests/testsuite.h +++ b/tests/testsuite.h @@ -1,5 +1,5 @@ #ifndef __BITLBEE_CHECK_H__ -#define __BITLBEE_CHECK_H__ +#define __BITLBEE_CHECK_H__ #include "irc.h" @@ -1,4 +1,4 @@ - /********************************************************************\ +/********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * * Copyright 2002-2012 Wilmer van der Gaast and others * @@ -45,250 +45,233 @@ #include "otr.h" #endif -global_t global; /* Against global namespace pollution */ +global_t global; /* Against global namespace pollution */ static int signal_shutdown_pipe[2] = { -1, -1 }; -static void sighandler_shutdown( int signal ); -static void sighandler_crash( int signal ); +static void sighandler_shutdown(int signal); +static void sighandler_crash(int signal); -static int crypt_main( int argc, char *argv[] ); +static int crypt_main(int argc, char *argv[]); -int main( int argc, char *argv[] ) +int main(int argc, char *argv[]) { int i = 0; char *old_cwd = NULL; struct sigaction sig, old; - + /* Required to make iconv to ASCII//TRANSLIT work. This makes BitlBee system-locale-sensitive. :-( */ - setlocale( LC_CTYPE, "" ); - - if( argc > 1 && strcmp( argv[1], "-x" ) == 0 ) - return crypt_main( argc, argv ); - + setlocale(LC_CTYPE, ""); + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + return crypt_main(argc, argv); + } + log_init(); - - global.conf_file = g_strdup( CONF_FILE_DEF ); - global.conf = conf_load( argc, argv ); - if( global.conf == NULL ) - return( 1 ); - + + global.conf_file = g_strdup(CONF_FILE_DEF); + global.conf = conf_load(argc, argv); + if (global.conf == NULL) { + return(1); + } + b_main_init(); - + /* libpurple doesn't like fork()s after initializing itself, so if we use it, do this init a little later (in case we're running in ForkDaemon mode). */ #ifndef WITH_PURPLE nogaim_init(); #endif - + #ifdef OTR_BI - otr_init(); + otr_init(); #endif - - global.helpfile = g_strdup( HELP_FILE ); - if( help_init( &global.help, global.helpfile ) == NULL ) - log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE ); - - global.storage = storage_init( global.conf->primary_storage, global.conf->migrate_storage ); - if( global.storage == NULL ) - { - log_message( LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage ); - return( 1 ); + + global.helpfile = g_strdup(HELP_FILE); + if (help_init(&global.help, global.helpfile) == NULL) { + log_message(LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE); } - - if( global.conf->runmode == RUNMODE_INETD ) - { - log_link( LOGLVL_ERROR, LOGOUTPUT_IRC ); - log_link( LOGLVL_WARNING, LOGOUTPUT_IRC ); - - i = bitlbee_inetd_init(); - log_message( LOGLVL_INFO, "%s %s starting in inetd mode.", PACKAGE, BITLBEE_VERSION ); + global.storage = storage_init(global.conf->primary_storage, global.conf->migrate_storage); + if (global.storage == NULL) { + log_message(LOGLVL_ERROR, "Unable to load storage backend '%s'", global.conf->primary_storage); + return(1); } - else if( global.conf->runmode == RUNMODE_DAEMON ) - { - log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); - log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); + + if (global.conf->runmode == RUNMODE_INETD) { + log_link(LOGLVL_ERROR, LOGOUTPUT_IRC); + log_link(LOGLVL_WARNING, LOGOUTPUT_IRC); + + i = bitlbee_inetd_init(); + log_message(LOGLVL_INFO, "%s %s starting in inetd mode.", PACKAGE, BITLBEE_VERSION); + + } else if (global.conf->runmode == RUNMODE_DAEMON) { + log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE); + log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE); i = bitlbee_daemon_init(); - log_message( LOGLVL_INFO, "%s %s starting in daemon mode.", PACKAGE, BITLBEE_VERSION ); - } - else if( global.conf->runmode == RUNMODE_FORKDAEMON ) - { - log_link( LOGLVL_ERROR, LOGOUTPUT_CONSOLE ); - log_link( LOGLVL_WARNING, LOGOUTPUT_CONSOLE ); + log_message(LOGLVL_INFO, "%s %s starting in daemon mode.", PACKAGE, BITLBEE_VERSION); + } else if (global.conf->runmode == RUNMODE_FORKDAEMON) { + log_link(LOGLVL_ERROR, LOGOUTPUT_CONSOLE); + log_link(LOGLVL_WARNING, LOGOUTPUT_CONSOLE); /* In case the operator requests a restart, we need this. */ - old_cwd = g_malloc( 256 ); - if( getcwd( old_cwd, 255 ) == NULL ) - { - log_message( LOGLVL_WARNING, "Could not save current directory: %s", strerror( errno ) ); - g_free( old_cwd ); + old_cwd = g_malloc(256); + if (getcwd(old_cwd, 255) == NULL) { + log_message(LOGLVL_WARNING, "Could not save current directory: %s", strerror(errno)); + g_free(old_cwd); old_cwd = NULL; } - + i = bitlbee_daemon_init(); - log_message( LOGLVL_INFO, "%s %s starting in forking daemon mode.", PACKAGE, BITLBEE_VERSION ); + log_message(LOGLVL_INFO, "%s %s starting in forking daemon mode.", PACKAGE, BITLBEE_VERSION); + } + if (i != 0) { + return(i); } - if( i != 0 ) - return( i ); - - if( ( global.conf->user && *global.conf->user ) && - ( global.conf->runmode == RUNMODE_DAEMON || - global.conf->runmode == RUNMODE_FORKDAEMON ) && - ( !getuid() || !geteuid() ) ) - { + + if ((global.conf->user && *global.conf->user) && + (global.conf->runmode == RUNMODE_DAEMON || + global.conf->runmode == RUNMODE_FORKDAEMON) && + (!getuid() || !geteuid())) { struct passwd *pw = NULL; - pw = getpwnam( global.conf->user ); - if( pw ) - { - initgroups( global.conf->user, pw->pw_gid ); - setgid( pw->pw_gid ); - setuid( pw->pw_uid ); - } - else - { - log_message( LOGLVL_WARNING, "Failed to look up user %s.", global.conf->user ); + pw = getpwnam(global.conf->user); + if (pw) { + initgroups(global.conf->user, pw->pw_gid); + setgid(pw->pw_gid); + setuid(pw->pw_uid); + } else { + log_message(LOGLVL_WARNING, "Failed to look up user %s.", global.conf->user); } } - + /* Catch some signals to tell the user what's happening before quitting */ - memset( &sig, 0, sizeof( sig ) ); + memset(&sig, 0, sizeof(sig)); sig.sa_handler = SIG_IGN; - sigaction( SIGCHLD, &sig, &old ); - sigaction( SIGPIPE, &sig, &old ); + sigaction(SIGCHLD, &sig, &old); + sigaction(SIGPIPE, &sig, &old); sig.sa_flags = SA_RESETHAND; sig.sa_handler = sighandler_crash; - sigaction( SIGSEGV, &sig, &old ); + sigaction(SIGSEGV, &sig, &old); /* Use a pipe for SIGTERM/SIGINT so the actual signal handler doesn't do anything unsafe */ - if ( pipe( signal_shutdown_pipe ) == 0 ) { - b_input_add( signal_shutdown_pipe[0], B_EV_IO_READ, bitlbee_shutdown, NULL ); + if (pipe(signal_shutdown_pipe) == 0) { + b_input_add(signal_shutdown_pipe[0], B_EV_IO_READ, bitlbee_shutdown, NULL); sig.sa_handler = sighandler_shutdown; - sigaction( SIGINT, &sig, &old ); - sigaction( SIGTERM, &sig, &old ); + sigaction(SIGINT, &sig, &old); + sigaction(SIGTERM, &sig, &old); } - - if( !getuid() || !geteuid() ) - log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" ); - + + if (!getuid() || !geteuid()) { + log_message(LOGLVL_WARNING, "BitlBee is running with root privileges. Why?"); + } + b_main_run(); - + /* Mainly good for restarting, to make sure we close the help.txt fd. */ - help_free( &global.help ); - - if( global.restart ) - { + help_free(&global.help); + + if (global.restart) { char *fn = ipc_master_save_state(); char *env; - - env = g_strdup_printf( "_BITLBEE_RESTART_STATE=%s", fn ); - putenv( env ); - g_free( fn ); + + env = g_strdup_printf("_BITLBEE_RESTART_STATE=%s", fn); + putenv(env); + g_free(fn); /* Looks like env should *not* be freed here as putenv doesn't make a copy. Odd. */ - - i = chdir( old_cwd ); - close( global.listen_socket ); - - if( execv( argv[0], argv ) == -1 ) + + i = chdir(old_cwd); + close(global.listen_socket); + + if (execv(argv[0], argv) == -1) { /* Apparently the execve() failed, so let's just jump back into our own/current main(). */ /* Need more cleanup code to make this work. */ return 1; /* main( argc, argv ); */ + } } - - return( 0 ); + + return(0); } -static int crypt_main( int argc, char *argv[] ) +static int crypt_main(int argc, char *argv[]) { int pass_len; unsigned char *pass_cr, *pass_cl; - - if( argc < 4 || ( strcmp( argv[2], "hash" ) != 0 && - strcmp( argv[2], "unhash" ) != 0 && argc < 5 ) ) - { - printf( "Supported:\n" - " %s -x enc <key> <cleartext password>\n" - " %s -x dec <key> <encrypted password>\n" - " %s -x hash <cleartext password>\n" - " %s -x unhash <hashed password>\n" - " %s -x chkhash <hashed password> <cleartext password>\n", - argv[0], argv[0], argv[0], argv[0], argv[0] ); - } - else if( strcmp( argv[2], "enc" ) == 0 ) - { - pass_len = arc_encode( argv[4], strlen( argv[4] ), (unsigned char**) &pass_cr, argv[3], 12 ); - printf( "%s\n", base64_encode( pass_cr, pass_len ) ); - } - else if( strcmp( argv[2], "dec" ) == 0 ) - { - pass_len = base64_decode( argv[4], (unsigned char**) &pass_cr ); - arc_decode( pass_cr, pass_len, (char**) &pass_cl, argv[3] ); - printf( "%s\n", pass_cl ); - } - else if( strcmp( argv[2], "hash" ) == 0 ) - { + + if (argc < 4 || (strcmp(argv[2], "hash") != 0 && + strcmp(argv[2], "unhash") != 0 && argc < 5)) { + printf("Supported:\n" + " %s -x enc <key> <cleartext password>\n" + " %s -x dec <key> <encrypted password>\n" + " %s -x hash <cleartext password>\n" + " %s -x unhash <hashed password>\n" + " %s -x chkhash <hashed password> <cleartext password>\n", + argv[0], argv[0], argv[0], argv[0], argv[0]); + } else if (strcmp(argv[2], "enc") == 0) { + pass_len = arc_encode(argv[4], strlen(argv[4]), (unsigned char **) &pass_cr, argv[3], 12); + printf("%s\n", base64_encode(pass_cr, pass_len)); + } else if (strcmp(argv[2], "dec") == 0) { + pass_len = base64_decode(argv[4], (unsigned char **) &pass_cr); + arc_decode(pass_cr, pass_len, (char **) &pass_cl, argv[3]); + printf("%s\n", pass_cl); + } else if (strcmp(argv[2], "hash") == 0) { md5_byte_t pass_md5[21]; md5_state_t md5_state; - - random_bytes( pass_md5 + 16, 5 ); - md5_init( &md5_state ); - md5_append( &md5_state, (md5_byte_t*) argv[3], strlen( argv[3] ) ); - md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */ - md5_finish( &md5_state, pass_md5 ); - - printf( "%s\n", base64_encode( pass_md5, 21 ) ); - } - else if( strcmp( argv[2], "unhash" ) == 0 ) - { - printf( "Hash %s submitted to a massive Beowulf cluster of\n" - "overclocked 486s. Expect your answer next year somewhere around this time. :-)\n", argv[3] ); - } - else if( strcmp( argv[2], "chkhash" ) == 0 ) - { - char *hash = strncmp( argv[3], "md5:", 4 ) == 0 ? argv[3] + 4 : argv[3]; - int st = md5_verify_password( argv[4], hash ); - - printf( "Hash %s given password.\n", st == 0 ? "matches" : "does not match" ); - + + random_bytes(pass_md5 + 16, 5); + md5_init(&md5_state); + md5_append(&md5_state, (md5_byte_t *) argv[3], strlen(argv[3])); + md5_append(&md5_state, pass_md5 + 16, 5); /* Add the salt. */ + md5_finish(&md5_state, pass_md5); + + printf("%s\n", base64_encode(pass_md5, 21)); + } else if (strcmp(argv[2], "unhash") == 0) { + printf("Hash %s submitted to a massive Beowulf cluster of\n" + "overclocked 486s. Expect your answer next year somewhere around this time. :-)\n", argv[3]); + } else if (strcmp(argv[2], "chkhash") == 0) { + char *hash = strncmp(argv[3], "md5:", 4) == 0 ? argv[3] + 4 : argv[3]; + int st = md5_verify_password(argv[4], hash); + + printf("Hash %s given password.\n", st == 0 ? "matches" : "does not match"); + return st; } - + return 0; } /* Signal handler for SIGTERM and SIGINT */ -static void sighandler_shutdown( int signal ) +static void sighandler_shutdown(int signal) { /* Write a single null byte to the pipe, just to send a message to the main loop. * This gets handled by bitlbee_shutdown (the b_input_add callback for this pipe) */ - write( signal_shutdown_pipe[1], "", 1 ); + write(signal_shutdown_pipe[1], "", 1); } /* Signal handler for SIGSEGV * A desperate attempt to tell the user that everything is wrong in the world. * Avoids using irc_abort() because it has several unsafe calls to malloc */ -static void sighandler_crash( int signal ) +static void sighandler_crash(int signal) { GSList *l; const char *message = "ERROR :BitlBee crashed! (SIGSEGV received)\r\n"; int len = strlen(message); - for (l = irc_connection_list; l; l = l->next ) { + for (l = irc_connection_list; l; l = l->next) { irc_t *irc = l->data; - write( irc->fd, message, len ); + write(irc->fd, message, len); } - raise( signal ); + raise(signal); } double gettime() { struct timeval time[1]; - gettimeofday( time, 0 ); - return( (double) time->tv_sec + (double) time->tv_usec / 1000000 ); + gettimeofday(time, 0); + return((double) time->tv_sec + (double) time->tv_usec / 1000000); } diff --git a/utils/bitlbeed.c b/utils/bitlbeed.c index 82bd0879..c4fa8ad0 100644 --- a/utils/bitlbeed.c +++ b/utils/bitlbeed.c @@ -12,9 +12,9 @@ * Modified by M. Dennis, 20040627 * \****************************************************************/ -/* +/* ChangeLog: - + 2004-06-27: Added support for AF_LOCAL (UNIX domain) sockets Renamed log to do_log to fix conflict warning Changed protocol to 0 (6 is not supported?) @@ -49,407 +49,365 @@ #include <netinet/in.h> #include <arpa/inet.h> -typedef struct settings -{ +typedef struct settings { char local; char debug; char *interface; signed int port; - + unsigned char max_conn; int seconds; - + int rate_seconds; int rate_times; int rate_ignore; - + char **call; } settings_t; -typedef struct ipstats -{ +typedef struct ipstats { unsigned int ip; - + time_t rate_start; int rate_times; time_t rate_ignore; - + struct ipstats *next; } ipstats_t; FILE *logfile; ipstats_t *ipstats; -settings_t *set_load( int argc, char *argv[] ); -void do_log( char *fmt, ... ); -ipstats_t *ip_get( char *ip_txt ); +settings_t *set_load(int argc, char *argv[]); +void do_log(char *fmt, ...); +ipstats_t *ip_get(char *ip_txt); -int main( int argc, char *argv[] ) +int main(int argc, char *argv[]) { const int rebind_on = 1; settings_t *set; - + int serv_fd, serv_len; struct sockaddr_in serv_addr; struct sockaddr_un local_addr; - + pid_t st; - - if( !( set = set_load( argc, argv ) ) ) - return( 1 ); - - if( !logfile ) - if( !( logfile = fopen( "/dev/null", "w" ) ) ) - { - perror( "fopen" ); - return( 1 ); + + if (!(set = set_load(argc, argv))) { + return(1); + } + + if (!logfile) { + if (!(logfile = fopen("/dev/null", "w"))) { + perror("fopen"); + return(1); } - - fcntl( fileno( logfile ), F_SETFD, FD_CLOEXEC ); - - if( set->local ) - serv_fd = socket( PF_LOCAL, SOCK_STREAM, 0 ); - else - serv_fd = socket( PF_INET, SOCK_STREAM, 0 ); - if( serv_fd < 0 ) - { - perror( "socket" ); - return( 1 ); } - setsockopt( serv_fd, SOL_SOCKET, SO_REUSEADDR, &rebind_on, sizeof( rebind_on ) ); - fcntl( serv_fd, F_SETFD, FD_CLOEXEC ); + + fcntl(fileno(logfile), F_SETFD, FD_CLOEXEC); + + if (set->local) { + serv_fd = socket(PF_LOCAL, SOCK_STREAM, 0); + } else { + serv_fd = socket(PF_INET, SOCK_STREAM, 0); + } + if (serv_fd < 0) { + perror("socket"); + return(1); + } + setsockopt(serv_fd, SOL_SOCKET, SO_REUSEADDR, &rebind_on, sizeof(rebind_on)); + fcntl(serv_fd, F_SETFD, FD_CLOEXEC); if (set->local) { local_addr.sun_family = AF_LOCAL; - strncpy( local_addr.sun_path, set->interface, sizeof( local_addr.sun_path ) - 1 ); - local_addr.sun_path[sizeof( local_addr.sun_path ) - 1] = '\0'; - + strncpy(local_addr.sun_path, set->interface, sizeof(local_addr.sun_path) - 1); + local_addr.sun_path[sizeof(local_addr.sun_path) - 1] = '\0'; + /* warning - don't let untrusted users run this program if it is setuid/setgid! Arbitrary file deletion risk! */ - unlink( set->interface ); - if( bind( serv_fd, (struct sockaddr *) &local_addr, SUN_LEN( &local_addr ) ) != 0 ) - { - perror( "bind" ); - return( 1 ); + unlink(set->interface); + if (bind(serv_fd, (struct sockaddr *) &local_addr, SUN_LEN(&local_addr)) != 0) { + perror("bind"); + return(1); } - chmod( set->interface, S_IRWXO|S_IRWXG|S_IRWXU ); + chmod(set->interface, S_IRWXO | S_IRWXG | S_IRWXU); } else { serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = inet_addr( set->interface ); - serv_addr.sin_port = htons( set->port ); - serv_len = sizeof( serv_addr ); - - if( bind( serv_fd, (struct sockaddr *) &serv_addr, serv_len ) != 0 ) - { - perror( "bind" ); - return( 1 ); + serv_addr.sin_addr.s_addr = inet_addr(set->interface); + serv_addr.sin_port = htons(set->port); + serv_len = sizeof(serv_addr); + + if (bind(serv_fd, (struct sockaddr *) &serv_addr, serv_len) != 0) { + perror("bind"); + return(1); } } - - if( listen( serv_fd, set->max_conn ) != 0 ) - { - perror( "listen" ); - return( 1 ); + + if (listen(serv_fd, set->max_conn) != 0) { + perror("listen"); + return(1); } - - if ( ! set->debug ) { + + if (!set->debug) { st = fork(); - if( st < 0 ) - { - perror( "fork" ); - return( 1 ); - } - else if( st > 0 ) - { - return( 0 ); + if (st < 0) { + perror("fork"); + return(1); + } else if (st > 0) { + return(0); } - + setsid(); - close( 0 ); - close( 1 ); - close( 2 ); + close(0); + close(1); + close(2); } - - do_log( "bitlbeed running" ); - + + do_log("bitlbeed running"); + /* The Daemon */ - while( 1 ) - { + while (1) { int cli_fd, cli_len, i, st; struct sockaddr_in cli_addr; struct sockaddr_un cli_local; ipstats_t *ip; char *cli_txt; pid_t child; - + static int running = 0; - + fd_set rd; struct timeval tm; - + /* accept() only returns after someone connects. To clean up old processes (by running waitpid()) it's better to use select() with a timeout. */ - FD_ZERO( &rd ); - FD_SET( serv_fd, &rd ); + FD_ZERO(&rd); + FD_SET(serv_fd, &rd); tm.tv_sec = SELECT_TIMEOUT; tm.tv_usec = 0; - if( select( serv_fd + 1, &rd, NULL, NULL, &tm ) > 0 ) - { + if (select(serv_fd + 1, &rd, NULL, NULL, &tm) > 0) { if (set->local) { - cli_len = SUN_LEN( &cli_local ); - cli_fd = accept( serv_fd, (struct sockaddr *) &cli_local, &cli_len ); + cli_len = SUN_LEN(&cli_local); + cli_fd = accept(serv_fd, (struct sockaddr *) &cli_local, &cli_len); cli_txt = "127.0.0.1"; } else { - cli_len = sizeof( cli_addr ); - cli_fd = accept( serv_fd, (struct sockaddr *) &cli_addr, &cli_len ); - cli_txt = inet_ntoa( cli_addr.sin_addr ); + cli_len = sizeof(cli_addr); + cli_fd = accept(serv_fd, (struct sockaddr *) &cli_addr, &cli_len); + cli_txt = inet_ntoa(cli_addr.sin_addr); } - - ip = ip_get( cli_txt ); - - if( set->rate_times == 0 || time( NULL ) > ip->rate_ignore ) - { + + ip = ip_get(cli_txt); + + if (set->rate_times == 0 || time(NULL) > ip->rate_ignore) { /* We want this socket on stdout and stderr too! */ - dup( cli_fd ); dup( cli_fd ); - - if( ( child = fork() ) == 0 ) - { - if( set->seconds ) - { + dup(cli_fd); dup(cli_fd); + + if ((child = fork()) == 0) { + if (set->seconds) { struct rlimit li; - + li.rlim_cur = (rlim_t) set->seconds; li.rlim_max = (rlim_t) set->seconds + 1; - setrlimit( RLIMIT_CPU, &li ); + setrlimit(RLIMIT_CPU, &li); } - execv( set->call[0], set->call ); - do_log( "Error while executing %s!", set->call[0] ); - return( 1 ); + execv(set->call[0], set->call); + do_log("Error while executing %s!", set->call[0]); + return(1); } - - running ++; - close( 0 ); - close( 1 ); - close( 2 ); - - do_log( "Started child process for client %s (PID=%d), got %d clients now", cli_txt, child, running ); - - if( time( NULL ) < ( ip->rate_start + set->rate_seconds ) ) - { - ip->rate_times ++; - if( ip->rate_times >= set->rate_times ) - { - do_log( "Client %s crossed the limit; ignoring for the next %d seconds", cli_txt, set->rate_ignore ); - ip->rate_ignore = time( NULL ) + set->rate_ignore; + + running++; + close(0); + close(1); + close(2); + + do_log("Started child process for client %s (PID=%d), got %d clients now", cli_txt, + child, running); + + if (time(NULL) < (ip->rate_start + set->rate_seconds)) { + ip->rate_times++; + if (ip->rate_times >= set->rate_times) { + do_log("Client %s crossed the limit; ignoring for the next %d seconds", + cli_txt, set->rate_ignore); + ip->rate_ignore = time(NULL) + set->rate_ignore; ip->rate_start = 0; } - } - else - { - ip->rate_start = time( NULL ); + } else { + ip->rate_start = time(NULL); ip->rate_times = 1; } - } - else - { - do_log( "Ignoring connection from %s", cli_txt ); - close( cli_fd ); + } else { + do_log("Ignoring connection from %s", cli_txt); + close(cli_fd); } } - + /* If the max. number of connection is reached, don't accept new connections until one expires -> Not always WNOHANG - + Cleaning up child processes is a good idea anyway... :-) */ - while( ( i = waitpid( 0, &st, ( ( running < set->max_conn ) || ( set->max_conn == 0 ) ) ? WNOHANG : 0 ) ) > 0 ) - { - running --; - if( WIFEXITED( st ) ) - { - do_log( "Child process (PID=%d) exited normally with status %d. %d Clients left now", - i, WEXITSTATUS( st ), running ); - } - else if( WIFSIGNALED( st ) ) - { - do_log( "Child process (PID=%d) killed by signal %d. %d Clients left now", - i, WTERMSIG( st ), running ); - } - else - { + while ((i = waitpid(0, &st, ((running < set->max_conn) || (set->max_conn == 0)) ? WNOHANG : 0)) > 0) { + running--; + if (WIFEXITED(st)) { + do_log("Child process (PID=%d) exited normally with status %d. %d Clients left now", + i, WEXITSTATUS(st), running); + } else if (WIFSIGNALED(st)) { + do_log("Child process (PID=%d) killed by signal %d. %d Clients left now", + i, WTERMSIG(st), running); + } else { /* Should not happen AFAIK... */ - do_log( "Child process (PID=%d) stopped for unknown reason, %d clients left now", - i, running ); + do_log("Child process (PID=%d) stopped for unknown reason, %d clients left now", + i, running); } } } - - return( 0 ); + + return(0); } -settings_t *set_load( int argc, char *argv[] ) +settings_t *set_load(int argc, char *argv[]) { settings_t *set; int opt, i; - - set = malloc( sizeof( settings_t ) ); - memset( set, 0, sizeof( settings_t ) ); - set->interface = NULL; /* will be filled in later */ + + set = malloc(sizeof(settings_t)); + memset(set, 0, sizeof(settings_t)); + set->interface = NULL; /* will be filled in later */ set->port = 6667; set->local = 0; set->debug = 0; - + set->rate_seconds = 600; set->rate_times = 5; set->rate_ignore = 900; - - while( ( opt = getopt( argc, argv, "i:p:n:t:l:r:hud" ) ) >= 0 ) - { - if( opt == 'i' ) - { - set->interface = strdup( optarg ); - } - else if( opt == 'p' ) - { - if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i <= 0 ) || ( i > 65535 ) ) - { - fprintf( stderr, "Invalid port number: %s\n", optarg ); - return( NULL ); + + while ((opt = getopt(argc, argv, "i:p:n:t:l:r:hud")) >= 0) { + if (opt == 'i') { + set->interface = strdup(optarg); + } else if (opt == 'p') { + if ((sscanf(optarg, "%d", &i) != 1) || (i <= 0) || (i > 65535)) { + fprintf(stderr, "Invalid port number: %s\n", optarg); + return(NULL); } set->port = i; - } - else if( opt == 'n' ) - { - if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i < 0 ) ) - { - fprintf( stderr, "Invalid number of connections: %s\n", optarg ); - return( NULL ); + } else if (opt == 'n') { + if ((sscanf(optarg, "%d", &i) != 1) || (i < 0)) { + fprintf(stderr, "Invalid number of connections: %s\n", optarg); + return(NULL); } set->max_conn = i; - } - else if( opt == 't' ) - { - if( ( sscanf( optarg, "%d", &i ) != 1 ) || ( i < 0 ) || ( i > 600 ) ) - { - fprintf( stderr, "Invalid number of seconds: %s\n", optarg ); - return( NULL ); + } else if (opt == 't') { + if ((sscanf(optarg, "%d", &i) != 1) || (i < 0) || (i > 600)) { + fprintf(stderr, "Invalid number of seconds: %s\n", optarg); + return(NULL); } set->seconds = i; - } - else if( opt == 'l' ) - { - if( !( logfile = fopen( optarg, "a" ) ) ) - { - perror( "fopen" ); - fprintf( stderr, "Error opening logfile, giving up.\n" ); - return( NULL ); + } else if (opt == 'l') { + if (!(logfile = fopen(optarg, "a"))) { + perror("fopen"); + fprintf(stderr, "Error opening logfile, giving up.\n"); + return(NULL); } - setbuf( logfile, NULL ); - } - else if( opt == 'r' ) - { - if( sscanf( optarg, "%d,%d,%d", &set->rate_seconds, &set->rate_times, &set->rate_ignore ) != 3 ) - { - fprintf( stderr, "Invalid argument to -r.\n" ); - return( NULL ); + setbuf(logfile, NULL); + } else if (opt == 'r') { + if (sscanf(optarg, "%d,%d,%d", &set->rate_seconds, &set->rate_times, &set->rate_ignore) != 3) { + fprintf(stderr, "Invalid argument to -r.\n"); + return(NULL); } - } - else if( opt == 'u' ) + } else if (opt == 'u') { set->local = 1; - else if( opt == 'd' ) + } else if (opt == 'd') { set->debug = 1; - else if( opt == 'h' ) - { - printf( "Usage: %s [-i <interface>] [-p <port>] [-n <num>] [-r x,y,z] ...\n" - " ... <command> <args...>\n" - "A simple inetd-like daemon to have a program listening on a TCP socket without\n" - "needing root access to the machine\n" - "\n" - " -i Specify the interface (by IP address) to listen on.\n" - " (Default: 0.0.0.0 (any interface))\n" - " -p Port number to listen on. (Default: 6667)\n" - " -n Maximum number of connections. (Default: 0 (unlimited))\n" - " -t Specify the maximum number of CPU seconds per process.\n" - " (Default: 0 (unlimited))\n" - " -l Specify a logfile. (Default: none)\n" - " -r Rate limiting: Ignore a host for z seconds when it connects for more\n" - " than y times in x seconds. (Default: 600,5,900. Disable: 0,0,0)\n" - " -u Use a local socket, by default /tmp/bitlbee (override with -i <filename>)\n" - " -d Don't fork for listening (for debugging purposes)\n" - " -h This information\n", argv[0] ); - return( NULL ); + } else if (opt == 'h') { + printf("Usage: %s [-i <interface>] [-p <port>] [-n <num>] [-r x,y,z] ...\n" + " ... <command> <args...>\n" + "A simple inetd-like daemon to have a program listening on a TCP socket without\n" + "needing root access to the machine\n" + "\n" + " -i Specify the interface (by IP address) to listen on.\n" + " (Default: 0.0.0.0 (any interface))\n" + " -p Port number to listen on. (Default: 6667)\n" + " -n Maximum number of connections. (Default: 0 (unlimited))\n" + " -t Specify the maximum number of CPU seconds per process.\n" + " (Default: 0 (unlimited))\n" + " -l Specify a logfile. (Default: none)\n" + " -r Rate limiting: Ignore a host for z seconds when it connects for more\n" + " than y times in x seconds. (Default: 600,5,900. Disable: 0,0,0)\n" + " -u Use a local socket, by default /tmp/bitlbee (override with -i <filename>)\n" + " -d Don't fork for listening (for debugging purposes)\n" + " -h This information\n", argv[0]); + return(NULL); } } - - if( set->interface == NULL ) + + if (set->interface == NULL) { set->interface = (set->local) ? "/tmp/bitlbee" : "0.0.0.0"; - - if( optind == argc ) - { - fprintf( stderr, "Missing program parameter!\n" ); - return( NULL ); } - + + if (optind == argc) { + fprintf(stderr, "Missing program parameter!\n"); + return(NULL); + } + /* The remaining arguments are the executable and its arguments */ - set->call = malloc( ( argc - optind + 1 ) * sizeof( char* ) ); - memcpy( set->call, argv + optind, sizeof( char* ) * ( argc - optind ) ); - set->call[argc-optind] = NULL; - - return( set ); + set->call = malloc((argc - optind + 1) * sizeof(char*)); + memcpy(set->call, argv + optind, sizeof(char*) * (argc - optind)); + set->call[argc - optind] = NULL; + + return(set); } -void do_log( char *fmt, ... ) +void do_log(char *fmt, ...) { va_list params; char line[MAX_LOG_LEN]; time_t tm; int l; - - memset( line, 0, MAX_LOG_LEN ); - - tm = time( NULL ); - strcpy( line, ctime( &tm ) ); - l = strlen( line ); - line[l-1] = ' '; - - va_start( params, fmt ); - vsnprintf( line + l, MAX_LOG_LEN - l - 2, fmt, params ); - va_end( params ); - strcat( line, "\n" ); - - fprintf( logfile, "%s", line ); + + memset(line, 0, MAX_LOG_LEN); + + tm = time(NULL); + strcpy(line, ctime(&tm)); + l = strlen(line); + line[l - 1] = ' '; + + va_start(params, fmt); + vsnprintf(line + l, MAX_LOG_LEN - l - 2, fmt, params); + va_end(params); + strcat(line, "\n"); + + fprintf(logfile, "%s", line); } -ipstats_t *ip_get( char *ip_txt ) +ipstats_t *ip_get(char *ip_txt) { unsigned int ip; ipstats_t *l; int p[4]; - - sscanf( ip_txt, "%d.%d.%d.%d", p + 0, p + 1, p + 2, p + 3 ); - ip = ( p[0] << 24 ) | ( p[1] << 16 ) | ( p[2] << 8 ) | ( p[3] ); - - for( l = ipstats; l; l = l->next ) - { - if( l->ip == ip ) - return( l ); + + sscanf(ip_txt, "%d.%d.%d.%d", p + 0, p + 1, p + 2, p + 3); + ip = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); + + for (l = ipstats; l; l = l->next) { + if (l->ip == ip) { + return(l); + } } - - if( ipstats ) - { - for( l = ipstats; l->next; l = l->next ); - - l->next = malloc( sizeof( ipstats_t ) ); + + if (ipstats) { + for (l = ipstats; l->next; l = l->next) { + ; + } + + l->next = malloc(sizeof(ipstats_t)); l = l->next; - } - else - { - l = malloc( sizeof( ipstats_t ) ); + } else { + l = malloc(sizeof(ipstats_t)); ipstats = l; } - memset( l, 0, sizeof( ipstats_t ) ); - + memset(l, 0, sizeof(ipstats_t)); + l->ip = ip; - - return( l ); + + return(l); } |