1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-27 18:46:38 +02:00
Files
unrealircd/src/api-isupport.c
T
Bram Matthys 7161f33311 Code cleanup: make src/*.c use the generic #include "unrealircd.h" file
(with only a few exceptions)
Now, we'll find out later if Windows still compiles, I guess ;)
2019-06-22 21:18:08 +02:00

329 lines
8.6 KiB
C

/************************************************************************
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/api-isupport.c
* (c) 2004 Dominick Meglio and the UnrealIRCd Team
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "unrealircd.h"
Isupport *Isupports; /* List of ISUPPORT (005) tokens */
#define MAXISUPPORTLINES 10
MODVAR char *IsupportStrings[MAXISUPPORTLINES+1];
void isupport_add_sorted(Isupport *is);
void make_isupportstrings(void);
/** Easier way to set a 005 name or name=value.
* @param name Name of the 005 token
* @param value Value of the 005 token (or NULL)
* @note The 'name' 005 token will be overwritten if it already exists.
* The 'value' may be NULL, in which case if there was a value
* it will be unset.
*/
void IsupportSet(Module *module, const char *name, const char *value)
{
Isupport *is = IsupportFind(name);
if (!is)
is = IsupportAdd(module, name, value);
IsupportSetValue(is, value);
}
/** Easy way to set a 005 name=value with printf style formatting.
* @param name Name of the 005 token
* @param pattern Value pattern for the 005 token (or NULL)
* @param ... Any variables needed for 'pattern'.
* @note The 'name' 005 token will be overwritten if it already exists.
* The 'pattern' may be NULL, in which case if there was a value
* it will be unset.
*/
void IsupportSetFmt(Module *module, const char *name, const char *pattern, ...)
{
const char *value = NULL;
char buf[256];
va_list vl;
if (pattern)
{
va_start(vl, pattern);
ircvsnprintf(buf, sizeof(buf), pattern, vl);
va_end(vl);
value = buf;
}
IsupportSet(module, name, value);
}
void IsupportDelByName(const char *name)
{
Isupport *is = IsupportFind(name);
if (is)
IsupportDel(is);
}
extern void set_isupport_extban(void);
extern void set_isupport_targmax(void);
/**
* Initializes the builtin isupport tokens.
*/
void isupport_init(void)
{
IsupportSet(NULL, "INVEX", NULL);
IsupportSet(NULL, "EXCEPTS", NULL);
#ifdef PREFIX_AQ
IsupportSet(NULL, "STATUSMSG", "~&@%+");
#else
IsupportSet(NULL, "STATUSMSG", "@%+");
#endif
IsupportSet(NULL, "ELIST", "MNUCT");
IsupportSet(NULL, "CASEMAPPING", "ascii");
IsupportSet(NULL, "NETWORK", ircnet005);
IsupportSetFmt(NULL, "CHANMODES",
CHPAR1 "%s," CHPAR2 "%s," CHPAR3 "%s," CHPAR4 "%s",
EXPAR1, EXPAR2, EXPAR3, EXPAR4);
IsupportSet(NULL, "PREFIX", CHPFIX);
IsupportSet(NULL, "CHANTYPES", "#");
IsupportSetFmt(NULL, "MODES", "%d", MAXMODEPARAMS);
IsupportSetFmt(NULL, "SILENCE", "%d", SILENCE_LIMIT);
if (WATCH_AWAY_NOTIFICATION)
IsupportSet(NULL, "WATCHOPTS", "A");
else
IsupportDelByName("WATCHOPTS");
IsupportSetFmt(NULL, "WATCH", "%d", MAXWATCH);
IsupportSet(NULL, "WALLCHOPS", NULL);
IsupportSetFmt(NULL, "AWAYLEN", "%d", iConf.away_length);
IsupportSetFmt(NULL, "KICKLEN", "%d", iConf.kick_length);
IsupportSetFmt(NULL, "TOPICLEN", "%d", iConf.topic_length);
IsupportSetFmt(NULL, "QUITLEN", "%d", iConf.quit_length);
IsupportSetFmt(NULL, "CHANNELLEN", "%d", CHANNELLEN);
IsupportSetFmt(NULL, "NICKLEN", "%d", iConf.nick_length);
IsupportSetFmt(NULL, "MAXNICKLEN", "%d", NICKLEN);
IsupportSetFmt(NULL, "MAXLIST", "b:%d,e:%d,I:%d", MAXBANS, MAXBANS, MAXBANS);
IsupportSetFmt(NULL, "CHANLIMIT", "#:%d", MAXCHANNELSPERUSER);
IsupportSetFmt(NULL, "MAXCHANNELS", "%d", MAXCHANNELSPERUSER);
IsupportSet(NULL, "HCN", NULL);
IsupportSet(NULL, "SAFELIST", NULL);
IsupportSet(NULL, "NAMESX", NULL);
if (UHNAMES_ENABLED)
IsupportSet(NULL, "UHNAMES", NULL);
else
IsupportDelByName("UHNAMES");
IsupportSet(NULL, "DEAF", "d");
set_isupport_extban(); /* EXTBAN=xyz */
set_isupport_targmax(); /* TARGMAX=... */
}
/**
* Sets or changes the value of an existing isupport token.
*
* @param isupport The pointer to the isupport handle.
* @param value The new value of the token (NULL indicates no value).
*/
void IsupportSetValue(Isupport *isupport, const char *value)
{
if (isupport->value)
free(isupport->value);
if (value)
isupport->value = strdup(value);
else
isupport->value = NULL;
make_isupportstrings();
}
/**
* Returns an isupport handle based on the given token name.
*
* @param token The isupport token to search for.
* @return Returns the handle to the isupport token if it was found,
* otherwise NULL is returned.
*/
Isupport *IsupportFind(const char *token)
{
Isupport *isupport;
for (isupport = Isupports; isupport; isupport = isupport->next)
{
if (!stricmp(token, isupport->token))
return isupport;
}
return NULL;
}
/**
* Adds a new isupport token.
*
* @param module The module which owns this token.
* @param token The name of the token to create.
* @param value The value of the token (NULL indicates no value).
* @return Returns the handle to the new token if successful, otherwise NULL.
* The module's error code contains specific information about the
* error.
*/
Isupport *IsupportAdd(Module *module, const char *token, const char *value)
{
Isupport *isupport;
const char *c;
if (IsupportFind(token))
{
if (module)
module->errorcode = MODERR_EXISTS;
return NULL;
}
/* draft-brocklesby-irc-isupport:
* token = a-zA-Z0-9 and 20 or less characters
* value = ASCII 0x21 - 0x7E
*/
for (c = token; c && *c; c++)
{
if (!isalnum(*c))
{
if (module)
module->errorcode = MODERR_INVALID;
return NULL;
}
}
if (!token || !*token || c-token > 20)
{
if (module)
module->errorcode = MODERR_INVALID;
return NULL;
}
for (c = value; c && *c; c++)
{
if (*c < '!' || *c > '~')
{
if (module)
module->errorcode = MODERR_INVALID;
return NULL;
}
}
isupport = MyMallocEx(sizeof(Isupport));
isupport->owner = module;
isupport->token = strdup(token);
if (value)
isupport->value = strdup(value);
isupport_add_sorted(isupport);
make_isupportstrings();
if (module)
{
ModuleObject *isupportobj = MyMallocEx(sizeof(ModuleObject));
isupportobj->object.isupport = isupport;
isupportobj->type = MOBJ_ISUPPORT;
AddListItem(isupportobj, module->objects);
module->errorcode = MODERR_NOERROR;
}
return isupport;
}
/**
* Removes the specified isupport token.
*
* @param isupport The token to remove.
*/
void IsupportDel(Isupport *isupport)
{
DelListItem(isupport, Isupports);
free(isupport->token);
if (isupport->value)
free(isupport->value);
free(isupport);
make_isupportstrings();
}
/**
* Builds isupport token strings.
* Respects both the 13 token limit and the 512 buffer limit.
*/
void make_isupportstrings(void)
{
int i;
#define ISUPPORTLEN BUFSIZE-HOSTLEN-NICKLEN-39
int bufsize = ISUPPORTLEN;
int tokcnt = 0, len = 0;
Isupport *isupport;
char tmp[ISUPPORTLEN];
/* Free any previous strings */
for (i = 0; IsupportStrings[i]; i++)
safefree(IsupportStrings[i]);
i = 0;
IsupportStrings[i] = MyMallocEx(bufsize+1);
for (isupport = Isupports; isupport; isupport = isupport->next)
{
if (isupport->value)
snprintf(tmp, sizeof(tmp), "%s=%s", isupport->token, isupport->value);
else
strlcpy(tmp, isupport->token, sizeof(tmp));
tokcnt++;
if ((strlen(IsupportStrings[i]) + strlen(tmp) + 1 >= ISUPPORTLEN) || (tokcnt == 13))
{
/* No room or max tokens reached: start a new buffer */
IsupportStrings[++i] = MyMallocEx(bufsize+1);
tokcnt = 1;
if (i == MAXISUPPORTLINES)
abort(); /* should never happen anyway */
}
if (*IsupportStrings[i])
strlcat(IsupportStrings[i], " ", ISUPPORTLEN);
strlcat(IsupportStrings[i], tmp, ISUPPORTLEN);
}
}
void isupport_add_sorted(Isupport *n)
{
Isupport *e;
if (!Isupports)
{
Isupports = n;
return;
}
for (e = Isupports; e; e = e->next)
{
if (strcmp(n->token, e->token) < 0)
{
/* Insert us before */
if (e->prev)
e->prev->next = n;
else
Isupports = n; /* new head */
n->prev = e->prev;
n->next = e;
e->prev = n;
return;
}
if (!e->next)
{
/* Append us at end */
e->next = n;
n->prev = e;
return;
}
}
}