Initial revision

This commit is contained in:
fishwaldo 2002-02-27 12:21:26 +00:00
commit 4c68fccd87
22 changed files with 4544 additions and 0 deletions

22
.gitattributes vendored Normal file
View file

@ -0,0 +1,22 @@
* text=auto !eol
/ChangeLog -text
/INSTALL -text
/Makefile.in -text
/ReadMe -text
/hash.c -text
lang/Makefile -text
lang/en_us -text svneol=unset#unset
lang/en_us.l -text
lang/index -text
lang/langcomp.c -text
lang/language.h -text
/language.c -text
/language.h -text
/makemask.todo -text
/match.c -text
/new.c -text
/nickserv.c -text
/options.h -text
/services.h -text
/servicescore.c -text
/svc_help.c -text

67
ChangeLog Normal file
View file

@ -0,0 +1,67 @@
Services ChangeLog (A stands for Alpha, B stands for Beta and R stands for Full Release)
Version 0.1.5A - Fish - Ocotber 31, 2001
- Tested with new Neo, 2.0.13, works fine, but 2.0.13 has bugs... waiting
for 2.0.14 (Send Shmad the patches)
- Language system implemented... entire Help Interface done, porting over static
strings as we speak... - Thanks to epona for the language stuff
- a few bug fixes with opercomment
- have to redo recover
- I can see a beta release on the horizon!!!!
Version 0.1.4A - Fish - Ocotber 29, 2001
- Forbidden nicknames now added, and checked when trying to register
if you forbid a nickname that is in use (and online) then it drops the
registration as well (and notifies the online user that its dropped
- more bugfixes
- setpass, getpass added, but can be disabled via config interface
- vhost support enabled (can be disabled)
- all config options now in options.h (till we get our config interface)
Version 0.1.3A - Fish - October 28, 2001
- Access Lists added
- fixed a segfault in core Neo (with corelen in parse)
- Nick Suspension done, with comment place in opercomment field
Version 0.1.2A - Fish - October 27, 2001
- Drop nickname supported, with opers also able to drop nicknames!
(Configurable levels again)
- opercomments added.. Allows opers to save comments with a nick
- sync db done... only sync's nicks that have changed information (good for
large networks.. doesn't try to sync 2000 nicknames when only 100 have
changed information that needs to be synced)
- set interface done
- Woop! its starting to be useable...
- info and channel greetings sets
- AIM, ICQ, Password sets
- private, kill, secure set
- Added some checks to see how long timers and database sync's take.
if it takes too long, it suggests the operators adjust timer settings via
the services channel
- info updated
- logout - if a user wants to stay connected, but not identified to nickserv
(because it might be a shared computer) they can un-identify (idea stolen
from epona!)
Version 0.1.1A - Fish - October 25, 2001
- Services Timers Implemented. Services Have their own Timer system that is
independand of NeoStats
- Nick_change, Kill, Signoff
- Enforcer Nick signon and quit when a nick has not been identified for and
if their kill setting is active
--- This needs investigation, Why Can't I sign on a user straight after
sending svsnick? means I have to use a timer to sign them on, which is
*bad*
- cleaned up some of the logging stuff.. made most other logging, apart from
critical errors #ifdef DEBUG
- A few Bug Fixes.
- Has been running on a largish network for > 2Hrs
- /ctcp nickserv version just for fun!
Version 0.1Alpha - Fish - October 25th, 2001
- First release to Shmad
- Initial Nickserv services implemented... Very Basic Functions at the
moment like:
Register, Identify, Info, Ghost, Recover
- Uses Berkeley Database to store information. Very reliable. (I had so many
crashes during my initial coding, and not once did the database be corrupt)
- As far as I can tell, pretty stable... so far

40
INSTALL Normal file
View file

@ -0,0 +1,40 @@
Services for NeoStats 0.1 Release
=================================
Requirements:
Berkeley DB (Most systems have it already)
- http://www.sleepycat.com/
NeoStats 2.0.12 (Duh)
- http://www.neostats.net/neostats/
Tested with Unreal 3.1.1, 3.1.2 and 3.2Beta3
Depending on how u got Services for Neostats, depends on how to Install it.
If you got it part of Neostats, there isn't much apart from just enabling
services in the configure script:
./configure --enable-services <any other options>
see ./configure --help for other options
if you got it as a Patch, then when I get around to doing it, I will write a
patch, but at the moment, you have to patch manually.
At the moment, if you can't figure out how to Patch stuff, then these
versions are not for you. As Development moves along, I will probably
release a script that patches Neo for you.
(as of Version 2.0.12 of Neo, there is a few bug fixes, but mostly feature
enhancements - Read the NeoStats Changelog after you patch)
Configuration:
==============
If you read the ReadMe file, then you will also realise that untill Operserv
is implemented, there is no easy way to configure Services.
Currently, if you want to change something, then you have to edit
services.h. Towards the bottom of the file are #ifdef's
Some are commented, some are not.
if you are not sure what some of the #ifdef's do, then u should look in the
code.
If you want to reset the Databases, delete data/nsdata.db (for Nickserv)

34
Makefile.in Normal file
View file

