+void freeNeonSpamSettings(struct NeonSpamSettings *settings) {
+ struct NeonSpamJoinNode *joinnode, *nextjoinnode;
+ for(joinnode = settings->join_nodes; joinnode; joinnode = nextjoinnode) {
+ nextjoinnode = joinnode->next;
+ freeJoinNode(joinnode);
+ }
+ free(settings);
+}
+
+static void freeJoinNode(struct NeonSpamJoinNode *joinnode) {
+ free(joinnode->ident);
+ free(joinnode->host);
+ free(joinnode);
+}
+
+static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser) {
+ struct NeonSpamJoinNode *joinnode, *prevjoinnode = NULL, *nextjoinnode, *result = NULL;
+ for(joinnode = chanuser->chan->spam_settings->join_nodes; joinnode; joinnode = nextjoinnode) {
+ nextjoinnode = joinnode->next;
+ if(!stricmp(joinnode->ident, chanuser->user->ident) && !stricmp(joinnode->host, chanuser->user->host)) {
+ prevjoinnode = joinnode;
+ result = joinnode;
+ } else if(time(0) - joinnode->last_penalty_update > MAX_JOIN_TIME) {
+ freeJoinNode(joinnode);
+ if(prevjoinnode)
+ prevjoinnode->next = nextjoinnode;
+ else
+ chanuser->chan->spam_settings->join_nodes = nextjoinnode;
+ } else
+ prevjoinnode = joinnode;
+ }
+ if(result)
+ return result;
+ joinnode = malloc(sizeof(*joinnode));
+ if(!joinnode) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ joinnode->ident = strdup(chanuser->user->ident);
+ joinnode->host = strdup(chanuser->user->host);
+ joinnode->last_penalty_update = time(0);
+ joinnode->joinpenalty = 0;
+ joinnode->next = chanuser->chan->spam_settings->join_nodes;
+ chanuser->chan->spam_settings->join_nodes = joinnode;
+ return joinnode;
+}
+