summaryrefslogtreecommitdiff
path: root/functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'functions.c')
-rw-r--r--functions.c250
1 files changed, 249 insertions, 1 deletions
diff --git a/functions.c b/functions.c
index fe96e0a..3dd8045 100644
--- a/functions.c
+++ b/functions.c
@@ -179,6 +179,7 @@ void appendcrlf(char *string) {
}
// Remove leading colon ':' which is the starting character of a prefix in an IRC message
+// If no leading colon present, string is left unchanged
void stripprefix(char *string) {
// Make a copy to work with
char string2[strlen(string)];
@@ -643,8 +644,11 @@ int createchannel(struct channel *channels, char *name, char *topic, char *topic
strncpy(channels[i].topicwhen, topicwhen, strlen(topicwhen));
channels[i].topicwhen[strlen(topicwhen)] = '\0';
channels[i].gotnames = 0;
+ // Set nicks to blank
+ for (int j = 0; j < MAXCHANNICKS; j++) {
+ channels[i].nicks[j][0] = '\0';
+ }
return 1;
- break; // TODO - This should be safe to remove since return is hit first
}
}
@@ -714,6 +718,10 @@ int removechannel(struct channel *channels, char *name) {
if (strncmp(channels[i].name, name, strlen(name)) == 0) {
// ..and NULL its name (0th character = '\0')
channels[i].name[0] = '\0';
+ // Set nicks to blank
+ for (int j = 0; j < MAXCHANNICKS; j++) {
+ channels[i].nicks[j][0] = '\0';
+ }
debugprint(DEBUG_FULL, "removechannel(): channel '%s' removed and topicwhen set to '%s'.\n", name, channels[i].topicwhen);
return 1;
}
@@ -1319,3 +1327,243 @@ void replacechar(char *str, char find, char replace) {
}
}
}
+
+// Add nick (passed as a :nick!user@host) to channel 'channel'
+// Returns 1 on success or 0 on failure
+int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels) {
+ debugprint(DEBUG_FULL, "addnicktochannel(): given '%s' and '%s'.\n", nickuserhost, channel);
+
+ // Get the nick from the prefix
+ extractnickfromprefix(nickuserhost);
+
+ // Make sure the channel exists
+ int chanfound = 0;
+ int chanindex;
+ for (chanindex = 0; chanindex < MAXCHANNELS; chanindex++) {
+ if (strlen(channels[chanindex].name) == strlen(channel) && !strcmp(channels[chanindex].name, channel)) {
+ chanfound = 1;
+ break;
+ }
+ }
+ if (!chanfound) {
+ debugprint(DEBUG_CRIT, "addnicktochannel(): channel '%s' not found in channel struct.\n", channel);
+ return 0;
+ }
+
+ // Add the nick to the channel
+ for (int i = 0; i < MAXCHANNICKS; i++) {
+ // Make sure the nick isn't already in the channel struct
+ if (strlen(channels[chanindex].nicks[i]) == strlen(nickuserhost) && !strcmp(channels[chanindex].nicks[i], nickuserhost)) {
+ // Unexectedly the nick is already here, hopefully it's OK so let's return 1
+ debugprint(DEBUG_FULL, "addnicktochannel(): nick '%s' already in channel '%s', returning.\n", nickuserhost, channel);
+ return 1;
+ }
+
+ // Find the first unoccupied slot and put the nick in
+ if (!channels[chanindex].nicks[i][0]) {
+ strcpy(channels[chanindex].nicks[i], nickuserhost);
+ debugprint(DEBUG_FULL, "addnicktochannel(): added nick '%s' to channel '%s'.\n", nickuserhost, channel);
+ return 1;
+ }
+ }
+
+ // We shouldn't get here, return error
+ debugprint(DEBUG_CRIT, "addnicktochannel(): got to the end of the function without adding nick '%s' to channel '%s', returning error.\n",
+ nickuserhost, channel);
+ return 0;
+}
+
+// Remove nick (passed as a :nick!user@host) from channel 'channel'
+// Returns 1 on success or 0 on failure
+int removenickfromchannel(char *nickuserhost, char *channel, struct channel *channels) {
+ debugprint(DEBUG_FULL, "removenickfromchannel(): given '%s' and '%s'.\n", nickuserhost, channel);
+
+ // Get the username from the prefix
+ extractnickfromprefix(nickuserhost);
+
+ // Make sure the channel exists
+ int chanfound = 0;
+ int chanindex;
+ for (chanindex = 0; chanindex < MAXCHANNELS; chanindex++) {
+ if (strlen(channels[chanindex].name) == strlen(channel) && !strcmp(channels[chanindex].name, channel)) {
+ chanfound = 1;
+ break;
+ }
+ }
+ if (!chanfound) {
+ debugprint(DEBUG_CRIT, "removenickfromchannel(): channel '%s' not found in channel struct.\n", channel);
+ return 0;
+ }
+
+ // Remove the nick from the channel
+ for (int i = 0; i < MAXCHANNICKS; i++) {
+ // Remove the the nick
+ if (strlen(channels[chanindex].nicks[i]) == strlen(nickuserhost) && !strcmp(channels[chanindex].nicks[i], nickuserhost)) {
+ // By null terminating its string
+ debugprint(DEBUG_FULL, "removenickfromchannel(): nick '%s' removed from channel '%s'.\n", nickuserhost, channel);
+ channels[chanindex].nicks[i][0] = '\0';
+ return 1;
+ }
+ }
+
+ // We shouldn't get here, return error
+ debugprint(DEBUG_CRIT, "removenickfromchannel(): got to the end of the function without removing nick '%s' from channel '%s', returning error.\n",
+ nickuserhost, channel);
+ return 0;
+}
+
+// Remove nick (passed as a :nick!user@host) from all channels
+// Returns 1 on success or 0 on failure
+int removenickfromallchannels(char *nickuserhost, struct channel *channels) {
+ debugprint(DEBUG_FULL, "removenickfromallchannels(): given '%s'.\n", nickuserhost);
+
+ // Get the nick from the prefix
+ extractnickfromprefix(nickuserhost);
+
+ // Go through all channels and remove nick if present
+ for (int i = 0; i < MAXCHANNELS; i++) {
+ // Go through all nicks in channel
+ for (int j = 0; j < MAXCHANNICKS; j++) {
+ // Remove the nick from the channel if present
+ if (strlen(channels[i].nicks[j]) == strlen(nickuserhost) && !strcmp(channels[i].nicks[j], nickuserhost)) {
+ // By null terminating its string
+ channels[i].nicks[j][0] = '\0';
+ debugprint(DEBUG_FULL, "removenickfromallchannels(): nick '%s' removed from channel '%s'.\n", nickuserhost, channels[i].name);
+ }
+ }
+ }
+
+ return 1;
+}
+
+// Update old nick (passed as a :nick!user@host) to 'newnick' in all channels
+// Returns 1 on success or 0 on failure
+int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *channels) {
+ debugprint(DEBUG_FULL, "updatenickinallchannels(): given '%s' and '%s'.\n", nickuserhost, newnick);
+
+ // Get the nick from the prefix
+ extractnickfromprefix(nickuserhost);
+
+ // Strip prefix from newnick
+ stripprefix(newnick);
+
+ // Go through all channels and update nick if present
+ for (int i = 0; i < MAXCHANNELS; i++) {
+ // Go through all nicks in channel
+ for (int j = 0; j < MAXCHANNICKS; j++) {
+ // Update the nick in the channel if present
+ if (strlen(channels[i].nicks[j]) == strlen(nickuserhost) && !strcmp(channels[i].nicks[j], nickuserhost)) {
+ strcpy(channels[i].nicks[j], newnick);
+ debugprint(DEBUG_FULL, "updatenickinallchannels(): nick '%s' updated to '%s' in channel '%s'.\n", nickuserhost, newnick, channels[i].name);
+ }
+ }
+ }
+
+ return 1;
+}
+
+// Populate our channels struct with all nicks in a RPL_NAMREPLY
+// Returns 1 on success or 0 on failure
+int addnamereplytochannel(char *namereply, struct channel *channels) {
+//:irc.tghost.co.uk 353 blabounce = #blabouncer :blabounce bbnick ~@l_bratch @l_blabnc Hughbla Bratchbot ars
+ debugprint(DEBUG_FULL, "addnamereplytochannel(): given '%s'.\n", namereply);
+
+ // Make a copy since we don't need to modify the original
+ char strcopy[MAXDATASIZE];
+ strcpy(strcopy, namereply);
+
+ // Strip the leading ':'
+ stripprefix(strcopy);
+
+ // Find the start of the channel name, which comes after the first '=' followed by a space
+ int channelpos = -1;
+ for (size_t i = 0; i < strlen(strcopy) - 2; i++) {
+ if (strcopy[i] == '=' && strcopy[i + 1] == ' ' && strcopy[i + 2] != '\0') {
+ // Name found
+ channelpos = i + 2;
+ break;
+ }
+ }
+ if (channelpos == -1) {
+ // Didn't find the name, abort
+ debugprint(DEBUG_FULL, "addnamereplytochannel(): couldn't find start of channel name in '%s'.\n", namereply);
+ return 0;
+ }
+
+ // Find the end of the channel name
+ char channelname[MAXCHANLENGTH];
+ for (size_t i = channelpos; i < strlen(strcopy); i++) {
+ // Stop when a space is found or if we're going to exceed MAXCHANLENGTH
+ if (strcopy[i] == ' ' || i - channelpos == MAXCHANLENGTH - 2) {
+ break;
+ }
+ channelname[i - channelpos] = strcopy[i];
+ channelname[i - channelpos + 1] = '\0';
+ }
+
+ // Start with a nice clean string that just consists of nicks at the end of the string
+ char nickstr[MAXDATASIZE];
+ strcpy(nickstr, strcopy + channelpos + strlen(channelname) + 1);
+
+ // Split nickstr up into its space-separated nick components
+
+ // Copy to a temporary string for feeding to strsep
+ char *nickcopy = strdup(nickstr);
+ // Keep track of initial pointer for free()ing later
+ char *nickcopyPtr = nickcopy;
+
+ // Track which CLRF-separated nick we're on
+ int nickcount = 0;
+ // Build array of each space-separated token
+ char nicks[MAXTOKENS][MAXDATASIZE];
+ // Split the string by ' ' and add each space-separated nick to an array
+ char *token;
+ while ((token = strsep(&nickcopy, " ")) != NULL) {
+ if (*token == '\0') continue; // Skip consecutive matches
+ if (nickcount >= MAXTOKENS) break; // Too many tokens
+ debugprint(DEBUG_FULL, "addnamereplytochannel(): Token: '%s', length '%ld'.\n", token, strlen(token));
+ // Make sure it's not too long
+ if (strlen(token) > MAXNICKLENGTH - 1) {
+ debugprint(DEBUG_CRIT, "addnamereplytochannel(): nick too long, discarding.\n");
+ continue;
+ }
+ // Copy into the token array (strlen + 1 to get the NULL terminator)
+ strncpy(nicks[nickcount], token, strlen(token) + 1);
+ nickcount++;
+ }
+
+ free(nickcopyPtr);
+
+ // Clean up each nick (remove prefixes and such)
+ for (int i = 0; i < nickcount; i++) {
+ stripprefixesfromnick(nicks[i]);
+ // And add to the channel
+ addnicktochannel(nicks[i], channelname, channels);
+ }
+
+ return 1;
+}
+
+// Strips all leading prefixes (colons, user modes) from a nick
+void stripprefixesfromnick(char *nick) {
+ debugprint(DEBUG_FULL, "stripprefixesfromnick(): given '%s'.\n", nick);
+
+ char nicktmp[MAXNICKLENGTH];
+ int pos = 0;
+
+ for (size_t i = 0; i < strlen(nick); i++) {
+ // Only copy non-prefix chars
+ if (nick[i] != ':' && nick[i] != '~' && nick[i] != '&' && nick[i] != '@' && nick[i] != '%' && nick[i] != '+') {
+ nicktmp[pos] = nick[i];
+ pos++;
+ }
+ }
+
+ // Null terminate
+ nicktmp[pos] = '\0';
+
+ debugprint(DEBUG_FULL, "stripprefixesfromnick(): produced '%s'.\n", nicktmp);
+
+ // Copy back to source string
+ strcpy(nick, nicktmp);
+}