summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbill auger <mr.j.spam.me@gmail.com>2013-09-21 02:57:38 -0400
committerbill auger <mr.j.spam.me@gmail.com>2013-09-21 02:57:38 -0400
commit69c1ac69f05479478cf849c367deefa63de457bc (patch)
treeac9ae54b42c691e668bff04e2628caff5772022e
parent4102a2b3112c7e5ed9e75dad836e1d0dd59f6c1b (diff)
reimplement remove command
-rw-r--r--CHANGELOG6
-rw-r--r--README.md14
-rw-r--r--bridgin.c389
-rw-r--r--bridgin.dbg.h13
-rw-r--r--bridgin.h92
5 files changed, 287 insertions, 227 deletions
diff --git a/CHANGELOG b/CHANGELOG
index ba2a178..97ac19d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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
diff --git a/README.md b/README.md
index 3391f60..5ec45df 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/bridgin.c b/bridgin.c
index 9b7bb33..a6b0d00 100644
--- a/bridgin.c
+++ b/bridgin.c
@@ -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) ; }
diff --git a/bridgin.h b/bridgin.h
index c1bf646..b553fd8 100644
--- a/bridgin.h
+++ b/bridgin.h
@@ -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) ;