diff options
author | bill auger <mr.j.spam.me@gmail.com> | 2013-09-21 02:57:38 -0400 |
---|---|---|
committer | bill auger <mr.j.spam.me@gmail.com> | 2013-09-21 02:57:38 -0400 |
commit | 69c1ac69f05479478cf849c367deefa63de457bc (patch) | |
tree | ac9ae54b42c691e668bff04e2628caff5772022e | |
parent | 4102a2b3112c7e5ed9e75dad836e1d0dd59f6c1b (diff) |
reimplement remove command
-rw-r--r-- | CHANGELOG | 6 | ||||
-rw-r--r-- | README.md | 14 | ||||
-rw-r--r-- | bridgin.c | 389 | ||||
-rw-r--r-- | bridgin.dbg.h | 13 | ||||
-rw-r--r-- | bridgin.h | 92 |
5 files changed, 287 insertions, 227 deletions
@@ -1,8 +1,12 @@ bridgin changelog -2013-09-18 - v0.5pre +2013-09-21 - v0.5pre CURRENT + reimplemented remove channel command and properly free heap resources + +2013-09-18 - v0.5pre + 4102a2b311 reimplemented persistence via purple preferences prefs.xml 2013-09-11 - v0.5pre @@ -14,10 +14,9 @@ some new functionalities this will allow: * better handling of special forms such as '/me' , smileys , etc ... * issuing admin commands in the standard form ('/add' instead of '?/add') * painfree installation and automatic loading with pidgin -* running on a nox box -* running on a windows box - - +* running on a nox box , windows , or mac + + ##build instructions for debian (ymmv) cd into your build dir and load the pidgin sources and build deps @@ -26,9 +25,10 @@ cd into your build dir and load the pidgin sources and build deps sudo apt-get build-dep pidgin cd into ./pidgin-x.x.x/ and build pidgin and finch -if you already have pidgin and/or finch installed -you can delete this build afterward -it is needed only to simplify building the bridgin plugin +you do not need to install this build +it is only used to simplify building the bridgin plugin +if you already have pidgin , finch , or adium installed +you can delete this entire directory after building the plugin cd ./pidgin* ./configure @@ -1,8 +1,3 @@ - - - - - #include "bridgin.h" #include "bridgin.dbg.h" @@ -28,123 +23,159 @@ PurpleAccount* getAccount(PurpleConversation* aConv) const char* getUsername(PurpleAccount* anAccount) { return purple_account_get_username(anAccount) ; } -const char* getNick(PurpleAccount* anAccount) - { return purple_account_get_name_for_display(anAccount) ; } - void alert(char* msg) { purple_notify_message(ThisPlugin , PURPLE_NOTIFY_MSG_INFO , msg , PLUGIN_VERSION , NULL , NULL , NULL) ; } -gboolean isBlank(const char* aCstring) { return (!aCstring || !*aCstring) ; } - /* model helpers */ +gboolean doesBridgeExist(Bridge* aBridge) { return (aBridge != SentinelBridge) ; } + gboolean areReservedIds(char* bridgeName , char* channelUid) { - return (!strcmp(bridgeName , SENTINEL_NAME) || + return (!strcmp(bridgeName , SENTINEL_NAME) || !strcmp(channelUid , SENTINEL_NAME)) ; } -Bridge* newBridge(char* bridgeName) +void prepareBridgeKeys(char* bridgeName) { - Bridge* aBridge ; Channel* aChannel ; - - aBridge = (Bridge*) malloc(sizeof(Bridge)) ; if (!aBridge) return NULL ; - aChannel = (Channel*)malloc(sizeof(Channel)) ; if (!aChannel) return NULL ; - - strcpy(aBridge->name , bridgeName) ; - aBridge->isEnabled = TRUE ; - aBridge->next = NULL ; - aBridge->sentinelChannel = aChannel ; + snprintf(BridgeKeyBuffer , UID_BUFFER_SIZE , BRIDGE_PREF_FMT , + BASE_PREF_KEY , bridgeName) ; + snprintf(EnabledKeyBuffer , UID_BUFFER_SIZE , ENABLED_PREF_FMT , + BridgeKeyBuffer , ENABLED_PREF_KEY) ; +} - strcpy(aChannel->uid , SENTINEL_NAME) ; - aChannel->next = NULL ; +void prepareChannelUid(PurpleConversation* aConv) +{ + PurpleAccount* anAccount ; + const char* protocol ; const char* username ; const char* channelName ; - return aBridge ; + anAccount = getAccount(aConv) ; protocol = getProtocol(anAccount) ; + username = getUsername(anAccount) ; channelName = getChannelName(aConv) ; + sprintf(ChannelUidBuffer , CHANNEL_ID_FMT , protocol , username , channelName) ; } -Channel* newChannel() +Bridge* newBridge(char* bridgeName , Bridge* prevBridge) { - Channel* aChannel = (Channel*)malloc(sizeof(Channel)) ; if (!aChannel) return NULL ; + Bridge* newBridge ; Channel* newChannel ; + + newBridge = (Bridge*) malloc(sizeof(Bridge)) ; if (!newBridge) return NULL ; + newChannel = (Channel*)malloc(sizeof(Channel)) ; if (!newChannel) return NULL ; - strcpy(aChannel->uid , UidBuffer) ; - aChannel->next = NULL ; + strcpy(newBridge->name , bridgeName) ; + newBridge->isEnabled = TRUE ; + newBridge->prev = prevBridge ; + newBridge->next = NULL ; + newBridge->sentinelChannel = newChannel ; - return aChannel ; + strcpy(newChannel->uid , SENTINEL_NAME) ; + newChannel->next = NULL ; + + return newBridge ; } -void makeChannelId(PurpleConversation* aConv) +Channel* newChannel(Channel* prevChannel) { - PurpleAccount* anAccount ; - const char* protocol ; const char* username ; const char* channelName ; + Channel* newChannel ; - anAccount = getAccount(aConv) ; protocol = getProtocol(anAccount) ; - username = getUsername(anAccount) ; channelName = getChannelName(aConv) ; - sprintf(UidBuffer , CHANNEL_ID_FMT , protocol , username , channelName) ; + newChannel = (Channel*)malloc(sizeof(Channel)) ; if (!newChannel) return NULL ; + + strcpy(newChannel->uid , ChannelUidBuffer) ; + newChannel->prev = prevChannel ; + newChannel->next = NULL ; + + return newChannel ; } -gboolean addChannel(char* bridgeName) +gboolean createChannel(char* bridgeName) { - Bridge* aBridge ; Channel* aChannel ; - char bridgePrefKey[UID_BUFFER_SIZE] ; char enabledPrefKey[UID_BUFFER_SIZE] ; - GList* channelsList = NULL ; + Bridge* aBridge ; Channel* aChannel ; GList* channelsList = NULL ; -DBGss("addChannel() bridgeName='" , bridgeName , "'" , "") ; - - // bridge pref key - snprintf(bridgePrefKey , UID_BUFFER_SIZE , BRIDGE_PREF_FMT , - BASE_PREF_KEY , bridgeName) ; - snprintf(enabledPrefKey , UID_BUFFER_SIZE , ENABLED_PREF_FMT , - bridgePrefKey , ENABLED_PREF_KEY) ; +DBGss("createChannel() bridgeName='" , bridgeName , "'" , "") ; + prepareBridgeKeys(bridgeName) ; if ((aBridge = getBridgeByName(bridgeName)) == SentinelBridge) { // create new bridge while (aBridge->next) aBridge = aBridge->next ; - aBridge->next = newBridge(bridgeName) ; + aBridge->next = newBridge(bridgeName , aBridge) ; if (!(aBridge = aBridge->next)) return FALSE ; // store bridge config - purple_prefs_add_bool(enabledPrefKey , TRUE) ; - purple_prefs_add_string_list(bridgePrefKey , channelsList) ; + purple_prefs_add_bool(EnabledKeyBuffer , TRUE) ; + purple_prefs_add_string_list(BridgeKeyBuffer , channelsList) ; -DBGs("addChannel() adding new bridgeKey=" , bridgePrefKey) ; +DBGs("createChannel() added new bridgeKey=" , BridgeKeyBuffer) ; } - else channelsList = purple_prefs_get_string_list(bridgePrefKey) ; + else channelsList = purple_prefs_get_string_list(BridgeKeyBuffer) ; // create new channel aChannel = aBridge->sentinelChannel ; while (aChannel->next) aChannel = aChannel->next ; - aChannel->next = newChannel() ; + aChannel->next = newChannel(aChannel) ; if (!aChannel->next) { g_list_free(channelsList) ; return FALSE ; } // store bridge config - channelsList = g_list_append(channelsList , (gpointer)UidBuffer) ; - purple_prefs_set_string_list(bridgePrefKey , channelsList) ; + channelsList = g_list_prepend(channelsList , (gpointer)ChannelUidBuffer) ; + purple_prefs_set_string_list(BridgeKeyBuffer , channelsList) ; -DBGs("addChannel() adding new channelUid=" , UidBuffer) ; +DBGs("createChannel() added new channelUid=" , ChannelUidBuffer) ; g_list_free(channelsList) ; return TRUE ; } +void destroyChannel(Bridge* aBridge , PurpleConversation* aConv) +{ + Channel* aChannel ; GList* channelsList = NULL ; GList* channelsIter = NULL ; + + // destroy channel struct + aChannel = aBridge->sentinelChannel ; prepareChannelUid(aConv) ; + while ((aChannel = aChannel->next)) + if (!strcmp(aChannel->uid , ChannelUidBuffer)) + { aChannel->prev->next = aChannel->next ; free(aChannel) ; } + + // store bridge config + prepareBridgeKeys(aBridge->name) ; + channelsList = purple_prefs_get_string_list(BridgeKeyBuffer) ; + channelsIter = g_list_first(channelsList) ; + while (channelsIter) + if (!strcmp(channelsIter->data , ChannelUidBuffer)) + { + channelsList = g_list_delete_link(channelsList , channelsIter) ; + channelsIter = g_list_first(channelsList) ; + } + else channelsIter = g_list_next(channelsIter) ; + purple_prefs_set_string_list(BridgeKeyBuffer , channelsList) ; + + // destroy empty bridge struct and preference keys + if (!g_list_length(channelsList)) + { + aBridge->prev->next = aBridge->next ; free(aBridge) ; + purple_prefs_remove(BridgeKeyBuffer) ; purple_prefs_remove(EnabledKeyBuffer) ; + } + + g_list_free(channelsList) ; g_list_free(channelsIter) ; +} + Bridge* getBridgeByChannel(PurpleConversation* aConv) { Bridge* aBridge ; Channel* aChannel ; -/*DBG*/makeChannelId(aConv);DBGss("getBridgeByChannel() channel='" , UidBuffer , "'" , "") ; +/*DBG*/prepareChannelUid(aConv);DBGss("getBridgeByChannel() channel='" , ChannelUidBuffer , "'" , "") ; - aBridge = SentinelBridge ; makeChannelId(aConv) ; + aBridge = SentinelBridge ; prepareChannelUid(aConv) ; while ((aBridge = aBridge->next)) { aChannel = aBridge->sentinelChannel ; while ((aChannel = aChannel->next)) - if (!strcmp(aChannel->uid , UidBuffer)) + if (!strcmp(aChannel->uid , ChannelUidBuffer)) return aBridge ; } -DBGss("getBridgeByChannel() '" , UidBuffer , "' not found" , "") ; + +DBGss("getBridgeByChannel() '" , ChannelUidBuffer , "' not found" , "") ; return SentinelBridge ; } @@ -179,7 +210,8 @@ unsigned int getNChannels(Bridge* aBridge) /* event handlers */ -void handlePluginInit(PurplePlugin* plugin) { purple_prefs_add_none(BASE_PREF_KEY) ; } +void handlePluginInit(PurplePlugin* aPlugin) + { ThisPlugin = aPlugin ; purple_prefs_add_none(BASE_PREF_KEY) ; } gboolean handlePluginLoaded(PurplePlugin* aPlugin) { @@ -190,7 +222,7 @@ gboolean handlePluginLoaded(PurplePlugin* aPlugin) DBG("handlePluginLoaded()") ; // init - ThisPlugin = aPlugin ; SentinelBridge = newBridge(SENTINEL_NAME) ; + SentinelBridge = newBridge(SENTINEL_NAME , NULL) ; if (!SentinelBridge) { alert(OOM_MSG) ; return FALSE ; } // register admin commands @@ -237,9 +269,10 @@ DBGs("handlePluginLoaded() found stored bridgeName=" , bridgeName) ; { DBGs("handlePluginLoaded() found stored channelUid=" , (char*)channelsIter->data) ; - strcpy(UidBuffer , (char*)channelsIter->data) ; - if (!addChannel(bridgeName)) + strcpy(ChannelUidBuffer , (char*)channelsIter->data) ; + if (!createChannel(bridgeName)) { + // malloc error - cleanup and bail g_list_free(channelsList) ; g_list_free(channelsIter) ; g_list_free(prefsList) ; g_list_free(prefsIter) ; alert(OOM_MSG) ; return FALSE ; @@ -261,9 +294,7 @@ DBGs("handlePluginLoaded() found stored channelUid=" , (char*)channelsIter->data gboolean handlePluginUnloaded(PurplePlugin* plugin) { - unsigned int i ; - Bridge* prevBridge ; Bridge* nextBridge ; - Channel* prevChannel ; Channel* nextChannel ; + unsigned int i ; Bridge* aBridge ; Channel* aChannel ; DBG("handlePluginUnloaded()") ; @@ -277,15 +308,14 @@ DBG("handlePluginUnloaded()") ; purple_signal_disconnect(purple_conversations_get_handle() , RECEIVED_CHAT_SIGNAL , ThisPlugin , PURPLE_CALLBACK(handleChat)) ; - prevBridge = SentinelBridge ; - while ((nextBridge = prevBridge->next)) + aBridge = SentinelBridge ; + while ((aBridge = aBridge->next)) { - prevChannel = nextBridge->sentinelChannel ; - while ((nextChannel = prevChannel->next)) - { free(prevChannel) ; prevChannel = nextChannel ; } - free(prevChannel) ; free(prevBridge) ; prevBridge = nextBridge ; + aChannel = aBridge->sentinelChannel ; + while ((aChannel = aChannel->next)) free(aChannel->prev) ; + free(aChannel) ; free(aBridge->prev) ; } - free(prevBridge) ; + free(aBridge) ; return TRUE ; } @@ -328,7 +358,7 @@ DBGs("handleChat() got active channelName=" , getChannelName((PurpleConversation /* admin command handlers */ -PurpleCmdRet handleAddCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleAddCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { char* bridgeName ; Bridge* thisBridge ; @@ -336,32 +366,41 @@ PurpleCmdRet handleAddCmd(PurpleConversation* aConv , const gchar* command , DBGcmd(command , args[0]) ; bridgeName = (isBlank(args[0]))? DEFAULT_BRIDGE_NAME : args[0] ; - if ((thisBridge = getBridgeByChannel(aConv)) != SentinelBridge) + if (doesBridgeExist(thisBridge = getBridgeByChannel(thisConv))) { - if (thisBridge == getBridgeByName(bridgeName)) addExistsResp(aConv , bridgeName) ; - else addConflictResp(aConv) ; + if (thisBridge != getBridgeByName(bridgeName)) addConflictResp(thisConv) ; + else addExistsResp(thisConv , bridgeName) ; } else { - makeChannelId(aConv) ; - if (!areReservedIds(bridgeName , UidBuffer)) - if (addChannel(bridgeName)) addResp(aConv , bridgeName) ; - else addFailResp(aConv) ; - else addReservedResp(aConv) ; + prepareChannelUid(thisConv) ; + if (!areReservedIds(bridgeName , ChannelUidBuffer)) + if (createChannel(bridgeName)) addResp(thisConv , bridgeName) ; + else addFailResp(thisConv) ; + else addReservedResp(thisConv) ; } return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleRemoveCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleRemoveCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { + Bridge* thisBridge ; char thisBridgeName[UID_BUFFER_SIZE] ; + DBGcmd(command , args[0]) ; + if (doesBridgeExist(thisBridge = getBridgeByChannel(thisConv))) + { + strncpy(thisBridgeName , thisBridge->name , UID_BUFFER_SIZE) ; + destroyChannel(thisBridge , thisConv) ; removeResp(thisConv , thisBridgeName) ; + } + else removeUnbridgedResp(thisConv) ; + return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleEnableCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleEnableCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; @@ -369,7 +408,7 @@ DBGcmd(command , args[0]) ; return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleEchoCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleEchoCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; @@ -377,7 +416,7 @@ DBGcmd(command , args[0]) ; return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleChatCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleChatCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; @@ -385,7 +424,7 @@ DBGcmd(command , args[0]) ; return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleBroadcastCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleBroadcastCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; @@ -393,15 +432,15 @@ DBGcmd(command , args[0]) ; return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleStatusCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleStatusCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; - statusResp(aConv , args[0]) ; return PURPLE_CMD_RET_OK ; + statusResp(thisConv , args[0]) ; return PURPLE_CMD_RET_OK ; } -PurpleCmdRet handleHelpCmd(PurpleConversation* aConv , const gchar* command , +PurpleCmdRet handleHelpCmd(PurpleConversation* thisConv , const gchar* command , gchar** args , gchar** error , void* data) { DBGcmd(command , args[0]) ; @@ -411,33 +450,44 @@ DBGcmd(command , args[0]) ; /* admin command responses */ -void addResp(PurpleConversation* aConv , char* bridgeName) +void addResp(PurpleConversation* thisConv , char* thisBridgeName) { - chatBufferPutSS("%s '%s'" , CH_SET_MSG , bridgeName) ; chatBufferDump(aConv) ; - chatBufferInit() ; bridgeStatsMsg(bridgeName) ; chatBufferDump(aConv) ; + chatBufferPutSS("%s '%s'" , CH_SET_MSG , thisBridgeName) ; + bridgeStatsMsg(thisBridgeName) ; chatBufferDump(thisConv) ; } -void addExistsResp(PurpleConversation* aConv , char* bridgeName) +void addExistsResp(PurpleConversation* thisConv , char* thisBridgeName) { - chatBufferPutSSS("%s %s '%s'" , THIS_CHANNEL_MSG , CHANNEL_EXISTS_MSG , bridgeName) ; - chatBufferDump(aConv) ; + chatBufferPutSSS("%s %s '%s'" , THIS_CHANNEL_MSG , CHANNEL_EXISTS_MSG , thisBridgeName) ; + chatBufferDump(thisConv) ; } -void addConflictResp(PurpleConversation* aConv) +void addConflictResp(PurpleConversation* thisConv) { - chatBufferPutS("%s" , BRIDGE_CONFLICT_MSG) ; chatBufferDump(aConv) ; + chatBufferPutS("%s" , BRIDGE_CONFLICT_MSG) ; chatBufferDump(thisConv) ; } -void addReservedResp(PurpleConversation* aConv) +void addReservedResp(PurpleConversation* thisConv) { - chatBufferPutS("%s" , RESERVED_NAME_MSG) ; chatBufferDump(aConv) ; + chatBufferPutS("%s" , RESERVED_NAME_MSG) ; chatBufferDump(thisConv) ; } -void addFailResp(PurpleConversation* aConv) +void addFailResp(PurpleConversation* thisConv) { - chatBufferPutS("%s" , OOM_MSG) ; chatBufferDump(aConv) ; + chatBufferPutS("%s" , OOM_MSG) ; chatBufferDump(thisConv) ; } +void removeResp(PurpleConversation* thisConv , char* thisBridgeName) +{ + chatBufferPutSS("%s '%s'" , CHANNEL_REMOVED_MSG , thisBridgeName) ; + if (doesBridgeExist(getBridgeByName(thisBridgeName))) bridgeStatsMsg(thisBridgeName) ; + else { chatBufferCatSSSS("\n'" , thisBridgeName , "' " , BRIDGE_REMOVED_MSG) ; } + chatBufferDump(thisConv) ; +} + +void removeUnbridgedResp(PurpleConversation* thisConv) + { chatBufferInit() ; channelStateMsg(thisConv) ; chatBufferDump(thisConv) ; } + /* TODO: the remaining admin commands and responses function removeResp($bridgeName) { @@ -492,7 +542,7 @@ function defaultResp() } */ -void statusResp(PurpleConversation* aConv , char* bridgeName) +void statusResp(PurpleConversation* thisConv , char* bridgeName) { Bridge* aBridge ; unsigned int nBridges = getNBridges() ; @@ -502,34 +552,28 @@ DBGs("statusResp() bridgeName=" , (!nBridges)? "no bridges" : ((!isBlank(bridgeN else if (!isBlank(bridgeName)) { chatBufferInit() ; bridgeStatsMsg(bridgeName) ; } else { - chatBufferPutSDS("%s %d %s\n\n" , STATS_MSGa , getNBridges() , STATS_MSGb) ; + chatBufferPutSDS("%s %d %s" , STATS_MSGa , getNBridges() , STATS_MSGb) ; aBridge = SentinelBridge ; while ((aBridge = aBridge->next)) bridgeStatsMsg(aBridge->name) ; } - if (nBridges) channelStateMsg(aConv) ; - chatBufferDump(aConv) ; + if (nBridges) { chatBufferCat("\n\n") ; channelStateMsg(thisConv) ; } + chatBufferDump(thisConv) ; } -void channelStateMsg(PurpleConversation* aConv) +void channelStateMsg(PurpleConversation* thisConv) { // NOTE: callers of channelStateMsg() should first initialize ChatBuffer // then eventually call chatBufferDump() to flush to screen Bridge* aBridge ; -DBGs("statusResp() channelName=" , getChannelName(aConv)) ; +DBGs("channelStateMsg() channelName=" , getChannelName(thisConv)) ; - if ((aBridge = getBridgeByChannel(aConv)) != SentinelBridge) - { - uidBufferPutSSS("%s %s '%s'" , THIS_CHANNEL_MSG , THIS_BRIDGE_MSG , aBridge->name) ; - chatBufferCat(UidBuffer) ; - } - else - { - uidBufferPutSS("%s %s" , THIS_CHANNEL_MSG , UNBRIDGED_MSG) ; - chatBufferCat(UidBuffer) ; - } + chatBufferCatSS(THIS_CHANNEL_MSG , " ") ; + if (doesBridgeExist(aBridge = getBridgeByChannel(thisConv))) + chatBufferCatSSSS(THIS_BRIDGE_MSG , " '" , aBridge->name , "'") ; + else chatBufferCat(UNBRIDGED_MSG) ; } void bridgeStatsMsg(const char* bridgeName) @@ -537,21 +581,21 @@ void bridgeStatsMsg(const char* bridgeName) // NOTE: callers of bridgeStatsMsg() should first initialize ChatBuffer // then eventually call chatBufferDump() to flush to screen - gboolean doesBridgeExist ; Bridge* aBridge ; Channel* aChannel ; - unsigned int nChannels ; + 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()") ; - aBridge = getBridgeByName(bridgeName) ; - doesBridgeExist = (aBridge != SentinelBridge) ; - if (!doesBridgeExist) - if (!getNBridges()) statusBufferPutS("%s" , NO_BRIDGES_MSG) ; - else statusBufferPutSS("%s '%s'" , NO_SUCH_BRIDGE_MSG , bridgeName) ; - else statusBufferPutSS("%s '%s' - " , STATS_MSGc , bridgeName) ; - chatBufferCat(StatusBuffer) ; if (!doesBridgeExist) return ; + chatBufferCat("\n\n") ; + if (!doesBridgeExist(aBridge = getBridgeByName(bridgeName))) + { + if (!getNBridges()) chatBufferCatSS(NO_BRIDGES_MSG , "\n") ; + else chatBufferCatSSSS(NO_SUCH_BRIDGE_MSG , " '" , bridgeName , "'\n") ; + return ; + } + else chatBufferCatSSSS(STATS_MSGc , " '" , bridgeName , "' - ") ; nChannels = getNChannels(aBridge) ; if (!nChannels) chatBufferCat(STATS_DELETED_MSG) ; @@ -559,8 +603,8 @@ DBG("bridgeStatsMsg()") ; { if (aBridge->isEnabled) chatBufferCat(STATS_ENABLED_MSG) ; else chatBufferCat(STATS_DISABLED_MSG) ; - statusBufferPutDS(" - %d %s\n" , nChannels , STATS_MSGd) ; - chatBufferCat(StatusBuffer) ; + channelUidBufferPutD("%d" , nChannels) ; + chatBufferCatSSSS(" - " , ChannelUidBuffer , " " , STATS_MSGd) ; } aChannel = aBridge->sentinelChannel ; @@ -573,8 +617,8 @@ DBG("bridgeStatsMsg()") ; if (aBridge == SentinelBridge->next && aChannel == aBridge->sentinelChannel->next) DBGs("bridgeStatsMsg() got active channelName=" , getChannelName((PurpleConversation*)activeChannelsIter->data)) ; - makeChannelId((PurpleConversation*)activeChannelsIter->data) ; - isActive |= !strcmp(aChannel->uid , UidBuffer) ; + prepareChannelUid((PurpleConversation*)activeChannelsIter->data) ; + isActive |= !strcmp(aChannel->uid , ChannelUidBuffer) ; activeChannelsIter = g_list_next(activeChannelsIter) ; } activeMsg = (isActive)? CH_ACTIVE_MSG : CH_INACTIVE_MSG ; @@ -582,8 +626,8 @@ DBGs("bridgeStatsMsg() got active channelName=" , getChannelName((PurpleConversa DBGss("bridgeStatsMsg() aChannel=" , aChannel->uid , " " , activeMsg) ; // parse channel data from channelUid - uidBufferPutS("%s" , aChannel->uid) ; - if (!(protocol = strtok(UidBuffer , UID_DELIMITER)) || + channelUidBufferPutS("%s" , aChannel->uid) ; + if (!(protocol = strtok(ChannelUidBuffer , UID_DELIMITER)) || !(username = strtok(NULL , UID_DELIMITER)) || !(channelName = strtok(NULL , UID_DELIMITER))) continue ; @@ -591,72 +635,75 @@ DBGss("bridgeStatsMsg() aChannel=" , aChannel->uid , " " , activeMsg) ; DBGsssss("bridgeStatsMsg() parsed channelId " , activeMsg , " protocol='" , protocol , "' username='" , username , "' channelName='" , channelName , "'" , "") ; // display channel data - statusBufferPutSSS(" %s '%s' on '%s" , activeMsg , channelName , protocol) ; - chatBufferCat(StatusBuffer) ; + chatBufferCatSSSSSS("\n " , activeMsg , "'" , channelName , "' on '" , protocol) ; if (!strcmp(protocol , IRC_PROTOCOL) && (network = strchr(username , '@')) && (strncpy(nick , username , network - username))) { nick[network - username] = '\0' ; - statusBufferPutSS("%s' as '%s'\n" , network , nick) ; + chatBufferCatSSSS(network , "' as '" , nick , "'") ; } - else statusBufferPutS("' as '%s'\n" , username) ; - chatBufferCat(StatusBuffer) ; + else chatBufferCatSSS("' as '" , username , "'") ; } // each aChannel - - chatBufferCat("\n") ; } /* text buffer helpers */ -void uidBufferPutS( const char* fmt , const char* s1) - { snprintf(UidBuffer , UID_BUFFER_SIZE , fmt , s1) ; } +gboolean isBlank(const char* aCstring) { return (!aCstring || !*aCstring) ; } + +void channelUidBufferPutS(const char* fmt , const char* s1) + { snprintf(ChannelUidBuffer , UID_BUFFER_SIZE , fmt , s1) ; } -void uidBufferPutSS( const char* fmt , const char* s1 , const char* s2) - { snprintf(UidBuffer , UID_BUFFER_SIZE , fmt , s1 , s2) ; } +void channelUidBufferPutD(const char* fmt , int d1) + { snprintf(ChannelUidBuffer , UID_BUFFER_SIZE , fmt , d1) ; } -void uidBufferPutSSS( const char* fmt , const char* s1 , const char* s2 , const char* s3) - { snprintf(UidBuffer , UID_BUFFER_SIZE , fmt , s1 , s2 , s3) ; } +void chatBufferInit() { ChatBuffer[0] = '\0' ; } -void statusBufferPutS( const char* fmt , const char* s1) - { snprintf(StatusBuffer , UID_BUFFER_SIZE , fmt , s1) ; } +void chatBufferPutS( const char* fmt , const char* s1) + { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1) ; } -void statusBufferPutSS( const char* fmt , const char* s1 , const char* s2) - { snprintf(StatusBuffer , UID_BUFFER_SIZE , fmt , s1 , s2) ; } +void chatBufferPutSS( const char* fmt , const char* s1 , const char* s2) + { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2) ; } -void statusBufferPutDS( const char* fmt , int d1 , const char* s1) - { snprintf(StatusBuffer , UID_BUFFER_SIZE , fmt , d1 , s1) ; } +void chatBufferPutSSS( const char* fmt , const char* s1 , const char* s2 , const char* s3) + { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2 , s3) ; } -void statusBufferPutSSS(const char* fmt , const char* s1 , const char* s2 , const char* s3) - { snprintf(StatusBuffer , UID_BUFFER_SIZE , fmt , s1 , s2 , s3) ; } +void chatBufferPutSDS( const char* fmt , const char* s1 , int d1 , const char* s2) + { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , d1 , s2) ; } -void chatBufferInit() { ChatBuffer[0] = '\0' ; } +void chatBufferPutSSSS(const char* fmt , const char* s1 , const char* s2 , + const char* s3 , const char* s4) + { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2 , s3 , s4) ; } -void chatBufferPutS( const char* fmt , const char* s1) - { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1) ; } +void chatBufferCat( const char* s) + { strncat(ChatBuffer , s , CHAT_BUFFER_SIZE - strlen(ChatBuffer) - 1) ; } -void chatBufferPutSS( const char* fmt , const char* s1 , const char* s2) - { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2) ; } +void chatBufferCatSS( const char* s1 , const char* s2) + { chatBufferCat(s1) ; chatBufferCat(s2) ; } -void chatBufferPutSSS( const char* fmt , const char* s1 , const char* s2 , const char* s3) - { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2 , s3) ; } +void chatBufferCatSSS( const char* s1 , const char* s2 , const char* s3) + { chatBufferCat(s1) ; chatBufferCat(s2) ; chatBufferCat(s3) ; } -void chatBufferPutSDS( const char* fmt , const char* s1 , int d1 , const char* s2) - { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , d1 , s2) ; } +void chatBufferCatSSSS( const char* s1 , const char* s2 , const char* s3 , + const char* s4) + { chatBufferCat(s1) ; chatBufferCat(s2) ; chatBufferCat(s3) ; chatBufferCat(s4) ; } -void chatBufferPutSSSS( const char* fmt , const char* s1 , const char* s2 , - const char* s3 , const char* s4) - { snprintf(ChatBuffer , CHAT_BUFFER_SIZE , fmt , s1 , s2 , s3 , s4) ; } +void chatBufferCatSSSSS( const char* s1 , const char* s2 , const char* s3 , + const char* s4 , const char* s5) + { chatBufferCat(s1) ; chatBufferCat(s2) ; chatBufferCat(s3) ; chatBufferCat(s4) ; + chatBufferCat(s5) ; } -void chatBufferCat( const char* aCstring) - { strncat(ChatBuffer , aCstring , CHAT_BUFFER_SIZE - strlen(ChatBuffer) - 1) ; } +void chatBufferCatSSSSSS(const char* s1 , const char* s2 , const char* s3 , + const char* s4 , const char* s5 , const char* s6) + { chatBufferCat(s1) ; chatBufferCat(s2) ; chatBufferCat(s3) ; chatBufferCat(s4) ; + chatBufferCat(s5) ; chatBufferCat(s6) ; } -void chatBufferDump(PurpleConversation* aConv) +void chatBufferDump(PurpleConversation* thisConv) { -DBGs("chatBufferDump() ChatBuffer\n=" , ChatBuffer) ; +DBGs("chatBufferDump() ChatBuffer = -->\n" , ChatBuffer) ; - purple_conversation_write(aConv , BRIDGIN_NICK , ChatBuffer , + purple_conversation_write(thisConv , BRIDGIN_NICK , ChatBuffer , PURPLE_MESSAGE_SYSTEM , time(0)) ; } diff --git a/bridgin.dbg.h b/bridgin.dbg.h index 9fb7901..1872cda 100644 --- a/bridgin.dbg.h +++ b/bridgin.dbg.h @@ -28,6 +28,9 @@ static void DBGsd(const char* s1 , const char* s2 , const char* s3 , int d1) { i 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) ; } +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 , PurpleConversation* thisConv , char* msg , PurpleMessageFlags flags) { @@ -46,7 +49,7 @@ static void DBGchat(char* convType , PurpleAccount* thisAccount , char* sender , activeChannelsIter = g_list_next(activeChannelsIter) ; } - statusBufferPutDS("%d %s" , nChannels , "channels") ; + snprintf(ChatBuffer , CHAT_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" , @@ -59,11 +62,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)? StatusBuffer : "")) ; + ((isRemote && !isUnbridged)? ChatBuffer : "")) ; } - -// static void DBGchannelClosed(PurpleConversation* thisConv) -// { purple_debug_misc(PLUGIN_NAME , "deleting-conversation (%s)\n" , purple_conversation_get_name(thisConv)) ; } - -static void DBGcmd(const char* command , char* args) - { purple_debug_misc(PLUGIN_NAME , "HandleCmd '/%s' args = %s\n" , command , args) ; } @@ -23,7 +23,7 @@ // app constants #define BRIDGIN_NICK "BRIDGIN" #define DEFAULT_BRIDGE_NAME "default" -#define CHAT_OUT_FMT "%s %s%s %s" +#define CHAT_OUT_FMT "%s %s%s %s" #define NICK_PREFIX "(from" // dont use '<' - some clients will supress it as html #define NICK_POSTFIX ")" @@ -51,7 +51,7 @@ #define ADDu_HELP "/ADD_CMD\nadd this channel to the default bridge" #define ADDb_HELP "/ADD_CMD 'a-bridge-name'\nadd this channel to the bridge 'a-bridge-name'" #define ADD_CB handleAddCmd -#define REMOVE_CMD "remove" +#define REMOVE_CMD "rem" #define REMOVE_HELP "/REMOVE_CMD\nunbridge this channel" #define REMOVE_CB handleRemoveCmd #define DISABLE_CMD "disable" @@ -85,6 +85,8 @@ #define CHANNEL_EXISTS_MSG "already exists on bridge" #define BRIDGE_CONFLICT_MSG "each channel may only be on one bridge" #define RESERVED_NAME_MSG "invalid name - not adding" +#define CHANNEL_REMOVED_MSG "channel removed from bridge" +#define BRIDGE_REMOVED_MSG "bridge removed" #define THIS_BRIDGE_MSG "is on bridge" #define UNBRIDGED_MSG "is not bridged" #define NO_SUCH_BRIDGE_MSG "no such bridge" @@ -114,6 +116,7 @@ typedef struct Channel { char uid[UID_BUFFER_SIZE] ; + struct Channel* prev ; struct Channel* next ; } Channel ; @@ -122,16 +125,18 @@ typedef struct Bridge char name[UID_BUFFER_SIZE] ; gboolean isEnabled ; Channel* sentinelChannel ; + struct Bridge* prev ; struct Bridge* next ; } Bridge ; -static PurplePluginInfo PluginInfo ; // init pre main() -static PurplePlugin* ThisPlugin ; // init handlePluginLoaded() -static PurpleCmdId CommandIds[N_COMMANDS] ; // init handlePluginLoaded() -static Bridge* SentinelBridge ; // init handlePluginInit() -static char UidBuffer[UID_BUFFER_SIZE] ; // volatile -static char StatusBuffer[UID_BUFFER_SIZE] ; // volatile -static char ChatBuffer[CHAT_BUFFER_SIZE] ; // volatile +static PurplePluginInfo PluginInfo ; // init pre main() +static PurplePlugin* ThisPlugin ; // init handlePluginLoaded() +static PurpleCmdId CommandIds[N_COMMANDS] ; // init handlePluginLoaded() +static Bridge* SentinelBridge ; // init handlePluginLoaded() +static char BridgeKeyBuffer[UID_BUFFER_SIZE] ; // volatile +static char EnabledKeyBuffer[UID_BUFFER_SIZE] ; // volatile +static char ChannelUidBuffer[UID_BUFFER_SIZE] ; // volatile +static char ChatBuffer[CHAT_BUFFER_SIZE] ; // volatile // purple helpers PurpleCmdId registerCmd( const char* command , const char* format , @@ -140,17 +145,17 @@ const char* getChannelName(PurpleConversation* aConv) ; const char* getProtocol( PurpleAccount* anAccount) ; PurpleAccount* getAccount( PurpleConversation* aConv) ; const char* getUsername( PurpleAccount* anAccount) ; -const char* getNick( PurpleAccount* anAccount) ; void alert( char* msg) ; -gboolean isBlank( const char* aCstring) ; // model helpers +gboolean doesBridgeExist( Bridge* aBridge) ; gboolean areReservedIds( char* bridgeName , char* channelUid) ; -gboolean isReservedId( char* aCstring) ; -Bridge* newBridge( char* bridgeName) ; -Channel* newChannel( void) ; -void makeChannelId( PurpleConversation* aConv) ; -gboolean addChannel( char* bridgeName) ; +void prepareBridgeKeys( char* bridgeName) ; +void prepareChannelUid( PurpleConversation* aConv) ; +Bridge* newBridge( char* bridgeName , Bridge* prevBridge) ; +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) ; @@ -186,29 +191,36 @@ PurpleCmdRet handleHelpCmd( PurpleConversation* aConv , const gchar* cmd , // 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 -void chatBufferDump( PurpleConversation* aConv) ; -void addResp( PurpleConversation* aConv , char* bridgeName) ; -void addExistsResp( PurpleConversation* aConv , char* bridgeName) ; -void addConflictResp(PurpleConversation* aConv) ; -void addReservedResp(PurpleConversation* aConv) ; -void addFailResp( PurpleConversation* aConv) ; -void statusResp( PurpleConversation* aConv , char* bridgeName) ; -void channelStateMsg(PurpleConversation* aConv) ; -void bridgeStatsMsg( const char* bridgeName) ; +void chatBufferDump( PurpleConversation* aConv) ; +void addResp( PurpleConversation* aConv , char* thisBridgeName) ; +void addExistsResp( PurpleConversation* aConv , char* thisBridgeName) ; +void addConflictResp( PurpleConversation* aConv) ; +void addReservedResp( PurpleConversation* aConv) ; +void addFailResp( PurpleConversation* aConv) ; +void removeResp( PurpleConversation* thisConv , char* thisBridgeName) ; +void removeUnbridgedResp(PurpleConversation* thisConv) ; +void statusResp( PurpleConversation* aConv , char* bridgeName) ; +void channelStateMsg( PurpleConversation* aConv) ; +void bridgeStatsMsg( const char* bridgeName) ; // text buffer helpers -void uidBufferPutS( const char* fmt , const char* s1) ; -void uidBufferPutSS( const char* fmt , const char* s1 , const char* s2) ; -void uidBufferPutSSS( const char* fmt , const char* s1 , const char* s2 , const char* s3) ; -void statusBufferPutS( const char* fmt , const char* s1) ; -void statusBufferPutSS( const char* fmt , const char* s1 , const char* s2) ; -void statusBufferPutDS( const char* fmt , int d1 , const char* s1) ; -void statusBufferPutSSS(const char* fmt , const char* s1 , const char* s2 , const char* s3) ; -void chatBufferInit( 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 , const char* s3) ; -void chatBufferPutSDS( const char* fmt , const char* s1 , int d1 , const char* s2) ; -void chatBufferPutSSSS( const char* fmt , const char* s1 , const char* s2 , - const char* s3 , const char* s4) ; -void chatBufferCat( const char* msg) ; +gboolean isBlank( const char* aCstring) ; +void channelUidBufferPutS(const char* fmt , const char* s1) ; +void channelUidBufferPutD(const char* fmt , int d1) ; +void chatBufferInit( 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 , + const char* s3) ; +void chatBufferPutSDS( const char* fmt , const char* s1 , int d1 , const char* s2) ; +void chatBufferPutSSSS( const char* fmt , const char* s1 , const char* s2 , + const char* s3 , const char* s4) ; +void chatBufferCat( const char* s) ; +void chatBufferCatSS( const char* s1 , const char* s2) ; +void chatBufferCatSSS( const char* s1 , const char* s2 , const char* s3) ; +void chatBufferCatSSSS( const char* s1 , const char* s2 , const char* s3 , + const char* s4) ; +void chatBufferCatSSSSS( const char* s1 , const char* s2 , const char* s3 , + const char* s4 , const char* s5) ; +void chatBufferCatSSSSSS( const char* s1 , const char* s2 , const char* s3 , + const char* s4 , const char* s5 , const char* s6) ; |