1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-25 18:26:38 +02:00
Files
unrealircd/src/api-isupport.c
T
2015-07-12 16:30:08 +02:00

278 lines
7.5 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.
*
* $Id$
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "version.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>
#include "h.h"
#include "proto.h"
Isupport *Isupports; /* List of ISUPPORT (005) tokens */
#define MAXISUPPORTLINES 10
MODVAR char *IsupportStrings[MAXISUPPORTLINES+1];
extern char *cmdstr;
/**
* Builds isupport token strings.
* Respects both the 13 token limit and the 512 buffer limit.
*/
/* TODO: is all this code really safe? */
void make_isupportstrings(void)
{
int i;
int bufsize = BUFSIZE-HOSTLEN-NICKLEN-39;
int tokcnt = 0, len = 0;
Isupport *isupport;
/* Clear out the old junk */
for (i = 0; IsupportStrings[i]; i++)
{
safefree(IsupportStrings[i]);
}
i = 0;
IsupportStrings[i] = MyMallocEx(bufsize);
for (isupport = Isupports; isupport; isupport = isupport->next)
{
int toklen;
/* Just a token */
if (!isupport->value)
{
toklen = strlen(isupport->token);
if (tokcnt == 13 || bufsize < len+toklen+1)
{
tokcnt = 0;
len = 0;
IsupportStrings[++i] = MyMallocEx(bufsize);
}
if (IsupportStrings[i][0]) toklen++;
ircsnprintf(IsupportStrings[i]+len, bufsize-len, "%s%s", IsupportStrings[i][0]? " ": "", isupport->token);
len += toklen;
tokcnt++;
}
else
{
toklen = strlen(isupport->token)+strlen(isupport->value)+1;
if (tokcnt == 13 || bufsize < len+toklen+1) {
tokcnt = 0;
len = 0;
IsupportStrings[++i] = MyMallocEx(bufsize);
}
if (IsupportStrings[i][0]) toklen++;
ircsnprintf(IsupportStrings[i]+len, bufsize-len, "%s%s=%s", IsupportStrings[i][0]? " ": "", isupport->token, isupport->value);
len += toklen;
tokcnt++;
}
if (i == MAXISUPPORTLINES)
abort(); /* should never happen anyway */
}
}
/**
* Initializes the builtin isupport tokens.
*/
void isupport_init(void)
{
char tmpbuf[512];
int i;
for (i=0; i <= MAXISUPPORTLINES; i++)
IsupportStrings[i] = NULL;
IsupportAdd(NULL, "INVEX", NULL);
IsupportAdd(NULL, "EXCEPTS", NULL);
#ifdef PREFIX_AQ
IsupportAdd(NULL, "STATUSMSG", "~&@%+");
#else
IsupportAdd(NULL, "STATUSMSG", "@%+");
#endif
IsupportAdd(NULL, "ELIST", "MNUCT");
ircsnprintf(tmpbuf, sizeof(tmpbuf), "~,%s", extbanstr);
IsupportAdd(NULL, "EXTBAN", tmpbuf);
IsupportAdd(NULL, "CASEMAPPING", "ascii");
IsupportAdd(NULL, "NETWORK", ircnet005);
ircsnprintf(tmpbuf, sizeof(tmpbuf), CHPAR1 "%s," CHPAR2 "%s," CHPAR3 "%s," CHPAR4 "%s",
EXPAR1, EXPAR2, EXPAR3, EXPAR4);
IsupportAdd(NULL, "CHANMODES", tmpbuf);
IsupportAdd(NULL, "PREFIX", CHPFIX);
IsupportAdd(NULL, "CHANTYPES", "#");
IsupportAdd(NULL, "MODES", my_itoa(MAXMODEPARAMS));
IsupportAdd(NULL, "SILENCE", my_itoa(SILENCE_LIMIT));
if (WATCH_AWAY_NOTIFICATION)
IsupportAdd(NULL, "WATCHOPTS", "A");
IsupportAdd(NULL, "WATCH", my_itoa(MAXWATCH));
IsupportAdd(NULL, "WALLCHOPS", NULL);
IsupportAdd(NULL, "MAXTARGETS", my_itoa(MAXTARGETS));
IsupportAdd(NULL, "AWAYLEN", my_itoa(TOPICLEN));
IsupportAdd(NULL, "KICKLEN", my_itoa(TOPICLEN));
IsupportAdd(NULL, "TOPICLEN", my_itoa(TOPICLEN));
IsupportAdd(NULL, "CHANNELLEN", my_itoa(CHANNELLEN));
IsupportAdd(NULL, "NICKLEN", my_itoa(iConf.nicklen));
IsupportAdd(NULL, "MAXNICKLEN", my_itoa(NICKLEN));
ircsnprintf(tmpbuf, sizeof(tmpbuf), "b:%d,e:%d,I:%d", MAXBANS, MAXBANS, MAXBANS);
IsupportAdd(NULL, "MAXLIST", tmpbuf);
ircsnprintf(tmpbuf, sizeof(tmpbuf), "#:%d", MAXCHANNELSPERUSER);
IsupportAdd(NULL, "CHANLIMIT", tmpbuf);
IsupportAdd(NULL, "MAXCHANNELS", my_itoa(MAXCHANNELSPERUSER));
IsupportAdd(NULL, "HCN", NULL);
IsupportAdd(NULL, "SAFELIST", NULL);
IsupportAdd(NULL, "NAMESX", NULL);
if (UHNAMES_ENABLED)
IsupportAdd(NULL, "UHNAMES", NULL);
if (cmdstr)
IsupportAdd(NULL, "CMDS", cmdstr);
}
/**
* 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;
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 = (char *)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 = (char *)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);
AddListItem(isupport, Isupports);
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();
}