@ -0,0 +1,34 @@
INCLUDES = -I../..
SOURCES= match.c hash.c servicescore.c nickserv.c languages.c
OBJECTS= match.o hash.o servicescore.o nickserv.o languages.h
TARGET= services.so
CC=@CC@
CFLAGS=@CFLAGS@ -fPIC $(INCLUDES)
LINKER=ld
all: $(OBJECTS) languages
$(LINKER) -shared -o $(TARGET) $(LIBS) $(OBJECTS)
/bin/cp $(TARGET) ../
clean:
/bin/rm -rf ../$(TARGET) Makefile
/bin/rm -rf *.o *.lo *.so
(cd lang ; $(MAKE clean > /dev/null)
languages:
(cd lang ; $(MAKE) CFLAGS="$(CFLAGS)")
match.o:
hash.o: services.h
servicescore.o: hash.c match.c services.h
languages.o: lanuages.c languages.h services.h
nickserv.o: servicescore.c hash.c match.c services.h
language.h: lang/language.h
cp -p lang/language.h .
lang/language.h: lang/Makefile lang/index
(cd lang ; $(MAKE) language.h)

176
ReadMe Normal file
View file

@ -0,0 +1,176 @@
Services for NeoStats Version 0.1
---------------------------------
Well, I finally got pissed of with some of the services out there, and I
recently played around with Magick-II.
I like some of the features that Magick-II has, but it is a Big Huge Ugly
muther of a monster (I'm not kidding, to Compile Magic and the required
Libaries took well over 5 hours on a Sparc64 Box!)
Unfortuantly, while I can see that Multithreading in Services is a good
idea, making it work effectively is really hard. When you have to deal with
Locking and so on, it can be a real pain.
The Magick-II services, as far as I can tell, have a BIG issue with
locking... constantly I was getting Unknown User and Unknown Channel
messages... the threads were just not working fast enough... (yeah, I know
its beta software, but I honestly think that there is a flaw in Magick-II
base coding, and to fix the problems would require a lot of Re-work)
So, thats what prompted me to write Services for Neostats... I plan to
incorporate as many of the features of Magick-II, and other services that I
like into these services... and make it useable.. something that doesn't
take 5 hours to compile (Currently, NeoStats with Services only takes around
15Sec's to Compile, Beat that Magick!!!!)
------------------------------------------------------------------------------
So here are some of the features I have planned:
------------------------------------------------------------------------------
1. All the Usual NickServ, ChanServ, MemoServ, Operserv features.
2. CommServ, in Magick-II is a nice idea, I'm going to include it as a
optional Module that can be loaded if you want it. See Below for CommServ
Features
3. Optionally Replace NeoStats Permission systems with either a database
(Where Opers have to be defined to have access, or if CommServ is used, by
Committe - Eg, Members of Opers Committe have access to these functions)
4. BotServ. Most Likely, BotServ will talk EggDrop Protocol, so in fact, the
Bots available in BotServ are Eggdrop Bots that are controlled by
Services. This would allow users to have more features that what is in
BotServ in existing Services. This will be after a 1.0 Release.
5. FileServ. A DCC FileService for the Network, where Network Administrators
can setup file serving applications, so they can share files. and example
might be to serve mIRC scripts designed for the network.
6. No Config File. All settings will be done Online. On Un-Configured
Networks, initial configuration would be done via OperServ.
7. Language Support.
The Features of each of the Services will be (and the Order they will be
developed and Milestones for that Release):
0.1 release will be just the Base Services Core. Things I need for All
Services. Not really usable by anyone. Includes:
* Berkeley DB Storage for all Services - Very reliable, and widely
Supported
* Minor Changes to the NeoStats Core (Will be submitted to Shmad for
Future versions of Neostats, hopefully he will accept them, otherwise
I will distribute a Patch System for Neostats to run with Services)
NickServ.(for 0.2 Release - Most features, not all, as some will require
other services, eg, Picture Storage requires FileServ)
* All the standard NickServ features, such as identify, drop, register
* Private (To Hide last online information)
* Secure (To disable identification even if host matchess access list)
* Kill (to either kill a user that has not identified in a specific time,
or to change their nick - The Network will define what it does)
* NickName Expiry (To expire un-used nicks)
* SendPass (Allows opers to send password automatically to the registered
email address of a nick)
* SetPass (Allow Opers to reset passwords)
* GetPass (Allow Opers to retrive passwords)
* Info, URL, Email, ICQ, AIM fields that can be set by the user
* Oper Comments (Allow Operators to set comments about a Nick, that only
other opers can see)
* Forbid (Don't allow users to register certian Nicks
* Suspend (Temporarly suspend access to a Nickname)
* Drop (Drop a Nickname Registration by Opers)
* Configurable Logging, with some PHP scripts to search log files for
events - Ideal when sorting out Nickname Disputes etc etc etc
* Picture Storage - As long as FileServ is active (see below) allow users
to DCC send pictures that can be associated with their nickname
registration, and other users can download it. File size limits can be
set by the Opers (Subject to FileServ Development)
* Ability to replace Current NeoStats Permissions with NickServ
registrations. Eg, can specify levels for nicks, regardless of O line
flags, and the opers can use it.
* Vhost Support. If a user has identified to nickserv, then their vhost
is set to what they have stored with nickserv. 2 ways that this can
work:
* they request a oper to set it, they can not unset it or delete it
without opers help
* They can set it themselves, delete it, or change it.
MemoServ (For 0.3 Release. Most Services available)
* Standard Features such as Send/read/erase
* Long Memos. Ability to write more than 1 line memo's and send to
someone
* File Attachments (Subject to FileServ Development)
* Ability to set Memo's to be forwarded via Email (maybe even ICQ/AIM?)
CommServ (For 0.4 Release, Again Most Services, some will require other
Services to enable)
* Committee MemberShip. ie, you can define a Committee Opers, and add
registered Nicks to that Committee.
* Group Memo's. You can send a Memo to a Committee, and all users of that
Committee get it
* Voting Systems. Allow Committee's to Vote on issues.
* Not Restricted to Opers
* Can replace Current NeoStats Permission systems (based on O line flags)
with Committe Membership. E.G. you can say Opers have access to these
commands, Service Admins can do this plus opers... (Think of the Levels
command in most chanserv's)
* FileServ Integration, so you can share files between members in a
Committee
OperServ (For 0.5 Release)
* Almost all Common OperServ commands found today.
* Akill Management
* Clone Protection
* Nickname Flood Protection
* Kill
* All Commands would be issued via the current NeoStats Bot. (ie, instead
of having NeoStats, and OperServ, just one Bot, NeoStats (or what ever
you want to call it)
* Interface to search Log Files for Events.
* Services Configuration Interface. Upto here, all versions will have all
settings compiled in, and unable to change, after this is done, you will
be able to change settings via OperServ instead of editing a config file.
FileServ (For 0.6 Release)
* Ability to have a FileServer
* Integrated with NickServ, CommServ, MemoServ
* Bandwidth Limiting (So it doesn't consume all your bandwidth and Lag
your Services.
* Queuing. So you Can Say only so many File Transfers can happen at one
time
* A public File area, where Opers can upload certian files
* Automatic Deletion of files associated with Expired Nicks/Committee's
* Quota Support
Channels Support (0.7 Release)
* As NeoStats in its Current form doesn't have any channel support (as of
2.0.12, I'll be working on Channel Support for NeoStats for this release.
No new Service Features (if Shmad works on Channel support and gets it
running before i get here, then this will just end up a maintence
release.)
ChanServ (0.8 Release)
* Normal Channel Services
* Integration with FileServ, to share files between Channel Members
* Op/De-op, modes, access lists, level definitions etc
Release 0.9 will Focus on Stability, and fixing any bugs
Release 1.0 should be fully Functioning Services
After Release 1.0, I'm not sure how the development will proceed. I plan to
Integrate a BotServ into these services as well, but exact details are not
yet Concrete. I've being toying with the idea of implementing support for
Eggdrops BotNet, with Userfile sharing (based on NickServ, ChanServ), as I
think a eggdrop bot integrated with services would be a lot better than a
Static Bot, that can't be extended.
But I'm also thinking about BotServ with a TCL Scripting engine.
I think a TCL engine would be cool, but a lot harder to implement
Other things I'm thinking about after a 1.0 release:
Backup Services with Automatic Replication
Ability to run different *Serv's on different hosts, and all share
information (eg, might be better to have fileserv on a different machine)
Any other features that I think are cool... or anything that you suggest to
me that I think is cool as well.
Also, Language settings would be cool as well.. but I'm still not 100% sure
on how to do that effectivly.
Anyways, thats my Rant for the moment... Read the INSTALL guide on how to
get it all up and running.
if you want more info, then email me at fish@irc-chat.org

446
hash.c Normal file
View file

@ -0,0 +1,446 @@
/* NetStats - IRC Statistical Services
** Copyright (c) 1999 Adam Rutter, Justin Hammond
** http://codeworks.kamserve.com
*
** Based from GeoStats 1.1.0 by Johnathan George net@lite.net
*
** NetStats CVS Identification
** $Id: hash.c,v 1.1 2002/02/27 12:21:27 fishwaldo Exp $
*/
#include <fnmatch.h>
#include "services.h"
void del_svs_dead_timers();
static void add_regnick_to_hash_table(char *name, NS_User *ns)
{
ns->hash = HASH(name, NS_USER_LIST);
ns->next = nsuserlist[ns->hash];
nsuserlist[ns->hash] = (void *)ns;
}
static void del_regnick_from_hash_table(char *name, NS_User *ns)
{
NS_User *tmp, *prev = NULL;
for (tmp = nsuserlist[ns->hash]; tmp; tmp = tmp->next) {
if (tmp == ns) {
if (prev)
prev->next = tmp->next;
else
nsuserlist[ns->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
void sync_changed_nicks_to_db() {
NS_User *tmp;
int i, j = 0;
int starttime;
starttime = time(NULL);
for (i = 0; i < NS_USER_LIST; i++) {
tmp = nsuserlist[i];
while (tmp) {
if (tmp->lastchange > last_db_sync) {
tmp->lastchange = time(NULL);
#ifdef DEBUG
log("Syncing Nick %s", tmp->nick);
#endif
sync_nick_to_db(tmp);
j++;
}
tmp = tmp->next;
}
}
last_db_sync = time(NULL);
/* we always sync anyway, in case other gets/puts have happened outside this timer */
dbp->sync(dbp, 0);
/* this checks how long it took to sync the databaes
** if it took too long, then it warns the opers
** and asks them to decrease the database sync time
** to stop lag of NeoStats
*/
if ((time(NULL) - starttime) > 5) {
notice(s_NickServ, "\002Warning, Database Sync is exceeding threasholds, NeoStats is Lagging out\002");
notice(s_NickServ, "\002Suggest you Change the Database Sync interval to something smaller\002");
notice(s_NickServ, "\002We Synced %d Records in %d Secs...\002", j, time(NULL) - starttime);
}
}
void sync_nick_to_db(NS_User *tmp) {
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = (void *)tmp->nick;
key.size = strlen(tmp->nick);
data.data = (void *)tmp;
data.size = sizeof(*tmp);
i = dbp->put(dbp, NULL, &key, &data, 0);
if (i != 0) {
log("Database Sync Error for %s: %s", tmp->nick, db_strerror(i));
notice(s_NickServ, "\002Database Sync Error\002 for %s: %s", tmp->nick, db_strerror(i));
return;
}
}
void del_nick_from_db(char *nick) {
DBT key;
int i;
memset(&key, 0, sizeof(key));
key.data = (void *)nick;
key.size = strlen(nick);
i = dbp->del(dbp, NULL, &key, 0);
if (i != 0) {
log("Database Sync Error for dropping nick %s: %s", nick, db_strerror(i));
notice(s_NickServ, "\002Database Sync error for dropping nick %s: %s", nick, db_strerror(i));
return;
}
}
void init_nick_forbid_list()
{
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* we store the forbidden lists in a key called ns_forbid_list - Hopefully no user tries to use this nick */
key.data = "ns_forbid_list";
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if (i == DB_NOTFOUND) {
log("Warning: No Forbidden Nick list found in Database!");
return;
} else if (i != 0) {
log("Error: Forbidden Nick list retrival from database %s", db_strerror(i));
return;
} else {
strcpy(ns_forbid_list, data.data);
}
}
void save_nick_forbid_list()
{
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "ns_forbid_list";
key.size = strlen(key.data);
data.data = ns_forbid_list;
data.size = strlen(ns_forbid_list);
i = dbp->put(dbp, NULL, &key, &data, 0);
if (i != 0) {
log("Error: Forbidden Nick list save to database: %s", db_strerror(i));
return;
} else {
notice(s_NickServ, "Saved Forbidden Nick List to database");
}
}
int is_forbidden(char *nick) {
char *tmp, *tmp2;
tmp = malloc(strlen(ns_forbid_list));
strcpy(tmp, ns_forbid_list);
tmp2 = strtok(tmp, " ");
while (tmp2) {
if (fnmatch(tmp2, nick, 0)) {
/* its a match */
free(tmp);
return 1;
}
tmp2 = strtok(NULL, " ");
}
free(tmp);
return 0;
}
void init_regnick_hash()
{
int i;
NS_User *ns, *prev;
for (i = 0; i < NS_USER_LIST; i++) {
ns = nsuserlist[i];
while (ns) {
prev = ns->next;
free(ns);
ns = prev;
}
nsuserlist[i] = NULL;
}
bzero((char *)nsuserlist, sizeof(nsuserlist));
}
NS_User *lookup_regnick(char *name)
{
NS_User *ns2;
DBT key, data;
int i;
ns2 = smalloc(sizeof(NS_User));
bzero(ns2, sizeof(NS_User));
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = (char *)name;
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if (i == DB_NOTFOUND) {
free(ns2);
return NULL;
}
if (i == 0) {
#ifdef DEBUG
log("Getting RegNick From Database");
#endif
ns2 = data.data;
return ns2;
} else {
notice(s_NickServ, "DataBase Error %s", db_strerror(i));
log("Database Error: %s", db_strerror(i));
}
return NULL;
}
NS_User *new_regnick(char *name, int create)
{
NS_User *ns, *ns2;
DBT key, data;
int i;
ns = smalloc(sizeof(NS_User));
ns2 = smalloc(sizeof(NS_User));
bzero(ns, sizeof(NS_User));
bzero(ns2, sizeof(NS_User));
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = name;
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if ((i == DB_NOTFOUND) && (create == 0)) {
free(ns);
free(ns2);
return NULL;
}
if ((i == 0) && (create ==0)) {
#ifdef DEBUG
log("Getting RegNick From Database");
#endif
ns2 = data.data;
strcpy(ns->pass, ns2->pass);
strcpy(ns->url, ns2->url);
strcpy(ns->email, ns2->email);
strcpy(ns->acl, ns2->acl);
strcpy(ns->last_mask, ns2->last_mask);
strcpy(ns->last_quit, ns2->last_quit);
strcpy(ns->aim, ns2->aim);
strcpy(ns->info, ns2->info);
strcpy(ns->greet, ns2->greet);
strcpy(ns->vhost, ns2->vhost);
ns->icq = ns2->icq;
ns->language = ns2->language;
ns->kill = ns2->kill;
ns->secure = ns2->secure;
ns->private = ns2->private;
ns->onlineflags = 0;
ns->lastchange = 0;
ns->registered_at = ns2->registered_at;
ns->flags = ns2->flags;
ns->last_seen_at = ns2->last_seen_at;
/* free(ns2); */
}
memcpy(ns->nick, name, strlen(name)+1);
add_regnick_to_hash_table(name, ns);
return ns;
}
NS_User *findregnick(char *name)
{
NS_User *ns;
ns = nsuserlist[HASH(name, NS_USER_LIST)];
while (ns && strcasecmp(ns->nick, name) != 0)
ns = ns->next;
#ifdef DEBUG
log("findregnick(%s) -> %s", name, (ns) ? ns->nick : "NOTFOUND");
#endif
return ns;
}
void del_regnick(char *name)
{
NS_User *ns = findregnick(name);
#ifdef DEBUG
log("DelRegnick(%s)", name);
#endif
if (!ns) {
log("Delregnick(%s) failed!", name);
return;
}
del_regnick_from_hash_table(name, ns);
}
/* this is the Timer Hash setting... Things can be added to the services timer, which get called again (Consider them a timer within a timer!) */
static void add_svstimer_to_hash_table(char *name, Svs_Timers *svstmr)
{
svstmr->hash = HASH(name, MAX_SVS_TIMERS);
svstmr->next = serv_timers[svstmr->hash];
serv_timers[svstmr->hash] = (void *)svstmr;
}
static void del_svstimer_from_hash_table(char *name, Svs_Timers *svstmr)
{
Svs_Timers *tmp, *prev = NULL;
for (tmp = serv_timers[svstmr->hash]; tmp; tmp = tmp->next) {
if (tmp == svstmr) {
if (prev)
prev->next = tmp->next;
else
serv_timers[svstmr->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
void init_svstimer_hash()
{
int i;
Svs_Timers *svstmr, *prev;
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
prev = svstmr->next;
free(svstmr);
svstmr = prev;
}
serv_timers[i] = NULL;
}
bzero((char *)serv_timers, sizeof(serv_timers));
}
int runsvstimers()
{
Svs_Timers *svstmr;
time_t current = time(NULL);
int i, ret = 0;
int startime, count = 0;
startime = time(NULL);
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
if (current - svstmr->lastrun >= svstmr->interval) {
#ifdef DEBUG
log("runsvstimers(%s)", svstmr->timername);
#endif
svstmr->lastrun = time(NULL);
ret = svstmr->function(svstmr->varibles);
/* if ret = 1 then delete the timer */
if (ret == 1) {
svstmr->interval = 0;
}
count++;
}
svstmr = svstmr->next;
}
}
/* only run garbage cleanup if there is something to clean up */
if (ret == 1) del_svs_dead_timers();
if ((time(NULL) - startime) > 5) {
notice(s_NickServ, "\002Warning, Timers are taking a long time to run\002");
notice(s_NickServ, "\002This is Lagging out NeoStats\002");
notice(s_NickServ, "\002Suggest you Change your Timer Settings (Such a EnforcerTime, Identtime) to something smaller\002");
notice(s_NickServ, "\002If this message keeps re-occuring. (it might be normal when a split server rejoins)\002");
notice(s_NickServ, "\002We Ran %d timers and it took %d Sec...\002", count, time(NULL) - startime);
}
return 1;
}
void del_svs_dead_timers()
{
Svs_Timers *svstmr;
int i;
#ifdef DEBUG
log("Services Timer Garbage Cleanup");
#endif
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
if (svstmr->interval == 0) {
del_svstimer_from_hash_table(svstmr->timername, svstmr);
}
svstmr = svstmr->next;
}
}
}
void del_svs_timers(char *name)
{
Svs_Timers *svstmr;
#ifdef DEBUG
log("Delsvstimer(%s)", name);
#endif
svstmr = serv_timers[HASH(name, MAX_SVS_TIMERS)];
while (svstmr && strcasecmp(svstmr->timername, name) != 0)
svstmr = svstmr->next;
if (!svstmr) {
log("Delsvstimer(%s) failed!", name);
return;
}
del_svstimer_from_hash_table(name, svstmr);
}
Svs_Timers *new_svs_timers(char *name)
{
Svs_Timers *svstmr;
svstmr = malloc(sizeof(Svs_Timers));
bzero(svstmr, sizeof(Svs_Timers));
#ifdef DEBUG
log("New Services Timer: %s", name);
#endif
memcpy(svstmr->timername, name, strlen(name));
add_svstimer_to_hash_table(name, svstmr);
return svstmr;
}

43
lang/Makefile Normal file
View file

@ -0,0 +1,43 @@
# Makefile for language module
#include ../../Makefile
LANGOBJS = en_us
LANGSRCS = en_us.l
#LANGCOMP = ./langcomp
LANGCOMP = ./langcomp -w
all: $(LANGOBJS)
clean:
rm -f $(LANGOBJS) langcomp language.h
spotless: clean
rm -f language.h
en_us: en_us.l langcomp index
./langcomp $@.l
langcomp: langcomp.c
$(CC) $(CFLAGS) langcomp.c -o $@
language.h: index Makefile
@perl -e <index >$@ '\
print STDERR "Generating language.h... "; \
$$i=0; \
while (<>) { \
chop; \
printf "#define %-32s %d\n", $$_, $$i++; \
} \
print "\n#define NUM_STRINGS $$i\n"; \
print STDERR "$$i strings\n";'
index: en_us.l
grep '^[A-Z]' en_us.l >index

BIN
lang/en_us Normal file

Binary file not shown.

413
lang/en_us.l Normal file
View file

@ -0,0 +1,413 @@
# United States English language file.
#
# Epona (c) 2000-2001 PegSoft
# Contact us at epona@pegsoft.net
#
# This program is free but copyrighted software; see the file COPYING for
# details.
#
# Based on the original code of Services by Andy Church.
# When translating this file to another language, keep in mind that the
# order of parameters for sprintf() is fixed in the source code, so your
# messages need to take the same parameters in the same order as the
# English messages do. (Obviously, this doesn't hold for the strftime()
# format lines immediately below.) If you can't get a natural translation
# of a message without changing the order of the parameters, let me know
# (achurch@dragonfire.net) which message is causing a problem and I'll see
# what I can do.
#
# In help messages, "%S" (capital S, not lowercase) refers to the name of
# the service sending the message; for example, in NickServ help messages,
# "%S" is replaced by "NickServ" (or whatever it is renamed to in
# config.h). The %S's do not count as sprintf() parameters, so they can be
# rearranged, removed, or added as necessary.
#
# Also in help messages, please try to limit line lengths to 60 characters
# of text (not including the leading tab). This length was chosen because
# it does not cause line wrap under default settings on most current IRC
# clients. Remember that format characters (control-B, control-_) are not
# included in that 60-character limit (since they don't show on the user's
# screen). Also remember that format specifiers (%S, etc.) will expand
# when displayed, so remember to take this into account; you can assume
# that the length of a pseudoclient name (%S replacement) will be eight
# characters, so reduce the maximum line length by 6 for every %S on a
# line.
#
# Finally, remember to put a tab at the beginning of every line of text
# (including empty lines). This has to be a tab, not spaces.
#
###########################################################################
#
# Name of this language
#
###########################################################################
# For languages other than English, this string should have the following
# format:
# language-name-in-language (language-name-in-English)
# For example, "Español (Spanish)" or "Français (French)".
LANG_NAME
English
###########################################################################
#
# General messages
#
###########################################################################
# strftime() format strings. man 3 strftime for information on the
# meanings of the format specifiers. Short version:
# %a = weekday name (short) %H = hour
# %b = month name (short) %M = minute
# %d = day of month %S = second
# %Y = year %Z = time zone
# This is used as the format string for strftime() for a date and time
# together.
STRFTIME_DATE_TIME_FORMAT
%b %d %H:%M:%S %Y %Z
# This is used as the format string for strftime() for a date alone in long
# format (English: including weekday).
STRFTIME_LONG_DATE_FORMAT
%a %b %d %Y
# This is used as the format string for strftime() for a date alone in
# short format (English: without weekday).
STRFTIME_SHORT_DATE_FORMAT
%b %d %Y
# These tell our strftime() what the names of months and days are. If you
# don't use %a, %A, %b, or %B in your strftime() strings above, you can
# leave these empty. However, if you enter names, they MUST stay in order,
# one per line, and the list MUST be complete!
# %a
STRFTIME_DAYS_SHORT
Sun
Mon
Tue
Wed
Thu
Fri
Sat
# %A
STRFTIME_DAYS_LONG
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
# %b
STRFTIME_MONTHS_SHORT
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
# %B
STRFTIME_MONTHS_LONG
January
February
March
April
May
June
July
August
September
October
November
December
# This is used in ChanServ/NickServ INFO displays.
COMMA_SPACE
,
# Various error messages.
NICKSERV_HELP
%S allows a IRC user to Register, or own a Nickname on the
IRC Network. This can be usefull to prevent other uses from using
your Nickname and impersinating you. You can also use NickServ to
store information about youself such as Email address, or webpage URL.
The Following list are the commands that you can use with %S.
To get further help with these commands, or to find out what they
to, type /msg %S help <command>.
Register Allows you to Register a New NickName
Identify Allows you to identify for your nickname after registration
Info Retrive information about your nickname, or someone elses nickname
Ghost Kill a Ghost user that has your nickname
Recover Get your nickname released if a Enforcer has taken it
Drop Drop your nickname registration
Logout Logout from Services. (un-Identify)
Set Set various options for your nickname (/msg %S help set for more information)
Access Set your lists of hosts from which you want to be automatically identified
NOTICE: This Service provides a interface for users to Register their Nickname,
it is not indended to Steal nicknames on the network. Any abuse of
this services will result in you loosing access to these services.
Nicknames that are not used for a period of time can be "expired",
meaning that the registration information is deleted, and the nickname is
able to be registered by any other user.
NICKSERV_OPERHELP
Additional Commands available to Operators:
NICKSERV_HELPOPERCOMMENT
OperComment
NICKSERV_HELPSUSPEND
Suspend
NICKSERV_HELPFORBID
Forbid
NICKSERV_HELPGETPASS
GetPass
NICKSERV_HELPSETPASS
SetPass
NICKSERV_HELPVHOST
Vhost
NICKSERV_HELP_REGISTER
Syntax: /msg %S register <email> <password>
Register allows you to Register a nickname with services.
This allows you to "own" this nickname on the irc network, and to
use the advanced features of these Services.
Set and Access allows you to configure this nickname
registration to your prefered settings.
Your email address is considered private, and will not be share with
any 3rd parties, but may be viewed via the info command. (This can be
disabled via a set command)
You should use a password that is hard to guess, and contains both
numbers and letters. This can stop people from easily guessing your password
and taking over your nickname.
NICKSERV_HELP_IDENTIFY
Syntax: /msg %S identify <password>
Identify allows you to tell services that you really own
your nickname. Identify is like a logon command for Services. A lot
of Commands that services have require that you are "identified"
(sent this command and recieved a positive acknowledgement)
NICKSERV_HELP_INFO
Syntax: /msg %S info <nickname>
Info allows you to view any public information on a
particular registered nickname. Information such as the last time a user was
seen on the network, Email addresses, or ICQ numbers maybe visible depending
on what a user has set.
Additionally, if you specify your own nickname after identifing to
Services, you can see your settings.
NICKSERV_HELP_INFO_OPERS
Additionally, as a Operator, allows you to view all the users
settings, including OperComments, or Vhost Settings.
NICKSERV_HELP_GHOST
Syntax: /msg %S ghost <nickname> <password>
Ghost Allows a User to regain their registered nickname, if has
been taken by another user, or if it is a result of a Ghosted Connection.
This can be a result of when you get disconnected from the irc
server, but the server hasn't notice it yet.
NICKSERV_HELP_RECOVER
Syntax: /msg %S recover <nickname> <password>
Recover allows you to regain a nickname when someone else has
taken your Nickname, but it works a bit differently. Recover will change the
Person who currently has your Nick, to a Random Nickname, and will Sign on a
"Enforcer" or fake user with your nickname. This can stop other
people from automatically re-taking your nickname. This "Enforcer" user will
disconnect after a short period, and allow you to take your Nickname. After
which, you maybe required to Identify again
NICKSERV_HELP_OPERDROP
Syntax: /msg %S drop <nickname>
Drop allows you to drop a Registered Nickname if you have the
correct Privledges with Services.
NICKSERV_HELP_DROP
Syntax: /msg %S drop
Drop will drop your nickname registration from the Services
Database, and delete any records associated with any of the services to do
with this nickname.
if you drop your Nickname, it cannot be un-done, so use with care
NICKSERV_HELP_LOGOUT
Syntax: /msg %S logout
Logout allows you to "un-identify" to services. This means that
you will not be reconised with serivices at all, regardless of your settings
(eg, even if you match your access list, you will still not be reconised).
This is usefull if you wish to stay on IRC, but are using a shared
computer, and do not want other people to mess with your Registered
Nickname.
NICKSERV_HELP_SET
Syntax: /msg %S set <option> <value>
Set allows you to customize certian settings with regards to your
Nickname Registration. Some of these Settings include email or passwords,
and Channel Greeting Messages, among others.
The Available Options are:
PASSWORD Allows you to set a New Password for your account
URL Allows you to set a URL that will be displayed with the info command
EMAIL Allows you to change your registered email account
ICQ Allows you to set a ICQ number that is displayed in the info command
INFO Set a General Description of youself. Maybe Something Funny or witty
AIM Allows you to set a AIM handle that is displayed in the info command
GREET Sets your Channel Entry message
KILL Toggles your Kill setting.
SECURE Toggles your Secure Setting.
PRIVATE Toggles your Private Setting.
VHOST Change your Vhost (May not be enabled on all networks)
/msg %S set will display your current Settings
more information can be found on each option, by typing /msg $S help set <option>
NICKSERV_HELP_SET_PASSWORD
Syntax: /msg %S set password <newpass>
Set Password allows you to change the password with your nickname registration.
You should pick a password that is difficult to guess, to stop
people from taking over your account by guessing your password.
NICKSERV_HELP_SET_URL
Syntax: /msg %S set url <newurl>/NONE
Set URL allows you to set or delete a URL that is displayed when people lookup your
nickname using the info command.
This can be used as a way for people to find out more information about yourself.
if you type NONE instead of a URL, then your current URL will be deleted.
NICKSERV_HELP_SET_EMAIL
Syntax: /msg %S set email <newemail>
Set Email allows you to change the email account that is assocated
with your services registration. The email must be a valid email account, so
that if you loose or forget your password, a Service Operator can send you a
your password via Email. Please keep this upto date.
NICKSERV_HELP_SET_ICQ
Syntax: /msg %S set icq <account>/NONE
Set ICQ allows you to set your ICQ number that will be displayed
when people lookup your information via the info command.
this can be used as a way for people to find out more information
about yourself.
if you type NONE instead of a ICQ number, then your ICQ number will
be deleted.
NICKSERV_HELP_SET_INFO
Syntax: /msg %S set info <text>
Set Info allows you to set a brief set of text that is displayed
when someone looks up your nickname with the info command.
Optionally, some networks also add this info line to your WHOIS
information, but this may be disabled on some networks.
NICKSERV_HELP_SET_AIM
Syntax: /msg %S set AIM <handle>/NONE
Set AIM allows you to set your AOL Instant Messaganger handle that
is displayed when someone looks up your nickname with the info command
this can be usefull to display additional information about
yourself.
you can delete this information with the NONE command.
NICKSERV_HELP_SET_GREET
Syntax: /msg %S set greet <text>/NONE
Set Greet allows you to set a message that is displayed when you
enter a channel that has this feature turned on and is registered.
This text could be a description of yourself, or a witty comment.
setting this to NONE will delete your Channel Greeting message.
NICKSERV_HELP_SET_KILL
Syntax: /msg %S set kill
Set Kill allows you to enforce some identification features of %S
kill when turned on, means that if you do not match a host in your
access list, or secure is turned off, you will have to identify to %S to
gain access to your nickname, otherwise your nickname will be changed.
this can be used to stop people using your nickname while you are
not online, and it does NOT kill a user for using your nickname, it only
changes their nickname if they do not supply the correct password within a
time limit.
see also: Set Secure
NICKSERV_HELP_SET_SECURE
Syntax: /msg %S set secure
Set Secure allows you to enable or disable the use of your access
lists for identification. if you have secure enabled, and kill is enabled as
well, then you must supply your password, otherwise your nickname will be
changed. if you have secure disabled, and kill enabled, then you will gain
limited access to your nickname, but some features or channels will still
require you to identify to gain access to them.
see also: Set Kill
NICKSERV_HELP_SET_PRIVATE
Syntax: /msg %S set private
Set Private allows you to disable the display of your email
address, the last time you were online, and your last hostname you connected
from in the info command.
if you have set things like ICQ, INFO, AIM etc, they will still be
visible.
NICKSERV_HELP_SET_VHOST
Syntax: /msg %S set vhost <hostname>/NONE
Set Vhost allows you to change the hostname you will appear to
connect from when you identify to %S.
Setting it to NONE will mean that your hostname will not change when
you identify to %S
Some Networks may have this feature disabled, or they may require a
Operator to set it for you. Check with your Networks Help Channel.
NICKSERV_HELP_OPERCOMMENT
Syntax: /msg %S opercomment <nick> <comment>
OperComment allows Operators to set comments associated with
registered nicknames, that are only visible by other Operators in the info
command.
This can be used as a way to comunicate information about a user
between operators. When you set a Comment, your nickname is also saved with
that comment.
e.g.: /msg %S opercomment this user always asks for ops in the help channels, don't give it to him.
would display that comment when another operator looks up his
registration information with %S
NICKSERV_HELP_SUSPEND
Syntax: /msg %S suspend <nick> <comment>/OFF
Suspend allows a Operator to suspend the use of a registered nickname
with services. This could be used by a operator to syspend a registration
for a troublesome user while investigations are made. While a user is
suspended, they can not access any services functions unless they register a
new nickname.
NICKSERV_HELP_FORBID
Syntax: /msg %S forbid list/add/del <option>
Forbid controls what type of nicknames can be registered with
services. It does not forbid the use of a nickname on a network (use SQLINE
for that).
/msg %S forbid list
this will list the current forbidden list.
/msg %S forbid add <nickmask>
this will add a nickname mask to the forbidden list. You can use Wildcards here (Such as * and ?).
/msg %S forbid del <num>
this will delete the corrosponding nickname from the forbidden list.
you can get the num, via the /msg %S forbid list command.
NICKSERV_HELP_GETPASS
Syntax: /msg %S getpass <nick>
GetPass allows a operator to retrive a registered nicknames
password from the database.
when this command is used, a Global message is sent to all online
operators, and the action is logged, to help stop abuse of this command by
operators.
NICKSERV_HELP_SETPASS
Syntax: /msg %S setpass <nick> <newpass>
SetPass allows a operator to reset a users password to a new
password.
When this command is used, a Global message is sent to all online
operators and the action is logged, to help stop abuse of this command by
operators.
NICKSERV_HELP_VHOST
Syntax: /msg %S vhost <nick> <vhost>/NONE
Vhost allows a operator to set or remove a users Virtual host that
they will recieve when they identify to services.
typing NONE will remove the users vhost.
NICKSERV_HELP_ACCESS
Syntax: /msg %S access list/add/current/del <option>
Access allows you to control your access lists with Services.
if you have kill turned on, and secure turned off, then if you
connect and match a access list, you will not be required to identify to
gain access to certian functions.
/msg %S access list
will list your current access lists associated with your nickname.
/msg %S access add <user@host>
will add the user@host to your access lists (You can use the
wildcards ? and * here as well>
/msg %S access current
will add your current hostmask to the access list if it does not
already exist
/msg %S access del <num>
will delete the corrosponding entry out of your access list. You can
figure out what num is via /msg %S access list

45
lang/index Normal file
View file

@ -0,0 +1,45 @@
LANG_NAME
STRFTIME_DATE_TIME_FORMAT
STRFTIME_LONG_DATE_FORMAT
STRFTIME_SHORT_DATE_FORMAT
STRFTIME_DAYS_SHORT
STRFTIME_DAYS_LONG
STRFTIME_MONTHS_SHORT
STRFTIME_MONTHS_LONG
COMMA_SPACE
NICKSERV_HELP
NICKSERV_OPERHELP
NICKSERV_HELPOPERCOMMENT
NICKSERV_HELPSUSPEND
NICKSERV_HELPFORBID
NICKSERV_HELPGETPASS
NICKSERV_HELPSETPASS
NICKSERV_HELPVHOST
NICKSERV_HELP_REGISTER
NICKSERV_HELP_IDENTIFY
NICKSERV_HELP_INFO
NICKSERV_HELP_INFO_OPERS
NICKSERV_HELP_GHOST
NICKSERV_HELP_RECOVER
NICKSERV_HELP_OPERDROP
NICKSERV_HELP_DROP
NICKSERV_HELP_LOGOUT
NICKSERV_HELP_SET
NICKSERV_HELP_SET_PASSWORD
NICKSERV_HELP_SET_URL
NICKSERV_HELP_SET_EMAIL
NICKSERV_HELP_SET_ICQ
NICKSERV_HELP_SET_INFO
NICKSERV_HELP_SET_AIM
NICKSERV_HELP_SET_GREET
NICKSERV_HELP_SET_KILL
NICKSERV_HELP_SET_SECURE
NICKSERV_HELP_SET_PRIVATE
NICKSERV_HELP_SET_VHOST
NICKSERV_HELP_OPERCOMMENT
NICKSERV_HELP_SUSPEND
NICKSERV_HELP_FORBID
NICKSERV_HELP_GETPASS
NICKSERV_HELP_SETPASS
NICKSERV_HELP_VHOST
NICKSERV_HELP_ACCESS

256
lang/langcomp.c Normal file
View file

@ -0,0 +1,256 @@
/* Compiler for language definition files.
*
* Epona (c) 2000-2001 PegSoft
* Contact us at epona@pegsoft.net
*
* This program is free but copyrighted software; see the file COPYING for
* details.
*
* Based on the original code of Services by Andy Church.
*
*/
/*
* A language definition file contains all strings which Services sends to
* users in a particular language. A language file may contain comments
* (lines beginning with "#") and blank lines. All other lines must adhere
* to the following format:
*
* Each string definition begins with the C name of a message (as defined
* in the file "index"--see below). This must be alone on a line, preceded
* and followed by no blank space. Following this line are zero or more
* lines of text; each line of text must begin with exactly one tab
* character, which is discarded. Newlines are retained in the strings,
* except the last newline in the text, which is discarded. A message with
* no text is replaced by a null pointer in the array (not an empty
* string).
*
* All messages in the program are listed, one per line, in the "index"
* file. No comments or blank lines are permitted in that file. The index
* file can be generated from a language file with a command like:
* grep '^[A-Z]' en_us.l >index
*
* This program takes one parameter, the name of the language file. It
* generates a compiled language file whose name is created by removing any
* extension on the source file on the input filename.
*
* You may also pass a "-w" option to print warnings for missing strings.
*
* This program isn't very flexible, because it doesn't need to be, but
* anyone who wants to try making it more flexible is welcome to.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#undef getline
int numstrings = 0; /* Number of strings we should have */
char **stringnames; /* Names of the strings (from index file) */
char **strings; /* Strings we have loaded */
int linenum = 0; /* Current line number in input file */
/*************************************************************************/
/* Read the index file and load numstrings and stringnames. Return -1 on
* error, 0 on success. */
int read_index_file()
{
FILE *f;
char buf[256];
int i;
if (!(f = fopen("index", "r"))) {
perror("fopen(index)");
return -1;
}
while (fgets(buf, sizeof(buf), f))
numstrings++;
if (!(stringnames = calloc(sizeof(char *), numstrings))) {
perror("calloc(stringnames)");
return -1;
}
if (!(strings = calloc(sizeof(char *), numstrings))) {
perror("calloc(strings)");
return -1;
}
fseek(f, 0, SEEK_SET);
i = 0;
while (fgets(buf, sizeof(buf), f)) {
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = 0;
if (!(stringnames[i++] = strdup(buf))) {
perror("strdup()");
return -1;
}
}
fclose(f);
return 0;
}
/*************************************************************************/
/* Return the index of a string name in stringnames, or -1 if not found. */
int stringnum(const char *name)
{
int i;
for (i = 0; i < numstrings; i++) {
if (strcmp(stringnames[i], name) == 0)
return i;
}
return -1;
}
/*************************************************************************/
/* Read a non-comment, non-blank line from the input file. Return NULL at
* end of file. */
char *getline(FILE *f)
{
static char buf[1024];
char *s;
do {
if (!(fgets(buf, sizeof(buf), f)))
return NULL;
linenum++;
} while (*buf == '#' || *buf == '\n');
s = buf + strlen(buf)-1;
if (*s == '\n')
*s = 0;
return buf;
}
/*************************************************************************/
/* Write a 32-bit value to a file in big-endian order. */
int fput32(int val, FILE *f)
{
if (fputc(val>>24, f) < 0 ||
fputc(val>>16, f) < 0 ||
fputc(val>> 8, f) < 0 ||
fputc(val , f) < 0
) {
return -1;
} else {
return 0;
}
}
/*************************************************************************/
int main(int ac, char **av)
{
unsigned char *filename = NULL, *s;
char langname[254], outfile[256];
FILE *in, *out;
int warn = 0;
int retval = 0;
int curstring = -2, i;
char *line;
int pos;
int maxerr = 50; /* Max errors before we bail out */
if (ac >= 2 && strcmp(av[1], "-w") == 0) {
warn = 1;
av[1] = av[2];
ac--;
}
if (ac != 2) {
fprintf(stderr, "Usage: %s [-w] <lang-file>\n", av[0]);
return 1;
}
filename = av[1];
s = strrchr(filename, '.');
if (!s)
s = filename + strlen(filename);
if (s-filename > sizeof(langname)-3)
s = filename + sizeof(langname)-1;
strncpy(langname, filename, s-filename);
langname[s-filename] = 0;
sprintf(outfile, "%s", langname);
if (read_index_file() < 0)
return 1;
if (!(in = fopen(filename, "r"))) {
perror(filename);
return 1;
}
if (!(out = fopen(outfile, "w"))) {
perror(outfile);
return 1;
}
while (maxerr > 0 && (line = getline(in)) != NULL) {
if (*line == '\t') {
if (curstring == -2) {
fprintf(stderr, "%s:%d: Junk at beginning of file\n",
filename, linenum);
retval = 1;
} else if (curstring >= 0) {
line++;
i = strings[curstring] ? strlen(strings[curstring]) : 0;
if (!(strings[curstring] =
realloc(strings[curstring], i+strlen(line)+2))) {
fprintf(stderr, "%s:%d: Out of memory!\n",filename,linenum);
return 2;
}
sprintf(strings[curstring]+i, "%s\n", line);
}
} else {
if ((curstring = stringnum(line)) < 0) {
fprintf(stderr, "%s:%d: Unknown string name `%s'\n",
filename, linenum, line);
retval = 1;
maxerr--;
} else if (strings[curstring]) {
fprintf(stderr, "%s:%d: Duplicate occurrence of string `%s'\n",
filename, linenum, line);
retval = 1;
maxerr--;
} else {
if (!(strings[curstring] = malloc(1))) {
fprintf(stderr, "%s:%d: Out of memory!\n",filename,linenum);
return 2;
}
*strings[curstring] = 0;
}
if (maxerr == 0)
fprintf(stderr, "%s:%d: Too many errors!\n", filename, linenum);
}
}
fput32(numstrings, out);
pos = numstrings * 8 + 4;
for (i = 0; i < numstrings; i++) {
int len = strings[i] && *strings[i] ? strlen(strings[i])-1 : 0;
fput32(pos, out);
fput32(len, out);
pos += len;
}
for (i = 0; i < numstrings; i++) {
if (strings[i]) {
if (*strings[i])
strings[i][strlen(strings[i])-1] = 0; /* kill last \n */
if (*strings[i])
fputs(strings[i], out);
} else if (warn) {
fprintf(stderr, "%s: String `%s' missing\n", filename,
stringnames[i]);
}
}
fclose(in);
fclose(out);
return retval;
}
/*************************************************************************/

47
lang/language.h Normal file
View file

@ -0,0 +1,47 @@
#define LANG_NAME 0
#define STRFTIME_DATE_TIME_FORMAT 1
#define STRFTIME_LONG_DATE_FORMAT 2
#define STRFTIME_SHORT_DATE_FORMAT 3
#define STRFTIME_DAYS_SHORT 4
#define STRFTIME_DAYS_LONG 5
#define STRFTIME_MONTHS_SHORT 6
#define STRFTIME_MONTHS_LONG 7
#define COMMA_SPACE 8
#define NICKSERV_HELP 9
#define NICKSERV_OPERHELP 10
#define NICKSERV_HELPOPERCOMMENT 11
#define NICKSERV_HELPSUSPEND 12
#define NICKSERV_HELPFORBID 13
#define NICKSERV_HELPGETPASS 14
#define NICKSERV_HELPSETPASS 15
#define NICKSERV_HELPVHOST 16
#define NICKSERV_HELP_REGISTER 17
#define NICKSERV_HELP_IDENTIFY 18
#define NICKSERV_HELP_INFO 19
#define NICKSERV_HELP_INFO_OPERS 20
#define NICKSERV_HELP_GHOST 21
#define NICKSERV_HELP_RECOVER 22
#define NICKSERV_HELP_OPERDROP 23
#define NICKSERV_HELP_DROP 24
#define NICKSERV_HELP_LOGOUT 25
#define NICKSERV_HELP_SET 26
#define NICKSERV_HELP_SET_PASSWORD 27
#define NICKSERV_HELP_SET_URL 28
#define NICKSERV_HELP_SET_EMAIL 29
#define NICKSERV_HELP_SET_ICQ 30
#define NICKSERV_HELP_SET_INFO 31
#define NICKSERV_HELP_SET_AIM 32
#define NICKSERV_HELP_SET_GREET 33
#define NICKSERV_HELP_SET_KILL 34
#define NICKSERV_HELP_SET_SECURE 35
#define NICKSERV_HELP_SET_PRIVATE 36
#define NICKSERV_HELP_SET_VHOST 37
#define NICKSERV_HELP_OPERCOMMENT 38
#define NICKSERV_HELP_SUSPEND 39
#define NICKSERV_HELP_FORBID 40
#define NICKSERV_HELP_GETPASS 41
#define NICKSERV_HELP_SETPASS 42
#define NICKSERV_HELP_VHOST 43
#define NICKSERV_HELP_ACCESS 44
#define NUM_STRINGS 45

320
language.c Normal file
View file

@ -0,0 +1,320 @@
/* Multi-language support.
*
* Epona (c) 2000-2001 PegSoft
* Contact us at epona@pegsoft.net
*
* This program is free but copyrighted software; see the file COPYING for
* details.
*
* Based on the original code of Services by Andy Church.
*
*/
#include <stdio.h>
#include "services.h"
#include "language.h"
#include "stats.h"
/*************************************************************************/
/* The list of lists of messages. */
char **langtexts[NUM_LANGS];
/* The list of names of languages. */
char *langnames[NUM_LANGS];
/* Indexes of available languages: */
int langlist[NUM_LANGS];
/* Order in which languages should be displayed: (alphabetical) */
static int langorder[NUM_LANGS] = {
LANG_EN_US, /* English (US) */
};
/*************************************************************************/
/* Load a language file. */
static int read_int32(int *ptr, FILE *f)
{
int a = fgetc(f);
int b = fgetc(f);
int c = fgetc(f);
int d = fgetc(f);
if (a == EOF || b == EOF || c == EOF || d == EOF)
return -1;
*ptr = a<<24 | b<<16 | c<<8 | d;
return 0;
}
static void load_lang(int index, const char *filename)
{
char buf[256];
FILE *f;
int num, i;
#ifdef DEBUG
log("debug: Loading language %d from file `dl/services/lang/%s'",
index, filename);
#endif
snprintf(buf, sizeof(buf), "dl/services/lang/%s", filename);
if (!(f = fopen(buf, "r"))) {
log("Failed to load language %d (%s)", index, filename);
return;
} else if (read_int32(&num, f) < 0) {
log("Failed to read number of strings for language %d (%s)",
index, filename);
return;
} else if (num != NUM_STRINGS) {
log("Warning: Bad number of strings (%d, wanted %d) "
"for language %d (%s)", num, NUM_STRINGS, index, filename);
}
langtexts[index] = smalloc(sizeof(char *) * NUM_STRINGS);
if (num > NUM_STRINGS)
num = NUM_STRINGS;
for (i = 0; i < num; i++) {
int pos, len;
fseek(f, i*8+4, SEEK_SET);
if (read_int32(&pos, f) < 0 || read_int32(&len, f) < 0) {
log("Failed to read entry %d in language %d (%s) TOC",
i, index, filename);
while (--i >= 0) {
if (langtexts[index][i])
free(langtexts[index][i]);
}
free(langtexts[index]);
langtexts[index] = NULL;
return;
}
if (len == 0) {
langtexts[index][i] = NULL;
} else if (len >= 65536) {
log("Entry %d in language %d (%s) is too long (over 64k)--"
"corrupt TOC?", i, index, filename);
while (--i >= 0) {
if (langtexts[index][i])
free(langtexts[index][i]);
}
free(langtexts[index]);
langtexts[index] = NULL;
return;
} else if (len < 0) {
log("Entry %d in language %d (%s) has negative length--"
"corrupt TOC?", i, index, filename);
while (--i >= 0) {
if (langtexts[index][i])
free(langtexts[index][i]);
}
free(langtexts[index]);
langtexts[index] = NULL;
return;
} else {
langtexts[index][i] = smalloc(len+1);
fseek(f, pos, SEEK_SET);
if (fread(langtexts[index][i], 1, len, f) != len) {
log("Failed to read string %d in language %d (%s)",
i, index, filename);
while (--i >= 0) {
if (langtexts[index][i])
free(langtexts[index][i]);
}
free(langtexts[index]);
langtexts[index] = NULL;
return;
}
langtexts[index][i][len] = 0;
}
}
fclose(f);
}
/*************************************************************************/
/* Initialize list of lists. */
void lang_init()
{
int i, j, n = 0;
load_lang(LANG_EN_US, "en_us");
for (i = 0; i < NUM_LANGS; i++) {
if (langtexts[langorder[i]] != NULL) {
langnames[langorder[i]] = langtexts[langorder[i]][LANG_NAME];
langlist[n++] = langorder[i];
for (j = 0; j < NUM_STRINGS; j++) {
if (!langtexts[langorder[i]][j]) {
langtexts[langorder[i]][j] =
langtexts[DEF_LANGUAGE][j];
}
if (!langtexts[langorder[i]][j]) {
langtexts[langorder[i]][j] =
langtexts[LANG_EN_US][j];
}
}
}
}
while (n < NUM_LANGS)
langlist[n++] = -1;
/* Not what I intended to do, but these services are so archaïc
* that it's difficult to do more. */
if ((NSDefLanguage = langlist[NSDefLanguage]) < 0)
NSDefLanguage = DEF_LANGUAGE;
if (!langtexts[DEF_LANGUAGE]) {
log("Unable to load default language");
exit(-1);
}
for (i = 0; i < NUM_LANGS; i++) {
if (!langtexts[i])
langtexts[i] = langtexts[DEF_LANGUAGE];
}
}
/*************************************************************************/
/*************************************************************************/
/* Format a string in a strftime()-like way, but heed the user's language
* setting for month and day names. The string stored in the buffer will
* always be null-terminated, even if the actual string was longer than the
* buffer size.
* Assumption: No month or day name has a length (including trailing null)
* greater than BUFSIZE.
*/
int strftime_lang(char *buf, int size, NS_User *u, int format, struct tm *tm)
{
int language = u && u->language ? u->language : NSDefLanguage;
char tmpbuf[BUFSIZE], buf2[BUFSIZE];
char *s;
int i, ret;
strncpy(tmpbuf, langtexts[language][format], sizeof(tmpbuf));
if ((s = langtexts[language][STRFTIME_DAYS_SHORT]) != NULL) {
for (i = 0; i < tm->tm_wday; i++)
s += strcspn(s, "\n")+1;
i = strcspn(s, "\n");
strncpy(buf2, s, i);
buf2[i] = 0;
strnrepl(tmpbuf, sizeof(tmpbuf), "%a", buf2);
}
if ((s = langtexts[language][STRFTIME_DAYS_LONG]) != NULL) {
for (i = 0; i < tm->tm_wday; i++)
s += strcspn(s, "\n")+1;
i = strcspn(s, "\n");
strncpy(buf2, s, i);
buf2[i] = 0;
strnrepl(tmpbuf, sizeof(tmpbuf), "%A", buf2);
}
if ((s = langtexts[language][STRFTIME_MONTHS_SHORT]) != NULL) {
for (i = 0; i < tm->tm_mon; i++)
s += strcspn(s, "\n")+1;
i = strcspn(s, "\n");
strncpy(buf2, s, i);
buf2[i] = 0;
strnrepl(tmpbuf, sizeof(tmpbuf), "%b", buf2);
}
if ((s = langtexts[language][STRFTIME_MONTHS_LONG]) != NULL) {
for (i = 0; i < tm->tm_mon; i++)
s += strcspn(s, "\n")+1;
i = strcspn(s, "\n");
strncpy(buf2, s, i);
buf2[i] = 0;
strnrepl(tmpbuf, sizeof(tmpbuf), "%B", buf2);
}
ret = strftime(buf, size, tmpbuf, tm);
if (ret == size)
buf[size-1] = 0;
return ret;
}
void notice_lang(const char *source, char *dest, int message, ...)
{
va_list args;
char buf[4096]; /* because messages can be really big */
char *s, *t, nick[55];
const char *fmt;
int lang = 0;
NS_User *tmp;
User *tmp1;
if (!dest)
return;
tmp = findregnick(dest);
if (!tmp) {
tmp1 = finduser(dest);
strcpy(nick, tmp1->nick);
lang = 0;
} else {
lang = tmp->language;
strcpy(nick, tmp->nick);
}
va_start(args, message);
fmt = getstring(lang, message);
if (!fmt)
return;
memset(buf, 0, 4096);
vsnprintf(buf, sizeof(buf), fmt, args);
s = buf;
while (*s) {
t = s;
s += strcspn(s, "\n");
if (*s)
*s++ = 0;
sts(":%s %s %s :%s", source, "NOTICE", nick, *t ? t : " ");
}
}
/* Like notice_lang(), but replace %S by the source. This is an ugly hack
* to simplify letting help messages display the name of the pseudoclient
* that's sending them.
*/
void notice_help(const char *source, char *dest, int message, ...)
{
va_list args;
char buf[4096], buf2[4096], outbuf[BUFSIZE];
char *s, *t, nick[55];
const char *fmt;
NS_User *tmp;
User *tmp1;
int lang = 0;
if (!dest)
return;
log("get %s", dest);
tmp = findregnick(dest);
if (!tmp) {
tmp1 = finduser(dest);
strcpy(nick, tmp1->nick);
} else {
lang = tmp->language;
strcpy(nick, tmp->nick);
}
log("get %s", nick);
va_start(args, message);
fmt = getstring(lang, message);
if (!fmt) {
return;
}
/* Some sprintf()'s eat %S or turn it into just S, so change all %S's
* into \1\1... we assume this doesn't occur anywhere else in the
* string. */
strncpy(buf2, fmt, sizeof(buf2));
strnrepl(buf2, sizeof(buf2), "%S", "\1\1");
vsnprintf(buf, sizeof(buf), buf2, args);
s = buf;
while (*s) {
t = s;
s += strcspn(s, "\n");
if (*s)
*s++ = 0;
strncpy(outbuf, t, sizeof(outbuf));
strnrepl(outbuf, sizeof(outbuf), "\1\1", source);
sts(":%s %s %s :%s", source, "NOTICE", nick, *outbuf ? outbuf : " ");
}
}

47
language.h Normal file
View file

@ -0,0 +1,47 @@
#define LANG_NAME 0
#define STRFTIME_DATE_TIME_FORMAT 1
#define STRFTIME_LONG_DATE_FORMAT 2
#define STRFTIME_SHORT_DATE_FORMAT 3
#define STRFTIME_DAYS_SHORT 4
#define STRFTIME_DAYS_LONG 5
#define STRFTIME_MONTHS_SHORT 6
#define STRFTIME_MONTHS_LONG 7
#define COMMA_SPACE 8
#define NICKSERV_HELP 9
#define NICKSERV_OPERHELP 10
#define NICKSERV_HELPOPERCOMMENT 11
#define NICKSERV_HELPSUSPEND 12
#define NICKSERV_HELPFORBID 13
#define NICKSERV_HELPGETPASS 14
#define NICKSERV_HELPSETPASS 15
#define NICKSERV_HELPVHOST 16
#define NICKSERV_HELP_REGISTER 17
#define NICKSERV_HELP_IDENTIFY 18
#define NICKSERV_HELP_INFO 19
#define NICKSERV_HELP_INFO_OPERS 20
#define NICKSERV_HELP_GHOST 21
#define NICKSERV_HELP_RECOVER 22
#define NICKSERV_HELP_OPERDROP 23
#define NICKSERV_HELP_DROP 24
#define NICKSERV_HELP_LOGOUT 25
#define NICKSERV_HELP_SET 26
#define NICKSERV_HELP_SET_PASSWORD 27
#define NICKSERV_HELP_SET_URL 28
#define NICKSERV_HELP_SET_EMAIL 29
#define NICKSERV_HELP_SET_ICQ 30
#define NICKSERV_HELP_SET_INFO 31
#define NICKSERV_HELP_SET_AIM 32
#define NICKSERV_HELP_SET_GREET 33
#define NICKSERV_HELP_SET_KILL 34
#define NICKSERV_HELP_SET_SECURE 35
#define NICKSERV_HELP_SET_PRIVATE 36
#define NICKSERV_HELP_SET_VHOST 37
#define NICKSERV_HELP_OPERCOMMENT 38
#define NICKSERV_HELP_SUSPEND 39
#define NICKSERV_HELP_FORBID 40
#define NICKSERV_HELP_GETPASS 41
#define NICKSERV_HELP_SETPASS 42
#define NICKSERV_HELP_VHOST 43
#define NICKSERV_HELP_ACCESS 44
#define NUM_STRINGS 45

48
makemask.todo Normal file
View file

@ -0,0 +1,48 @@
/* Given a user, return a mask that will most likely match any address the
* user will have from that location. For IP addresses, wildcards the
* appropriate subnet mask (e.g. 35.1.1.1 -> 35.*; 128.2.1.1 -> 128.2.*);
* for named addresses, wildcards the leftmost part of the name unless the
* name only contains two parts. If the username begins with a ~, delete
* it. The returned character string is malloc'd and should be free'd
* when done with.
*/
/*
char *create_mask(User *u)
{
char *mask, *s, *end;
int ulen = strlen(u->username);
/* Get us a buffer the size of the username plus hostname. The result
* will never be longer than this (and will often be shorter), thus we
* can use strcpy() and sprintf() safely.
*/
end = mask = smalloc(ulen + strlen(GetHost(u)) + 2);
end += sprintf(end, "%s%s@",
(ulen < (*(u->username) == '~' ? USERMAX+1 : USERMAX) ? "?" : ""),
(*(u->username) == '~' ? u->username+1 : u->username));
if (strspn(GetHost(u), "0123456789.") == strlen(GetHost(u))
&& (s = strchr(GetHost(u), '.'))
&& (s = strchr(s+1, '.'))
&& (s = strchr(s+1, '.'))
&& ( !strchr(s+1, '.'))) { /* IP addr */
s = sstrdup(GetHost(u));
*strrchr(s, '.') = 0;
sprintf(end, "%s.*", s);
free(s);
} else {
if ((s = strchr(GetHost(u), '.')) && strchr(s+1, '.')) {
s = sstrdup(strchr(GetHost(u), '.')-1);
*s = '*';
} else {
s = sstrdup(GetHost(u));
}
strcpy(end, s);
free(s);
}
return mask;
}
*/

439
match.c Normal file
View file

@ -0,0 +1,439 @@
/*
* Unreal Internet Relay Chat Daemon, src/match.c
* Copyright (C) 1990 Jarkko Oikarinen
*
* 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 <stdio.h>
#include <ctype.h>
/* ID_Copyright("(C) 1990 Jarkko Oikarinen"); */
/*
* Compare if a given string (name) matches the given
* mask (which can contain wild cards: '*' - match any
* number of chars, '?' - match any single character.
*
* return 0, if match
* 1, if no match
*/
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
typedef unsigned int u_int;
#ifndef USE_LOCALE
u_char touppertab[], tolowertab[];
#define tolowertab2 tolowertab
#endif
#define PRINT 1
#define CNTRL 2
#define ALPHA 4
#define PUNCT 8
#define DIGIT 16
#define SPACE 32
#define ALLOW 64
/*
* match()
* written by binary
*/
int match2(mask, name)
char *mask, *name;
{
u_char *m; /* why didn't the old one use registers */
u_char *n; /* because registers suck -- codemastr */
u_char cm;
u_char *wsn = NULL;
u_char *wsm;
m = (u_char *)mask;
cm = *m;
#ifndef USE_LOCALE
#define lc(x) tolowertab2[x] /* use mylowertab, because registers are FASTER */
#else /* maybe in the old 4mb hard drive days but not anymore -- codemastr */
#define lc(x) tolower(x)
#endif
n = (u_char *)name;
if (cm == '*')
{
if (m[1] == '\0') /* mask is just "*", so true */
return 0;
}
else if (cm != '?' && lc(cm) != lc(*n))
return 1; /* most likely first chars won't match */
else
{
m++;
n++;
}
cm = lc(*m);
wsm = (char *)NULL;
while (1)
{
if (cm == '*') /* found the * wildcard */
{
m++; /* go to next char of mask */
if (!*m) /* if at end of mask, */
return 0; /* function becomes true. */
while (*m == '*') /* while the char at m is "*" */
{
m++; /* go to next char of mask */
if (!*m) /* if at end of mask, */
return 0; /* function becomes true. */
}
cm = *m;
if (cm == '\\') /* don't do ? checking if a \ */
{
cm = *(++m); /* just skip this char, no ? checking */
}
else if (cm == '?') /* if it's a ? */
{
do
{
m++; /* go to the next char of both */
n++;
if (!*n) /* if end of test string... */
return (!*m ? 0 : 1); /* true if end of mask str, else false */
}
while (*m == '?'); /* while we have ?'s */
cm = *m;
if (!cm) /* last char of mask is ?, so it's true */
return 0;
}
cm = lc(cm);
while (lc(*n) != cm)
{ /* compare */
n++; /* go to next char of n */
if (!*n) /* if at end of n string */
return 1; /* function becomes false. */
}
wsm = m; /* mark after where wildcard found */
cm = lc(*(++m)); /* go to next mask char */
wsn = n; /* mark spot first char was found */
n++; /* go to next char of n */
continue;
}
if (cm == '?') /* found ? wildcard */
{
cm = lc(*(++m)); /* just skip and go to next */
n++;
if (!*n) /* return true if end of both, */
return (cm ? 1 : 0); /* false if end of test str only */
continue;
}
if (cm == '\\') /* next char will not be a wildcard. */
{ /* skip wild checking, don't continue */
cm = lc(*(++m));
n++;
}
/* Complicated to read, but to save CPU time. Every ounce counts. */
if (lc(*n) != cm) /* if the current chars don't equal, */
{
if (!wsm) /* if there was no * wildcard, */
return 1; /* function becomes false. */
n = wsn + 1; /* start on char after the one we found last */
m = wsm; /* set m to the spot after the "*" */
cm = lc(*m);
while (cm != lc(*n))
{ /* compare them */
n++; /* go to next char of n */
if (!*n) /* if we reached end of n string, */
return 1; /* function becomes false. */
}
wsn = n; /* mark spot first char was found */
}
if (!cm) /* cm == cn, so if !cm, then we've */
return 0; /* reached end of BOTH, so it matches */
m++; /* go to next mask char */
n++; /* go to next testing char */
cm = lc(*m); /* pointers are slower */
}
}
/*
* collapse a pattern string into minimal components.
* This particular version is "in place", so that it changes the pattern
* which is to be reduced to a "minimal" size.
*/
char *collapse(pattern)
char *pattern;
{
char *s;
char *s1;
char *t;
s = pattern;
/* if (BadPtr(pattern))
* return pattern;
*/
/*
* Collapse all \** into \*, \*[?]+\** into \*[?]+
*/
for (; *s; s++)
if (*s == '\\')
{
if (!*(s + 1))
break;
else
s++;
}
else if (*s == '*')
{
if (*(t = s1 = s + 1) == '*')
while (*t == '*')
t++;
else if (*t == '?')
for (t++, s1++; *t == '*' || *t == '?'; t++)
if (*t == '?')
*s1++ = *t;
while ((*s1++ = *t++))
;
}
return pattern;
}
/*
* Case insensitive comparison of two NULL terminated strings.
*
* returns 0, if s1 equal to s2
* <0, if s1 lexicographically less than s2
* >0, if s1 lexicographically greater than s2
*/
int smycmp(s1, s2)
char *s1;
char *s2;
{
u_char *str1;
u_char *str2;
int res;
str1 = (u_char *)s1;
str2 = (u_char *)s2;
while ((res = toupper(*str1) - toupper(*str2)) == 0)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return (res);
}
int myncmp(str1, str2, n)
char *str1;
char *str2;
int n;
{
u_char *s1;
u_char *s2;
int res;
s1 = (u_char *)str1;
s2 = (u_char *)str2;
while ((res = toupper(*s1) - toupper(*s2)) == 0)
{
s1++;
s2++;
n--;
if (n == 0 || (*s1 == '\0' && *s2 == '\0'))
return 0;
}
return (res);
}
#ifndef USE_LOCALE
u_char tolowertab[] = {
0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f,
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
'*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^',
'_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
u_char touppertab[] = {
0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f,
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
'*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
0x5f,
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~',
0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
u_char char_atribs[] = {
/* 0-7 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
/* 8-12 */ CNTRL, CNTRL | SPACE, CNTRL | SPACE, CNTRL | SPACE,
CNTRL | SPACE,
/* 13-15 */ CNTRL | SPACE, CNTRL, CNTRL,
/* 16-23 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
/* 24-31 */ CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL, CNTRL,
/* space */ PRINT | SPACE,
/* !"#$%&'( */ PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT, PRINT,
/* )*+,-./ */ PRINT, PRINT, PRINT, PRINT, PRINT | ALLOW, PRINT | ALLOW,
PRINT,
/* 012 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
PRINT | DIGIT | ALLOW,
/* 345 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
PRINT | DIGIT | ALLOW,
/* 678 */ PRINT | DIGIT | ALLOW, PRINT | DIGIT | ALLOW,
PRINT | DIGIT | ALLOW,
/* 9:; */ PRINT | DIGIT | ALLOW, PRINT, PRINT,
/* <=>? */ PRINT, PRINT, PRINT, PRINT,
/* @ */ PRINT,
/* ABC */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* DEF */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* GHI */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* JKL */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* MNO */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* PQR */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* STU */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* VWX */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* YZ[ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA,
/* \]^ */ PRINT | ALPHA, PRINT | ALPHA, PRINT | ALPHA,
/* _` */ PRINT | ALLOW, PRINT,
/* abc */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* def */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* ghi */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* jkl */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* mno */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* pqr */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* stu */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* vwx */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW,
PRINT | ALPHA | ALLOW,
/* yz{ */ PRINT | ALPHA | ALLOW, PRINT | ALPHA | ALLOW, PRINT | ALPHA,
/* |}~ */ PRINT | ALPHA, PRINT | ALPHA, PRINT | ALPHA,
/* del */ 0,
/* 80-8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 90-9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* a0-af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* b0-bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* c0-cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* d0-df */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* e0-ef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* f0-ff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Old match() */
int _match(char *mask, char *name) {
return match2(mask,name);
}
/* Old match() plus some optimizations from bahamut */
int match(char *mask, char *name) {
if (mask[0] == '*' && mask[1] == '!') {
mask += 2;
while (*name != '!' && *name)
name++;
if (!*name)
return 1;
name++;
}
if (mask[0] == '*' && mask[1] == '@') {
mask += 2;
while (*name != '@' && *name)
name++;
if (!*name)
return 1;
name++;
}
return match2(mask,name);
}

33
new.c Normal file
View file

@ -0,0 +1,33 @@
/*************************************************************************/
/* strnrepl: Replace occurrences of `old' with `new' in string `s'. Stop
* replacing if a replacement would cause the string to exceed
* `size' bytes (including the null terminator). Return the
* string.
*/
char *strnrepl(char *s, int32 size, const char *old, const char *new)
{
char *ptr = s;
int32 left = strlen(s);
int32 avail = size - (left+1);
int32 oldlen = strlen(old);
int32 newlen = strlen(new);
int32 diff = newlen - oldlen;
while (left >= oldlen) {
if (strncmp(ptr, old, oldlen) != 0) {
left--;
ptr++;
continue;
}
if (diff > avail)
break;
if (diff != 0)
memmove(ptr+oldlen+diff, ptr+oldlen, left+1);
strncpy(ptr, new, newlen);
ptr += newlen;
left -= oldlen;
}
return s;
}

1426
nickserv.c Normal file

File diff suppressed because it is too large Load diff

214
options.h Normal file
View file

@ -0,0 +1,214 @@
/* NetStats - IRC Statistical Services
** Copyright (c) 1999 Adam Rutter, Justin Hammond
** http://codeworks.kamserve.com
*
** Based from GeoStats 1.1.0 by Johnathan George net@lite.net
*
** NetStats CVS Identification
** $Id: options.h,v 1.1 2002/02/27 12:21:28 fishwaldo Exp $
*/
/* this is the config file for services.
** anything that is configurable should be set via this file for now
** until we have the config interface coded and into the core neostats software
**
** I'll try to document each setting and what it does
*/
#ifndef M_OPTIONS
#define M_OPTIONS
/* this setting is the maxium no of registered online nicks at any one tiem
** if more users than this setting identify
** god knows what will happen to Neostats (Most likely it will core
**
** just setting this to a high value is not a good idea if you dont need it
** its going to increase memory usage, and also probably slow down NeoStats
** when it does its Database Sync's, as it will have to go through each record, even
** if its not being used
*/
#define NS_USER_LIST 1024
/* This is the Maxium number of timers that services can activate at any one time
** things that use timers at the moment are
** - when a registered nick sign's on, and its kill option is active, but its not in a access list
** - When nicks are changed (upto 2 timers as well!)
**
** again, setting this high, might lag out NeoStats, so be carefull with it.
*/
#define MAX_SVS_TIMERS 255
/* this defines the databaes Location.
** you can put it anywhere you want, if Services can't find a database, it will
** automatically create the database for you
** if the database gets corrupted you can use the Berkeley database recovery tools
** on it
*/
#define NSDBASE "data/nsdata.db"
/* how long do users have to ident to nickserv before their nick is changed.
** this is set if kill is active for that nick (kill isn't a good word, read the online help about set kill.
** This relates to timers above, so setting this to a long time, and having lots of users pending "identification"
** can mean you run out of timer slots.. be carefull
*/
#define NICK_IDENT_TIME 30
/* how long does a enforcer stay online
** if a Enforcer Nick joins the network to stop people regaining the nickname
** how long does it stay online?
** again, relates to timers above, so set this carefully
*/
#define ENFORCER_HOLD_TIME 30
/* how often to check registered nick records that need to be synced to the database
** each online nick has a "lastchanged" field.
** every period you set here (Seconds) Services goes through the list of nicks
** looking for nicks that need to have the database synced (for instance, if they update the
** set interface or so on.
**
** Setting this too low will lag out NeoStats, Setting it too high might mean if you have a lot of nicks
** that need to be synced, NeoStats gets lagged out for a while, as the database is synced
** I suggest around 5-10 minutes for most networks
** if Services thinks its taking too long to sync the database
** it will broadcast a message into the services channel, you should change it then
*/
#define DB_SYNC_TIME 30
/* how long can user have their info line (viewable via /nickserv info <nick>)
** some networks prefer to limit how long it can be
** but you can't go over 100,
** if you do, it will still be limited to 100, as thats the database field size
*/
#define NICK_INFO_LEN 100 /* is the max */
/* No of bad passwords before kill'ing the user
** if the number of bad passwords is this, then the user is killed from the network
*/
#define NO_BAD_PASS 3
/* Default Kill setting for New nicks
** what default setting should new registered nicks have?
** setting this to 1 means that kill is active
** setting to 0 means that kill is not active
** setting to anything higher than 1 will work as well, but wont change the function of it
*/
#define DEF_KILL 1
/* Default secure settings for new nicks
** what default setting shoudl new registered nicks have?
** setting this to 1 means secure is active
** setting to 0 means its not active
*/
#define DEF_SECURE 0
/* default private setting for new nicks
** what default setting should new registered nicks have?
** setting this to 1 means private is active
** setting to 0 means its not active
*/
#define DEF_PRIVATE 0
/* What level does a user have to be to set the opercomment
** You should look at the NeoStats core file users.c to figure out levels
** Default, is 50 (Global Oper)
*/
#define OPERCOMMENT_SET_ACCESS_LEVEL 50
/* what level does a user have to be to see the opercomment
** you should look at the Neostats core file users.c to figure out levels
** default, is 40 (LocalOp)
*/
#define OPERCOMMENT_SEE_ACCESS_LEVEL 40
/* what level is required to drop a nickname
** you should look at the Neostats core file users.c to figure out levels
** default, is 100 (Service Admins)
*/
#define CAN_DROP_NICK_LEVEL 100
/* what level is reqiured to suspend a nickname
** you should look at the neostats core file users.c to figure out levels
** default is 100 (service admins)
*/
#define OPERSUSPEND_SET_ACCESS_LEVEL 100
/* what level is required to forbid a nickname
** default is 100 (Service Admins)
*/
#define OPERFORBID_SET_ACCESS_LEVEL 100
/* should we enable getpass for nickserv, chanset et al?
** value of 1 says yes
** value of 0 says no
*/
#define ENABLE_GETPASS 1
/* if ENABLE_GETPASS is 1 above, then what level to we require for
** operators to use this command?
** default is 100 (service admins)
*/
#define GETPASS_ACCESS_LEVEL 100
/* should we enable setpass for nickserv, chanserv et al?
** value of 1 says yes
** value of 0 says no
*/
#define ENABLE_SETPASS 1
/* if ENABLE_SETPASS is 1 above, then what level to we require for
** operators to use this command?
** default is 100 (service admins)
*/
#define SETPASS_ACCESS_LEVEL 100
/* Vhost Support.
** 3 settings here for networks, this is how it works
** if set to 0, then vhost is disabled
** if set to 1, then users are allowed to set their own vhost
** if set to 2, then users get vhost on identify/accesslist match, but can not change, only opers can change
*/
#define ENABLE_VHOST 2
/* if ENABLE_VHOST is set to 2 then what access
** level is required to set a users Vhost?
** default is 100 (Service Admins)
** if ENABLE_VHOST is 1 then this is what level a admin can change the vhost
** if ENABLE_VHOST is 0, this has no effect
*/
#define SETVHOST_ACCESS_LEVEL 100
#endif

164
services.h Normal file
View file

@ -0,0 +1,164 @@
/* NetStats - IRC Statistical Services
** Copyright (c) 1999 Adam Rutter, Justin Hammond
** http://codeworks.kamserve.com
*
** Based from GeoStats 1.1.0 by Johnathan George net@lite.net
*
** NetStats CVS Identification
** $Id: services.h,v 1.1 2002/02/27 12:21:29 fishwaldo Exp $
*/
#ifndef M_SERVICES
#define M_SERVICES
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/time.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <db.h>
#include "stats.h"
#include "options.h"
DB *dbp;
char *s_NickServ;
/* used to determine which nicks have changed, and need sync'ing */
int last_db_sync;
char ns_forbid_list[4096];
typedef struct ns_user NS_User;
NS_User *nsuserlist[NS_USER_LIST];
struct ns_user {
NS_User *prev;
NS_User *next;
long hash;
char nick[15];
char pass[15];
int language;
char url[100];
char email[100];
int icq;
char aim[100];
int kill;
int secure;
int private;
int onlineflags;
int lastchange;
char acl[1024];
struct {
char usermask:1;
char email:1;
char quit:1;
} hide;
int registered_at;
int last_seen_at;
int flags;
char last_mask[100];
char vhost[100];
char last_quit[200];
char info[100];
char greet[100];
char opercomment[255];
};
typedef struct svs_timers Svs_Timers;
Svs_Timers *serv_timers[MAX_SVS_TIMERS];
struct svs_timers {
Svs_Timers *prev;
Svs_Timers *next;
long hash;
char varibles[255];
char timername[255];
int interval;
time_t lastrun;
int (*function)();
};
struct ns_access {
struct ns_access *prev;
struct ns_access *next;
char hostmask[100];
};
typedef struct ns_access NS_AccessList;
struct ns_links {
struct ns_links *prev;
struct ns_links *next;
NS_User *user;
char nick[15];
};
typedef struct ns_links NS_LinkList;
int NSDefLanguage;
int match2(char *, char *);
void init_regnick_hash();
NS_User *new_regnick(char *, int create);
NS_User *findregnick(char *);
void del_regnick(char *);
NS_User *lookup_regnick(char *);
int ns_new_user(User *);
int ns_bye_user(User *);
int ns_nickchange_user(char *);
Svs_Timers *new_svs_timers(char *);
void sync_nick_to_db(NS_User *);
void del_nick_from_db(char *);
char *makemask(User *u, int vhost);
void init_nick_forbid_list();
void save_nick_forbid_list();
int is_forbidden(char *);
char *strnrepl(char *s, int size, const char *old, const char *new);
void lang_init();
/* these functions are in the core neostats, and are needed for internal functions */
void Usr_Kill(char *, char *);
void Usr_Nick(char *, char *);
int get_dl_handle(char *);
/* this is just stuff we need */
#define getstring(na,index) \
(langtexts[((na)&&((NS_User*)na)->language?((NS_User*)na)->language:NSDefLanguage)][(index)])
/* Flags for NS_User->onlineflags */
#define NSFL_IDENTIFED 0x0001 /* user has Identified */
#define NSFL_BADPASS 0x0002 /* User specified a badpass */
#define NSFL_ACCESSMATCH 0x0004 /* user has been matched against the accesslist */
#define NSFL_ENFORCED 0x0008 /* this is a Enforcer.. ie, not a real user */
#define NSFL_SUSPEND 0x0010 /* nickname is suspended */
#define NUM_LANGS 10
#define LANG_EN_US 0 /* United States English */
#define USED_LANGS 6 /* Number of languages provided */
#define DEF_LANGUAGE LANG_EN_US
#endif

191
servicescore.c Normal file
View file

@ -0,0 +1,191 @@
/* NeoStats - IRC Statistical Services Copryight (c) 1999-2001 NeoStats Group.
*
** Module: LoveServ
** Version: 1.0
*/
/* TODO STUFF
** Delete or add as u do stuff
*/
#include <stdio.h>
#include <db.h>
#include "dl.h"
#include "stats.h"
#include "services.h"
const char servicesversion_date[] = __DATE__;
const char servicesversion_time[] = __TIME__;
Module_Info my_info[] = { {
"Services",
"Services for Neostats",
"0.1.4A"
} };
int new_m_version(char *av, char *tmp) {
sts(":%s 351 %s :Module NickServ Loaded, Version %s %s %s",me.name, av,my_info[0].module_version,servicesversion_date,servicesversion_time);
return 0;
}
Functions my_fn_list[] = {
{ "VERSION", new_m_version, 1 },
{ NULL, NULL, 0 }
};
int Online(Server *data) {
if (init_bot(s_NickServ,"nick",me.name,"Network Nick Service", "+xd", my_info[0].module_name) == -1 ) {
/* Nick was in use!!!! */
s_NickServ = strcat(s_NickServ, "_");
init_bot(s_NickServ,"nick",me.name,"Network Nick Service", "+xd", my_info[0].module_name);
}
/* TODO: don't use constants here */
add_mod_timer("runsvstimers", "Services", "Services", 1);
add_mod_timer("sync_changed_nicks_to_db", "DB_Sync", "Services", DB_SYNC_TIME);
return 1;
};
EventFnList my_event_list[] = {
{ "ONLINE", (void *)Online},
{ "SIGNON", (void *)ns_new_user},
{ "SIGNOFF", (void *)ns_bye_user},
{ "KILL", (void *)ns_bye_user},
{ "NICK_CHANGE", (void *)ns_nickchange_user},
{ NULL, NULL}
};
Module_Info *__module_get_info() {
return my_info;
};
Functions *__module_get_functions() {
return my_fn_list;
};
EventFnList *__module_get_events() {
return my_event_list;
};
void _init() {
int ret;
s_NickServ = "NS";
ret = db_create(&dbp, NULL,0);
if (ret != 0) {
log("nickserv dbcreate error");
return;
}
ret = dbp->open(dbp, NSDBASE, NULL, DB_HASH, 0, 0644);
if (ret == ENOENT) {
/* db doesn't exist */
log("nickserv Database Doesn't Exist, Creating it!");
ret = dbp->open(dbp, NSDBASE, NULL, DB_HASH, DB_CREATE, 0644);
}
if (ret != 0) {
log("nickserv dbopen error %s", db_strerror(ret));
return;
}
log("NickServ Loaded");
init_regnick_hash();
/* load the nickserv forbidden list */
init_nick_forbid_list();
lang_init();
}
void _fini() {
int ret;
if (dbp != NULL) {
if ((ret = dbp->close(dbp, 0) != 0)) {
sts(":%s GLOBOPS :NickServ DB Close Error: %s", me.name, db_strerror(ret));
};
}
log("NickServ Unloaded");
};
char *makemask(User *u, int vhost) {
char userid[15], hostmask[255], *temp;
int i,j=0;
bzero(userid, 15);
bzero(hostmask, 255);
strncpy(userid, u->username, strlen(u->username));
if ((strncmp(userid, "~", 1) ==0)) {
userid[0] = '*';
}
/* TODO: handle IP address and hostnames */
/* this only does hostnames... */
if (vhost == 1) {
for (i=0; i<strlen(u->vhost); i++) {
if (!j && u->vhost[i] == '.') {
j = i+1;
} else if (j) {
hostmask[i-j+1] = u->vhost[i];
}
}
} else {
for (i=0; i<strlen(u->hostname); i++) {
if (!j && u->hostname[i] == '.') {
j = i+1;
} else if (j) {
hostmask[i-j+1] = u->hostname[i];
}
}
}
hostmask[0] = '*';
temp = malloc(sizeof(userid) + sizeof(hostmask) +1);
snprintf(temp, strlen(userid) + strlen(hostmask) +2 , "%s@%s", userid, hostmask);
return (char *)temp;
}
/*************************************************************************/
/* strnrepl: Replace occurrences of `old' with `new' in string `s'. Stop
* replacing if a replacement would cause the string to exceed
* `size' bytes (including the null terminator). Return the
* string.
*/
char *strnrepl(char *s, int size, const char *old, const char *new)
{
char *ptr = s;
int left = strlen(s);
int avail = size - (left+1);
int oldlen = strlen(old);
int newlen = strlen(new);
int diff = newlen - oldlen;
while (left >= oldlen) {
if (strncmp(ptr, old, oldlen) != 0) {
left--;
ptr++;
continue;
}
if (diff > avail)
break;
if (diff != 0)
memmove(ptr+oldlen+diff, ptr+oldlen, left+1);
strncpy(ptr, new, newlen);
ptr += newlen;
left -= oldlen;
}
return s;
}

73
svc_help.c Normal file
View file

@ -0,0 +1,73 @@
/* NeoStats - IRC Statistical Services Copryight (c) 1999-2001 NeoStats Group.
*
** Module: Services
*/
#include "language.h"
#include "services.h"
#include "stats.h"
struct int_help {
char *name;
int function;
int level;
};
typedef struct int_help SVC_help_ns;
const SVC_help_ns svc_ns_help_index[] = {
/* help, help function, level */
{"HELP", NICKSERV_HELP, 0},
{"HELP", NICKSERV_OPERHELP, 40},
{"HELP", NICKSERV_HELPOPERCOMMENT, OPERCOMMENT_SET_ACCESS_LEVEL},
{"HELP", NICKSERV_HELPSUSPEND, OPERSUSPEND_SET_ACCESS_LEVEL},
{"HELP", NICKSERV_HELPFORBID, OPERFORBID_SET_ACCESS_LEVEL},
{"HELP", NICKSERV_HELPGETPASS, GETPASS_ACCESS_LEVEL},
{"HELP", NICKSERV_HELPSETPASS, SETPASS_ACCESS_LEVEL},
{"HELP", NICKSERV_HELPVHOST, SETVHOST_ACCESS_LEVEL},
{"REGISTER", NICKSERV_HELP_REGISTER, 0},
{"IDENTIFY", NICKSERV_HELP_IDENTIFY, 0},
{"INFO", NICKSERV_HELP_INFO, 0},
{"INFO", NICKSERV_HELP_INFO_OPERS, 40},
{"GHOST", NICKSERV_HELP_GHOST, 0},
{"RECOVER", NICKSERV_HELP_RECOVER, 0},
{"DROP", NICKSERV_HELP_OPERDROP, CAN_DROP_NICK_LEVEL},
{"DROP", NICKSERV_HELP_DROP, 0},
{"LOGOUT", NICKSERV_HELP_LOGOUT, 0},
{"SET", NICKSERV_HELP_SET, 0},
{"SET PASSWORD",NICKSERV_HELP_SET_PASSWORD, 0},
{"SET URL", NICKSERV_HELP_SET_URL, 0},
{"SET EMAIL", NICKSERV_HELP_SET_EMAIL, 0},
{"SET ICQ", NICKSERV_HELP_SET_ICQ, 0},
{"SET INFO", NICKSERV_HELP_SET_INFO, 0},
{"SET AIM", NICKSERV_HELP_SET_AIM, 0},
{"SET GREET", NICKSERV_HELP_SET_GREET, 0},
{"SET KILL", NICKSERV_HELP_SET_KILL, 0},
{"SET SECURE", NICKSERV_HELP_SET_SECURE, 0},
{"SET PRIVATE", NICKSERV_HELP_SET_PRIVATE, 0},
{"SET VHOST", NICKSERV_HELP_SET_VHOST, 0},
{"OPERCOMMENT", NICKSERV_HELP_OPERCOMMENT, OPERCOMMENT_SET_ACCESS_LEVEL},
{"SUSPEND", NICKSERV_HELP_SUSPEND, OPERSUSPEND_SET_ACCESS_LEVEL},
{"FORBID", NICKSERV_HELP_FORBID, OPERFORBID_SET_ACCESS_LEVEL},
{"GETPASS", NICKSERV_HELP_GETPASS, GETPASS_ACCESS_LEVEL},
{"SETPASS", NICKSERV_HELP_SETPASS, SETPASS_ACCESS_LEVEL},
{"VHOST", NICKSERV_HELP_VHOST, SETVHOST_ACCESS_LEVEL},
{"ACCESS", NICKSERV_HELP_ACCESS, 0},
{NULL, NULL, 0}
};
extern void send_help(User *u, char *line) {
int i;
if (!line) {
line = smalloc(5);
strcpy(line, "HELP");
}
for (i = 0; i < ((sizeof(svc_ns_help_index) / sizeof(svc_ns_help_index[0])) -1); i++) {
log("%s - %s %d", svc_ns_help_index[i].name, line, strcasecmp(svc_ns_help_index[i].name, line));
if (!strcasecmp(svc_ns_help_index[i].name, line)) {
if (UserLevel(u) >= svc_ns_help_index[i].level) {
notice_help(s_NickServ, u->nick, svc_ns_help_index[i].function);
}
}
}
}