diff options
author | bill auger <mr.j.spam.me@gmail.com> | 2013-09-21 20:25:36 -0400 |
---|---|---|
committer | bill auger <mr.j.spam.me@gmail.com> | 2013-09-21 20:25:36 -0400 |
commit | aff1a426a265f8665f096ebe867c0ab321acbbad (patch) | |
tree | a3fd84f7fbc5441eaf1813d46896fc0171a35d1f | |
parent | 69c1ac69f05479478cf849c367deefa63de457bc (diff) |
reimplement disable/enable bridge commands
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | bridgin.c | 328 | ||||
-rw-r--r-- | bridgin.dbg.h | 41 | ||||
-rw-r--r-- | bridgin.h | 47 |
4 files changed, 266 insertions, 154 deletions
@@ -3,6 +3,10 @@ bridgin changelog 2013-09-21 - v0.5pre CURRENT + reimplemented disable/enable bridge commands + +2013-09-21 - v0.5pre + 69c1ac69f0 reimplemented remove channel command and properly free heap resources 2013-09-18 - v0.5pre @@ -32,12 +32,73 @@ void alert(char* msg) /* model helpers */ -gboolean doesBridgeExist(Bridge* aBridge) { return (aBridge != SentinelBridge) ; } +Bridge* getBridgeByChannel(PurpleConversation* aConv) +{ + Bridge* aBridge ; Channel* aChannel ; + +#ifdef DEBUG_VB +prepareChannelUid(aConv) ; DBGss("getBridgeByChannel() channel='" , ChannelUidBuffer , "'" , "") ; +#endif + + aBridge = SentinelBridge ; prepareChannelUid(aConv) ; + while ((aBridge = aBridge->next)) + { + aChannel = aBridge->sentinelChannel ; + while ((aChannel = aChannel->next)) + if (!strcmp(aChannel->uid , ChannelUidBuffer)) + return aBridge ; + } + +#ifdef DEBUG_VB +DBGss("getBridgeByChannel() '" , ChannelUidBuffer , "' not found" , "") ; +#endif -gboolean areReservedIds(char* bridgeName , char* channelUid) + return SentinelBridge ; +} + +Bridge* getBridgeByName(const char* bridgeName) +{ + Bridge* aBridge = SentinelBridge ; if (isBlank(bridgeName)) return SentinelBridge ; + + while ((aBridge = aBridge->next)) + if (!strcmp(aBridge->name , bridgeName)) + return aBridge ; + +#ifdef DEBUG_VB +DBGsds("getBridgeByName() '" , bridgeName , "' not found - " , getNBridges() , " bridges exist" , "") ; +#endif + + return SentinelBridge ; +} + +unsigned int getNBridges() +{ + Bridge* aBridge ; unsigned int n ; aBridge = SentinelBridge ; n = 0 ; + while ((aBridge = aBridge->next)) ++n ; + return n ; +} + +unsigned int getNChannels(Bridge* aBridge) +{ + Channel* aChannel ; unsigned int n ; aChannel = aBridge->sentinelChannel ; n = 0 ; + while ((aChannel = aChannel->next)) ++n ; + return n ; +} + +gboolean doesBridgeExist(Bridge* aBridge) + { return (!!aBridge && aBridge != SentinelBridge) ; } + +gboolean isServerChannel(PurpleConversation* aConv) +{ + const char* channelName = getChannelName(aConv) ; + return (!strcmp(channelName , "NickServ") || !strcmp(channelName , "MemoServ")) ; +} + +gboolean areReservedIds(char* bridgeName , char* channelUid , PurpleConversation* aConv) { return (!strcmp(bridgeName , SENTINEL_NAME) || - !strcmp(channelUid , SENTINEL_NAME)) ; + !strcmp(channelUid , SENTINEL_NAME) || + isServerChannel(aConv)) ; } void prepareBridgeKeys(char* bridgeName) @@ -58,7 +119,7 @@ void prepareChannelUid(PurpleConversation* aConv) sprintf(ChannelUidBuffer , CHANNEL_ID_FMT , protocol , username , channelName) ; } -Bridge* newBridge(char* bridgeName , Bridge* prevBridge) +Bridge* newBridge(char* bridgeName , Bridge* prevBridge , gboolean isEnabled) { Bridge* newBridge ; Channel* newChannel ; @@ -66,7 +127,7 @@ Bridge* newBridge(char* bridgeName , Bridge* prevBridge) newChannel = (Channel*)malloc(sizeof(Channel)) ; if (!newChannel) return NULL ; strcpy(newBridge->name , bridgeName) ; - newBridge->isEnabled = TRUE ; + newBridge->isEnabled = isEnabled ; newBridge->prev = prevBridge ; newBridge->next = NULL ; newBridge->sentinelChannel = newChannel ; @@ -94,35 +155,46 @@ gboolean createChannel(char* bridgeName) { Bridge* aBridge ; Channel* aChannel ; GList* channelsList = NULL ; +#ifdef DEBUG_VB DBGss("createChannel() bridgeName='" , bridgeName , "'" , "") ; +#endif prepareBridgeKeys(bridgeName) ; - if ((aBridge = getBridgeByName(bridgeName)) == SentinelBridge) + + // create bridge if necessary + if (!doesBridgeExist(aBridge = getBridgeByName(bridgeName))) { - // create new bridge + // check if we are restoring a stored config + gboolean doesConfigExist = (purple_prefs_exists(EnabledKeyBuffer)) ; + gboolean isEnabled = (!doesConfigExist || purple_prefs_get_bool(EnabledKeyBuffer)) ; + + // create new bridge struct while (aBridge->next) aBridge = aBridge->next ; - aBridge->next = newBridge(bridgeName , aBridge) ; + aBridge->next = newBridge(bridgeName , aBridge , isEnabled) ; if (!(aBridge = aBridge->next)) return FALSE ; - // store bridge config - purple_prefs_add_bool(EnabledKeyBuffer , TRUE) ; - purple_prefs_add_string_list(BridgeKeyBuffer , channelsList) ; + // store config + if (!doesConfigExist) + { + purple_prefs_add_bool(EnabledKeyBuffer , TRUE) ; + purple_prefs_add_string_list(BridgeKeyBuffer , channelsList) ; + } -DBGs("createChannel() added new bridgeKey=" , BridgeKeyBuffer) ; +DBGss("createChannel() added new bridgeKey='" , BridgeKeyBuffer , "'" , "") ; } else channelsList = purple_prefs_get_string_list(BridgeKeyBuffer) ; - // create new channel + // create new channel struct aChannel = aBridge->sentinelChannel ; while (aChannel->next) aChannel = aChannel->next ; aChannel->next = newChannel(aChannel) ; if (!aChannel->next) { g_list_free(channelsList) ; return FALSE ; } - // store bridge config + // store config channelsList = g_list_prepend(channelsList , (gpointer)ChannelUidBuffer) ; purple_prefs_set_string_list(BridgeKeyBuffer , channelsList) ; -DBGs("createChannel() added new channelUid=" , ChannelUidBuffer) ; +DBGss("createChannel() added new channelUid='" , ChannelUidBuffer , "'" , "") ; g_list_free(channelsList) ; return TRUE ; } @@ -131,6 +203,8 @@ void destroyChannel(Bridge* aBridge , PurpleConversation* aConv) { Channel* aChannel ; GList* channelsList = NULL ; GList* channelsIter = NULL ; +DBGsss("destroyChannel() removing channel='" , getChannelName(aConv) , "' from bridge='" , aBridge->name , "'" , "") ; + // destroy channel struct aChannel = aBridge->sentinelChannel ; prepareChannelUid(aConv) ; while ((aChannel = aChannel->next)) @@ -160,51 +234,13 @@ void destroyChannel(Bridge* aBridge , PurpleConversation* aConv) g_list_free(channelsList) ; g_list_free(channelsIter) ; } -Bridge* getBridgeByChannel(PurpleConversation* aConv) +void enableBridge(Bridge* aBridge , gboolean shouldEnable) // TODO: move this { - Bridge* aBridge ; Channel* aChannel ; + if (aBridge->isEnabled == shouldEnable) return ; -/*DBG*/prepareChannelUid(aConv);DBGss("getBridgeByChannel() channel='" , ChannelUidBuffer , "'" , "") ; - - aBridge = SentinelBridge ; prepareChannelUid(aConv) ; - while ((aBridge = aBridge->next)) - { - aChannel = aBridge->sentinelChannel ; - while ((aChannel = aChannel->next)) - if (!strcmp(aChannel->uid , ChannelUidBuffer)) - return aBridge ; - } - -DBGss("getBridgeByChannel() '" , ChannelUidBuffer , "' not found" , "") ; - - return SentinelBridge ; -} - -Bridge* getBridgeByName(const char* bridgeName) -{ - Bridge* aBridge = SentinelBridge ; - - while ((aBridge = aBridge->next)) - if (!strcmp(aBridge->name , bridgeName)) - return aBridge ; - -DBGsd("getBridgeByName() '" , bridgeName , "' not found - nBridges=" , getNBridges()) ; - - return SentinelBridge ; -} - -unsigned int getNBridges() -{ - Bridge* aBridge ; unsigned int n ; aBridge = SentinelBridge ; n = 0 ; - while ((aBridge = aBridge->next)) ++n ; - return n ; -} - -unsigned int getNChannels(Bridge* aBridge) -{ - Channel* aChannel ; unsigned int n ; aChannel = aBridge->sentinelChannel ; n = 0 ; - while ((aChannel = aChannel->next)) ++n ; - return n ; + aBridge->isEnabled = shouldEnable ; + prepareBridgeKeys(aBridge->name) ; + purple_prefs_set_bool(EnabledKeyBuffer , shouldEnable) ; } @@ -222,52 +258,58 @@ gboolean handlePluginLoaded(PurplePlugin* aPlugin) DBG("handlePluginLoaded()") ; // init - SentinelBridge = newBridge(SENTINEL_NAME , NULL) ; + SentinelBridge = newBridge(SENTINEL_NAME , NULL , FALSE) ; if (!SentinelBridge) { alert(OOM_MSG) ; return FALSE ; } // register admin commands - CommandIds[0] = registerCmd(ADD_CMD , UNARY_FMT , ADD_CB , ADDu_HELP) ; - CommandIds[1] = registerCmd(ADD_CMD , BINARY_FMT , ADD_CB , ADDb_HELP) ; - CommandIds[2] = registerCmd(REMOVE_CMD , UNARY_FMT , REMOVE_CB , REMOVE_HELP) ; - CommandIds[3] = registerCmd(DISABLE_CMD , UNARY_FMT , ENABLE_CB , DISABLEu_HELP) ; - CommandIds[4] = registerCmd(DISABLE_CMD , BINARY_FMT , ENABLE_CB , DISABLEb_HELP) ; - CommandIds[5] = registerCmd(ENABLE_CMD , UNARY_FMT , ENABLE_CB , ENABLEu_HELP) ; - CommandIds[6] = registerCmd(ENABLE_CMD , BINARY_FMT , ENABLE_CB , ENABLEb_HELP) ; - CommandIds[7] = registerCmd(ECHO_CMD , BINARY_FMT , ECHO_CB , ECHO_HELP) ; - CommandIds[8] = registerCmd(CHAT_CMD , BINARY_FMT , CHAT_CB , CHAT_HELP) ; - CommandIds[9] = registerCmd(BCAST_CMD , BINARY_FMT , BCAST_CB , BCAST_HELP) ; - CommandIds[10] = registerCmd(STATUS_CMD , UNARY_FMT , STATUS_CB , STATUSu_HELP) ; - CommandIds[11] = registerCmd(STATUS_CMD , BINARY_FMT , STATUS_CB , STATUSb_HELP) ; - CommandIds[12] = registerCmd(HELP_CMD , UNARY_FMT , HELP_CB , HELP_HELP) ; + CommandIds[0] = registerCmd(ADD_CMD , UNARY_FMT , ADD_CB , ADDu_HELP) ; + CommandIds[1] = registerCmd(ADD_CMD , BINARY_FMT , ADD_CB , ADDb_HELP) ; + CommandIds[2] = registerCmd(REMOVE_CMD , UNARY_FMT , REMOVE_CB , REMOVE_HELP) ; + CommandIds[3] = registerCmd(DISABLE_CMD , UNARY_FMT , DISABLE_CB , DISABLEu_HELP) ; + CommandIds[4] = registerCmd(DISABLE_CMD , BINARY_FMT , DISABLE_CB , DISABLEb_HELP) ; + CommandIds[5] = registerCmd(ENABLE_CMD , UNARY_FMT , ENABLE_CB , ENABLEu_HELP) ; + CommandIds[6] = registerCmd(ENABLE_CMD , BINARY_FMT , ENABLE_CB , ENABLEb_HELP) ; + CommandIds[7] = registerCmd(ECHO_CMD , BINARY_FMT , ECHO_CB , ECHO_HELP) ; + CommandIds[8] = registerCmd(CHAT_CMD , BINARY_FMT , CHAT_CB , CHAT_HELP) ; + CommandIds[9] = registerCmd(BCAST_CMD , BINARY_FMT , BCAST_CB , BCAST_HELP) ; + CommandIds[10] = registerCmd(STATUS_CMD , UNARY_FMT , STATUS_CB , STATUSu_HELP) ; + CommandIds[11] = registerCmd(STATUS_CMD , BINARY_FMT , STATUS_CB , STATUSb_HELP) ; + CommandIds[12] = registerCmd(HELP_CMD , UNARY_FMT , HELP_CB , HELP_HELP) ; // register conversation callbacks convs = purple_conversations_get_handle() ; - purple_signal_connect(convs , RECEIVED_IM_SIGNAL , ThisPlugin , - PURPLE_CALLBACK(handleChat) , NULL) ; - purple_signal_connect(convs , RECEIVED_CHAT_SIGNAL , ThisPlugin , - PURPLE_CALLBACK(handleChat) , NULL) ; + purple_signal_connect(convs , RECEIVING_IM_SIGNAL , ThisPlugin , + PURPLE_CALLBACK(handleChat) , NULL) ; + purple_signal_connect(convs , RECEIVING_CHAT_SIGNAL , ThisPlugin , + PURPLE_CALLBACK(handleChat) , NULL) ; // restore session prefsList = purple_prefs_get_children_names(BASE_PREF_KEY) ; prefsIter = g_list_first(prefsList) ; while (prefsIter) { +#ifdef DEBUG_VB if (purple_prefs_get_type((char*)prefsIter->data) == PURPLE_PREF_BOOLEAN) -DBGsd("handlePluginLoaded() found bool prefKey=" , (char*)prefsIter->data , " val=" , purple_prefs_get_bool((char*)prefsIter->data)) ; + DBGsds("handlePluginLoaded() found bool prefKey='" , (char*)prefsIter->data , "' val='" , purple_prefs_get_bool((char*)prefsIter->data) , "'" , "") ; else if (purple_prefs_get_type((char*)prefsIter->data) == PURPLE_PREF_STRING) -DBGss("handlePluginLoaded() found string prefKey=" , (char*)prefsIter->data , " val=" , purple_prefs_get_string((char*)prefsIter->data)) ; + DBGsss("handlePluginLoaded() found string prefKey='" , (char*)prefsIter->data , "' val='" , purple_prefs_get_string((char*)prefsIter->data) , "'" , "") ; +#endif prefKey = (char*)prefsIter->data ; if (purple_prefs_get_type(prefKey) == PURPLE_PREF_STRING_LIST && (bridgeName = strrchr(prefKey , '/')) && ++bridgeName) { -DBGs("handlePluginLoaded() found stored bridgeName=" , bridgeName) ; +#ifdef DEBUG_VB +DBGss("handlePluginLoaded() found stored bridgeName='" , bridgeName , "'" , "") ; +#endif channelsList = purple_prefs_get_string_list(prefKey) ; channelsIter = g_list_first(channelsList) ; while (channelsIter) { -DBGs("handlePluginLoaded() found stored channelUid=" , (char*)channelsIter->data) ; +#ifdef DEBUG_VB +DBGss("handlePluginLoaded() found stored channelUid='" , (char*)channelsIter->data , "'" , "") ; +#endif strcpy(ChannelUidBuffer , (char*)channelsIter->data) ; if (!createChannel(bridgeName)) @@ -289,6 +331,8 @@ DBGs("handlePluginLoaded() found stored channelUid=" , (char*)channelsIter->data g_list_foreach(prefsList , (GFunc)g_free , NULL) ; g_list_free(prefsList) ; g_list_free(prefsIter) ; + chatBufferClear() ; + return TRUE ; } @@ -303,9 +347,9 @@ DBG("handlePluginUnloaded()") ; // unregister callbacks purple_prefs_disconnect_by_handle(purple_prefs_get_handle()) ; - purple_signal_disconnect(purple_conversations_get_handle() , RECEIVED_IM_SIGNAL , + purple_signal_disconnect(purple_conversations_get_handle() , RECEIVING_IM_SIGNAL , ThisPlugin , PURPLE_CALLBACK(handleChat)) ; - purple_signal_disconnect(purple_conversations_get_handle() , RECEIVED_CHAT_SIGNAL , + purple_signal_disconnect(purple_conversations_get_handle() , RECEIVING_CHAT_SIGNAL , ThisPlugin , PURPLE_CALLBACK(handleChat)) ; aBridge = SentinelBridge ; @@ -320,26 +364,34 @@ DBG("handlePluginUnloaded()") ; return TRUE ; } -void handleChat(PurpleAccount* thisAccount , char* sender , char* msg , - PurpleConversation* thisConv , PurpleMessageFlags flags , void* data) +gboolean handleChat(PurpleAccount* thisAccount , char** sender , char** msg , + PurpleConversation* thisConv , PurpleMessageFlags* flags , void* data) { GList* activeChannelsIter = NULL ; Bridge* thisBridge ; PurpleConversation* aConv ; unsigned int convType ; -// NOTE: DBGchat() should mirror changes to logic here -DBGchat(((purple_conversation_get_type(thisConv) == PURPLE_CONV_TYPE_IM)? RECEIVED_IM_SIGNAL : RECEIVED_CHAT_SIGNAL) , thisAccount , sender , thisConv , msg , flags) ; +#ifdef DEBUG_CHAT // NOTE: DBGchat() should mirror changes to logic here +if (thisConv) DBGchat(thisAccount , *sender , thisConv , *msg , *flags) ; +#endif - if (flags & PURPLE_MESSAGE_SEND) return ; - if (!(flags & PURPLE_MESSAGE_RECV)) return ; - if ((thisBridge = getBridgeByChannel(thisConv)) == SentinelBridge) return ; + if (!thisConv) return TRUE ; // supress rogue msgs (autojoined server msgs maybe unbound) - chatBufferPutSSSS(CHAT_OUT_FMT , NICK_PREFIX , sender , NICK_POSTFIX , msg) ; + thisBridge = getBridgeByChannel(thisConv) ; + if (isServerChannel(thisConv)) return FALSE ; // allow server msgs but never relay + if (*flags & PURPLE_MESSAGE_SEND) return FALSE ; // never relay unprefixed local chat + if (!(*flags & PURPLE_MESSAGE_RECV)) return FALSE ; // TODO: handle special message types + if (!doesBridgeExist(thisBridge)) return FALSE ; // input channel is unbridged + if (!thisBridge->isEnabled) return FALSE ; // input channel bridge is disabled + + chatBufferPutSSSS(CHAT_OUT_FMT , NICK_PREFIX , *sender , NICK_POSTFIX , *msg) ; // relay chat to all opened channels on this bridge activeChannelsIter = g_list_first(purple_get_conversations()) ; while (activeChannelsIter) { -DBGs("handleChat() got active channelName=" , getChannelName((PurpleConversation*)activeChannelsIter->data)) ; +#ifdef DEBUG_VB +DBGss("handleChat() got active channelName='" , getChannelName((PurpleConversation*)activeChannelsIter->data) , (((PurpleConversation*)activeChannelsIter->data == thisConv)? " isThisChannel - skipping" : ((getBridgeByChannel((PurpleConversation*)activeChannelsIter->data) == thisBridge)? "' isThisBridge - relaying" : "' notThisBridge - skipping" )) , "") ; +#endif aConv = (PurpleConversation*)activeChannelsIter->data ; if (aConv != thisConv && getBridgeByChannel(aConv) == thisBridge) @@ -353,6 +405,9 @@ DBGs("handleChat() got active channelName=" , getChannelName((PurpleConversation activeChannelsIter = g_list_next(activeChannelsIter) ; } + chatBufferClear() ; + + return FALSE ; } @@ -374,7 +429,7 @@ DBGcmd(command , args[0]) ; else { prepareChannelUid(thisConv) ; - if (!areReservedIds(bridgeName , ChannelUidBuffer)) + if (!areReservedIds(bridgeName , ChannelUidBuffer , thisConv)) if (createChannel(bridgeName)) addResp(thisConv , bridgeName) ; else addFailResp(thisConv) ; else addReservedResp(thisConv) ; @@ -403,8 +458,28 @@ DBGcmd(command , args[0]) ; PurpleCmdRet handleEnableCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { + gboolean shouldEnable ; char* bridgeName ; Bridge* aBridge ; + DBGcmd(command , args[0]) ; + shouldEnable = !strcmp(command , ENABLE_CMD) ; bridgeName = args[0] ; + if (!getNBridges()) enableNoneResp(thisConv , "") ; + else if (isBlank(bridgeName)) + { + aBridge = SentinelBridge ; enableAllResp(thisConv , shouldEnable) ; + while ((aBridge = aBridge->next)) + { + enableBridge(aBridge , shouldEnable) ; + enableResp(thisConv , aBridge->name , shouldEnable) ; + } + } + else if (doesBridgeExist(aBridge = getBridgeByName(bridgeName))) + { + enableBridge(aBridge , shouldEnable) ; + enableResp(thisConv , aBridge->name , shouldEnable) ; + } + else enableNoneResp(thisConv , bridgeName) ; + return PURPLE_CMD_RET_OK ; } @@ -486,32 +561,22 @@ void removeResp(PurpleConversation* thisConv , char* thisBridgeName) } void removeUnbridgedResp(PurpleConversation* thisConv) - { chatBufferInit() ; channelStateMsg(thisConv) ; chatBufferDump(thisConv) ; } - -/* TODO: the remaining admin commands and responses -function removeResp($bridgeName) -{ - global $CHANNEL_REMOVED_MSG , $BRIDGE_REMOVED_MSG ; $resp = $CHANNEL_REMOVED_MSG ; - - if (array_key_exists($bridgeName , $Bridges)) $resp .= bridgeStatsMsg($bridgeName) ; - else $resp .= $BRIDGE_REMOVED_MSG ; - return $resp ; -} + { channelStateMsg(thisConv) ; chatBufferDump(thisConv) ; } -function removeUnbridgedResp($accountId , $channelId) - { return channelStateMsg($accountId , $channelId) ; } +void enableNoneResp(PurpleConversation* thisConv , char* bridgeName) + { bridgeStatsMsg(bridgeName) ; chatBufferDump(thisConv) ; } -function enableNoneResp($bridgeName) { return bridgeStatsMsg($bridgeName) ; } +void enableAllResp(PurpleConversation* thisConv , gboolean shouldEnable) + { chatBufferPutS("%s" , ((shouldEnable)? ENABLING_ALL_MSG : DISABLING_ALL_MSG)) ; } -function enableAllResp($isEnable) +void enableResp(PurpleConversation* thisConv , char* bridgeName , gboolean shouldEnable) { - global $ENABLING_ALL_MSG , $DISABLING_ALL_MSG ; - return ($isEnable)? $ENABLING_ALL_MSG : $DISABLING_ALL_MSG ; + char* enabledMsg = ((shouldEnable)? ENABLED_MSG : DISABLED_MSG) ; + chatBufferPutSSS("%s '%s' %s" , ENABLE_MSG , bridgeName , enabledMsg) ; + chatBufferDump(thisConv) ; } -function enableResp($bridgeName , $enabledMsg) - { global $ENABLE_MSG ; return "$ENABLE_MSG '$bridgeName' $enabledMsg" ; } - +/* TODO: the remaining admin commands and responses function echoResp($nick , $msg) { global $NICK_PREFIX ; return chatOut($NICK_PREFIX , $nick , $msg) ; } @@ -546,10 +611,12 @@ void statusResp(PurpleConversation* thisConv , char* bridgeName) { Bridge* aBridge ; unsigned int nBridges = getNBridges() ; -DBGs("statusResp() bridgeName=" , (!nBridges)? "no bridges" : ((!isBlank(bridgeName))? bridgeName : "unspecified - listing all")) ; +#ifdef DEBUG_VB +if (!nBridges) DBGs("statusResp() no bridges") ; else if (isBlank(bridgeName)) DBGs("statusResp() bridge unspecified - listing all") ; else DBGs("statusResp() bridgeName='" , bridgeName , "'" , "") ; +#endif - if (!nBridges) { chatBufferInit() ; bridgeStatsMsg("") ; } - else if (!isBlank(bridgeName)) { chatBufferInit() ; bridgeStatsMsg(bridgeName) ; } + if (!nBridges) bridgeStatsMsg("") ; + else if (!isBlank(bridgeName)) bridgeStatsMsg(bridgeName) ; else { chatBufferPutSDS("%s %d %s" , STATS_MSGa , getNBridges() , STATS_MSGb) ; @@ -563,12 +630,13 @@ DBGs("statusResp() bridgeName=" , (!nBridges)? "no bridges" : ((!isBlank(bridgeN void channelStateMsg(PurpleConversation* thisConv) { -// NOTE: callers of channelStateMsg() should first initialize ChatBuffer -// then eventually call chatBufferDump() to flush to screen +// NOTE: callers of channelStateMsg() should eventually call chatBufferDump() Bridge* aBridge ; -DBGs("channelStateMsg() channelName=" , getChannelName(thisConv)) ; +#ifdef DEBUG_VB +DBGss("channelStateMsg() channelName='" , getChannelName(thisConv) , "'" , "") ; +#endif chatBufferCatSS(THIS_CHANNEL_MSG , " ") ; if (doesBridgeExist(aBridge = getBridgeByChannel(thisConv))) @@ -578,16 +646,13 @@ DBGs("channelStateMsg() channelName=" , getChannelName(thisConv)) ; void bridgeStatsMsg(const char* bridgeName) { -// NOTE: callers of bridgeStatsMsg() should first initialize ChatBuffer -// then eventually call chatBufferDump() to flush to screen +// NOTE: callers of bridgeStatsMsg() should eventually call chatBufferDump() Bridge* aBridge ; Channel* aChannel ; unsigned int nChannels ; GList* activeChannelsIter = NULL ; gboolean isActive = FALSE ; char* activeMsg ; char* protocol ; char* username ; const char* channelName ; char* network ; char nick[UID_BUFFER_SIZE] ; -DBG("bridgeStatsMsg()") ; - chatBufferCat("\n\n") ; if (!doesBridgeExist(aBridge = getBridgeByName(bridgeName))) { @@ -614,8 +679,10 @@ DBG("bridgeStatsMsg()") ; activeChannelsIter = g_list_first(purple_get_conversations()) ; while (activeChannelsIter) { +#ifdef DEBUG_VB if (aBridge == SentinelBridge->next && aChannel == aBridge->sentinelChannel->next) -DBGs("bridgeStatsMsg() got active channelName=" , getChannelName((PurpleConversation*)activeChannelsIter->data)) ; + DBGss("bridgeStatsMsg() got active channelName='" , getChannelName((PurpleConversation*)activeChannelsIter->data) , "'" , "") ; +#endif prepareChannelUid((PurpleConversation*)activeChannelsIter->data) ; isActive |= !strcmp(aChannel->uid , ChannelUidBuffer) ; @@ -623,7 +690,9 @@ DBGs("bridgeStatsMsg() got active channelName=" , getChannelName((PurpleConversa } activeMsg = (isActive)? CH_ACTIVE_MSG : CH_INACTIVE_MSG ; -DBGss("bridgeStatsMsg() aChannel=" , aChannel->uid , " " , activeMsg) ; +#ifdef DEBUG_VB +DBGss("bridgeStatsMsg() aChannel='" , aChannel->uid , "' " , activeMsg) ; +#endif // parse channel data from channelUid channelUidBufferPutS("%s" , aChannel->uid) ; @@ -632,10 +701,12 @@ DBGss("bridgeStatsMsg() aChannel=" , aChannel->uid , " " , activeMsg) ; !(channelName = strtok(NULL , UID_DELIMITER))) continue ; +#ifdef DEBUG_VB DBGsssss("bridgeStatsMsg() parsed channelId " , activeMsg , " protocol='" , protocol , "' username='" , username , "' channelName='" , channelName , "'" , "") ; +#endif // display channel data - chatBufferCatSSSSSS("\n " , activeMsg , "'" , channelName , "' on '" , protocol) ; + chatBufferCatSSSSSS("\n " , activeMsg , " '" , channelName , "' on '" , protocol) ; if (!strcmp(protocol , IRC_PROTOCOL) && (network = strchr(username , '@')) && (strncpy(nick , username , network - username))) @@ -658,7 +729,7 @@ void channelUidBufferPutS(const char* fmt , const char* s1) void channelUidBufferPutD(const char* fmt , int d1) { snprintf(ChannelUidBuffer , UID_BUFFER_SIZE , fmt , d1) ; } -void chatBufferInit() { ChatBuffer[0] = '\0' ; } +void chatBufferClear() { ChatBuffer[0] = '\0' ; } void chatBufferPutS( const char* fmt , const char* s1) { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1) ; } @@ -701,10 +772,13 @@ void chatBufferCatSSSSSS(const char* s1 , const char* s2 , const char* s3 , void chatBufferDump(PurpleConversation* thisConv) { -DBGs("chatBufferDump() ChatBuffer = -->\n" , ChatBuffer) ; +#ifdef DEBUG_CHAT +DBGs("chatBufferDump() ChatBuffer=\n" , ChatBuffer) ; +#endif purple_conversation_write(thisConv , BRIDGIN_NICK , ChatBuffer , PURPLE_MESSAGE_SYSTEM , time(0)) ; + chatBufferClear() ; } diff --git a/bridgin.dbg.h b/bridgin.dbg.h index 1872cda..30b9c32 100644 --- a/bridgin.dbg.h +++ b/bridgin.dbg.h @@ -1,3 +1,7 @@ +#define DEBUG +//#define DEBUG_VB +#define DEBUG_CHAT + #include "debug.h" @@ -9,12 +13,12 @@ static void DBGs(const char* s1 , const char* s2) { if (isBlank(s1)) return ; pu //static void DBGd(const char* s1 , int d1) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%d\n" , s1 , d1) ; } static void DBGss(const char* s1 , const char* s2 , const char* s3 , const char* s4) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s\n" , s1 , s2 , s3 , s4) ; } - +#ifdef DEBUG_VB static void DBGsd(const char* s1 , const char* s2 , const char* s3 , int d1) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%d\n" , s1 , s2 , s3 , d1) ; } - +#endif //static void DBGdd(const char* s1 , int d1 , const char* s2 , int d2) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%d%s%d\n" , s1 , d1 , s2 , d2) ; } -//static void DBGsss(const char* s1 , const char* s2 , const char* s3 , const char* s4 , const char* s5 , const char* s6) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s%s%s\n" , s1 , s2 , s3 , s4 , s5 , s6) ; } +static void DBGsss(const char* s1 , const char* s2 , const char* s3 , const char* s4 , const char* s5 , const char* s6) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s%s%s\n" , s1 , s2 , s3 , s4 , s5 , s6) ; } //static void DBGsdd(const char* s1 , const char* s2 , const char* s3 , int d1 , const char* s4 , int d2) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%d%s%d\n" , s1 , s2 , s3 , d1 , s4 , d2) ; } @@ -25,15 +29,20 @@ static void DBGsd(const char* s1 , const char* s2 , const char* s3 , int d1) { i //static void DBGsssd(const char* s1 , const char* s2 , const char* s3 , const char* s4 , const char* s5 , const char* s6 , const char* s7 , int d1) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s%s%s%s%d\n" , s1 , s2 , s3 , s4 , s5 , s6 , s7 , d1) ; } //static void DBGsdsd(const char* s1 , const char* s2 , const char* s3 , int d1 , const char* s4 , const char* s5 , const char* s6 , int d2) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%d%s%s%s%d\n" , s1 , s2 , s3 , d1 , s4 , s5 , s6 , d2) ; } - +#ifdef DEBUG_VB static void DBGsssss(const char* s1 , const char* s2 , const char* s3 , const char* s4 , const char* s5 , const char* s6 , const char* s7 , const char* s8 , const char* s9 , const char* s10) { if (isBlank(s1)) return ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s%s%s%s%s%s%s\n" , s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8 , s9 , s10) ; } +#endif + static void DBGcmd(const char* command , char* args) { purple_debug_misc(PLUGIN_NAME , "HandleCmd '/%s' args = %s\n" , command , args) ; } -static void DBGchat(char* convType , PurpleAccount* thisAccount , char* sender , + +static void DBGchat(PurpleAccount* thisAccount , char* sender , PurpleConversation* thisConv , char* msg , PurpleMessageFlags flags) { + char* convType = ((purple_conversation_get_type(thisConv) == PURPLE_CONV_TYPE_IM)? + RECEIVING_IM_SIGNAL : RECEIVING_CHAT_SIGNAL) ; Bridge* thisBridge = getBridgeByChannel(thisConv) ; const char* channelName = purple_conversation_get_name(thisConv) ; gboolean isLocal = (flags & PURPLE_MESSAGE_SEND) ; @@ -41,15 +50,27 @@ static void DBGchat(char* convType , PurpleAccount* thisAccount , char* sender , gboolean isUnbridged = (thisBridge == SentinelBridge) ; GList* activeChannelsIter = g_list_first(purple_get_conversations()) ; unsigned int nChannels = 0 ; PurpleConversation* aConv ; + char dbgBuffer[UID_BUFFER_SIZE] ; + + if (!strcmp(channelName , "NickServ") || !strcmp(channelName , "MemoServ")) + { + purple_debug_misc(PLUGIN_NAME , "%s from %s - dropping\n" , convType , channelName) ; + return ; + } + + if (isLocal && !strcmp(msg , ChatBuffer)) + { + DBGss(convType , " relay on channel '" , channelName , "' - ignoring") ; + return ; + } + while (activeChannelsIter) { aConv = (PurpleConversation*)activeChannelsIter->data ; - if (aConv != thisConv && getBridgeByChannel(aConv) == thisBridge) - ++nChannels ; - + if (aConv != thisConv && getBridgeByChannel(aConv) == thisBridge) ++nChannels ; activeChannelsIter = g_list_next(activeChannelsIter) ; } - snprintf(ChatBuffer , CHAT_BUFFER_SIZE , "%d %s" , nChannels , "channels") ; + snprintf(dbgBuffer , UID_BUFFER_SIZE , "%d %s" , nChannels , "channels") ; purple_debug_misc(PLUGIN_NAME , "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%d%s%s%s\n" , @@ -62,5 +83,5 @@ static void DBGchat(char* convType , PurpleAccount* thisAccount , char* sender , "\n" , ((isLocal)? "local message - dropping" : ((!isRemote)? "special message - dropping" : ((isUnbridged)? "unbridged - dropping" : "relaying to "))) , - ((isRemote && !isUnbridged)? ChatBuffer : "")) ; + ((isRemote && !isUnbridged)? dbgBuffer : "")) ; } @@ -27,6 +27,11 @@ #define NICK_PREFIX "(from" // dont use '<' - some clients will supress it as html #define NICK_POSTFIX ")" +// purple constants +#define RECEIVING_IM_SIGNAL "receiving-im-msg" +#define RECEIVING_CHAT_SIGNAL "receiving-chat-msg" +#define IRC_PROTOCOL "IRC" + // model constants #define BRIDGE_PREF_FMT "%s/%s" #define ENABLED_PREF_FMT "%s%s" @@ -38,11 +43,6 @@ #define UID_DELIMITER "::" #define CHANNEL_ID_FMT "%s"UID_DELIMITER"%s"UID_DELIMITER"%s" -// purple constants -#define RECEIVED_IM_SIGNAL "received-im-msg" -#define RECEIVED_CHAT_SIGNAL "received-chat-msg" -#define IRC_PROTOCOL "IRC" - // admin commands #define N_COMMANDS 13 #define BINARY_FMT "s" @@ -57,6 +57,7 @@ #define DISABLE_CMD "disable" #define DISABLEu_HELP "/DISABLE_CMD\ntemporarily disable all bridges" #define DISABLEb_HELP "/DISABLE_CMD 'a-bridge-name'\ntemporarily disable the bridge 'a-bridge-name'" +#define DISABLE_CB handleEnableCmd #define ENABLE_CMD "enable" #define ENABLEu_HELP "/ENABLE_CMD\nenable all bridges" #define ENABLEb_HELP "/ENABLE_CMD 'a-bridge-name'\nenable the bridge 'a-bridge-name'" @@ -87,6 +88,11 @@ #define RESERVED_NAME_MSG "invalid name - not adding" #define CHANNEL_REMOVED_MSG "channel removed from bridge" #define BRIDGE_REMOVED_MSG "bridge removed" +#define ENABLING_ALL_MSG "enabling all bridges" +#define DISABLING_ALL_MSG "disabling all bridges" +#define ENABLE_MSG "bridge" +#define ENABLED_MSG "is enabled" +#define DISABLED_MSG "is disabled" #define THIS_BRIDGE_MSG "is on bridge" #define UNBRIDGED_MSG "is not bridged" #define NO_SUCH_BRIDGE_MSG "no such bridge" @@ -148,26 +154,30 @@ const char* getUsername( PurpleAccount* anAccount) ; void alert( char* msg) ; // model helpers +Bridge* getBridgeByChannel(PurpleConversation* aConv) ; +Bridge* getBridgeByName( const char* bridgeName) ; +unsigned int getNBridges( void) ; +unsigned int getNChannels( Bridge* aBridge) ; gboolean doesBridgeExist( Bridge* aBridge) ; -gboolean areReservedIds( char* bridgeName , char* channelUid) ; +gboolean isServerChannel( PurpleConversation* aConv) ; +gboolean areReservedIds( char* bridgeName , char* channelUid , + PurpleConversation* aConv) ; void prepareBridgeKeys( char* bridgeName) ; void prepareChannelUid( PurpleConversation* aConv) ; -Bridge* newBridge( char* bridgeName , Bridge* prevBridge) ; +Bridge* newBridge( char* bridgeName , Bridge* prevBridge , + gboolean isEnabled) ; Channel* newChannel( Channel* prevChannel) ; gboolean createChannel( char* bridgeName) ; void destroyChannel( Bridge* aBridge , PurpleConversation* aConv) ; -Bridge* getBridgeByChannel(PurpleConversation* aConv) ; -Bridge* getBridgeByName( const char* bridgeName) ; -unsigned int getNBridges( void) ; -unsigned int getNChannels( Bridge* aBridge) ; +void enableBridge( Bridge* aBridge , gboolean isEnable) ; // event handlers void handlePluginInit( PurplePlugin* plugin) ; gboolean handlePluginLoaded( PurplePlugin* plugin) ; gboolean handlePluginUnloaded(PurplePlugin* plugin) ; -void handleChat( PurpleAccount* anAccount , char* sender , - char* buffer , PurpleConversation* aConv , - PurpleMessageFlags flags , void* data) ; +gboolean handleChat( PurpleAccount* anAccount , char** sender , + char** msg , PurpleConversation* aConv , + PurpleMessageFlags* flags , void* data) ; // admin command handlers */ PurpleCmdRet handleAddCmd( PurpleConversation* aConv , const gchar* cmd , @@ -189,8 +199,7 @@ PurpleCmdRet handleHelpCmd( PurpleConversation* aConv , const gchar* cmd , // admin command responses // NOTE: callers of channelStateMsg() or bridgeStatsMsg() -// should first initialize ChatBuffer using one of the text buffer helpers -// then eventually call chatBufferDump() to flush to screen +// should eventually call chatBufferDump() to flush to screen void chatBufferDump( PurpleConversation* aConv) ; void addResp( PurpleConversation* aConv , char* thisBridgeName) ; void addExistsResp( PurpleConversation* aConv , char* thisBridgeName) ; @@ -199,6 +208,10 @@ void addReservedResp( PurpleConversation* aConv) ; void addFailResp( PurpleConversation* aConv) ; void removeResp( PurpleConversation* thisConv , char* thisBridgeName) ; void removeUnbridgedResp(PurpleConversation* thisConv) ; +void enableNoneResp( PurpleConversation* thisConv , char* bridgeName) ; +void enableAllResp( PurpleConversation* thisConv , gboolean shouldEnable) ; +void enableResp( PurpleConversation* thisConv , char* bridgeName , + gboolean shouldEnable) ; void statusResp( PurpleConversation* aConv , char* bridgeName) ; void channelStateMsg( PurpleConversation* aConv) ; void bridgeStatsMsg( const char* bridgeName) ; @@ -207,7 +220,7 @@ void bridgeStatsMsg( const char* bridgeName) ; gboolean isBlank( const char* aCstring) ; void channelUidBufferPutS(const char* fmt , const char* s1) ; void channelUidBufferPutD(const char* fmt , int d1) ; -void chatBufferInit( void) ; +void chatBufferClear( void) ; void chatBufferPutS( const char* fmt , const char* s1) ; void chatBufferPutSS( const char* fmt , const char* s1 , const char* s2) ; void chatBufferPutSSS( const char* fmt , const char* s1 , const char* s2 , |