Add files via upload

This commit is contained in:
Koragg 2019-01-23 09:32:56 +01:00 committed by GitHub
parent 580cb48284
commit 9a5d7a4e1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 63417 additions and 0 deletions

50
lang/Makefile Normal file
View File

@ -0,0 +1,50 @@
# Makefile for language module
include ../Makefile.inc
LANGOBJS = de en_us es fr hu ja_euc ja_sjis nl ru tr
LANGSRCS = $(LANGOBJS:%=%.l)
LANGCOMP = ./langcomp
#LANGCOMP = ./langcomp -w
all: $(LANGOBJS)
install: all
mkdir -p "$(INSTALL_PREFIX)$(DATDEST)/languages"
cp $(LANGOBJS) "$(INSTALL_PREFIX)$(DATDEST)/languages"
clean:
rm -f $(LANGOBJS) langcomp
spotless: clean
rm -f langstrs.h
$(LANGOBJS): %: %.l langcomp index
$(LANGCOMP) $<
ja_jis.l: ja_euc.l jconv.pl
perl jconv.pl -jis <ja_euc.l >$@
ja_sjis.l: ja_euc.l jconv.pl
perl jconv.pl -sjis <ja_euc.l >$@
langcomp: langcomp.c
$(CC) $(CFLAGS) langcomp.c -o $@
langstrs.h: index make-langstrs-h.pl
perl make-langstrs-h.pl >$@.new
@if cmp $@ $@.new >/dev/null 2>&1 ; then \
echo "$@ unchanged" ; \
rm -f $@.new ; \
else \
mv -f $@.new $@ ; \
fi
index: en_us.l
grep '^[A-Z]' <en_us.l >$@

4846
lang/de.l Normal file

File diff suppressed because it is too large Load Diff

5184
lang/en_us.l Normal file

File diff suppressed because it is too large Load Diff

5181
lang/es.l Normal file

File diff suppressed because it is too large Load Diff

5048
lang/fr.l Normal file

File diff suppressed because it is too large Load Diff

5204
lang/hu.l Normal file

File diff suppressed because it is too large Load Diff

1240
lang/index Normal file

File diff suppressed because it is too large Load Diff

4818
lang/ja_euc.l Normal file

File diff suppressed because it is too large Load Diff

4818
lang/ja_sjis.l Normal file

File diff suppressed because it is too large Load Diff

33
lang/jconv.pl Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/perl
binmode STDIN;
binmode STDOUT;
undef $/;
$text = <STDIN>;
if ($ARGV[0] eq "-jis") {
$text =~ s/EUC/JIS/g;
$text =~ s/euc-jp/iso-2022-jp/g;
$text =~ s#([\241-\376])([\241-\376])#
"\033\$B".pack("cc",ord($1)&127,ord($2)&127)."\033(B"#eg;
# The language name (the only thing before the STRFTIME_* strings)
# shouldn't have its %'s escaped; all other strings should, because
# they go through sprintf().
$pos = index($text, "STRFTIME");
$pos = length($text) if $pos == 0;
$t1 = substr($text, 0, $pos);
$t2 = substr($text, $pos, length($text)-$pos);
$t2 =~ s#(\033\$B.)%(\033\(B)#\1%%\2#g;
$t2 =~ s#(\033\$B)%(.\033\(B)#\1%%\2#g;
$text = $t1 . $t2;
$text =~ s#\033\(B\033\$B##g;
} elsif ($ARGV[0] eq "-sjis") {
$text =~ s/EUC/SJIS/g;
$text =~ s/euc-jp/shift_jis/g;
$text =~ s#([\241-\376])([\241-\376])#
$x = 0201+(ord($1)-0241)/2;
$y = 0100+(ord($2)-0241)+((ord($1)-0241)%2)*94;
$x += 0100 if $x >= 0240;
$y++ if $y >= 0177;
pack("cc",$x,$y)#eg;
}
print $text;

309
lang/langcomp.c Normal file
View File

@ -0,0 +1,309 @@
/* Compiler for language definition files.
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
/*
* 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 "#"--note that inline comments are not allowed!)
* 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>
#include <unistd.h>
/* CR/LF values--used instead of '\r' and '\n' to avoid platform-dependent
* messiness */
#define CR ((char)13)
#define LF ((char)10)
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. */
static int read_index_file(void)
{
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] == LF)
buf[strlen(buf)-1] = 0;
if (buf[strlen(buf)-1] == CR)
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. */
static 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. */
static char *readline(FILE *f)
{
static char buf[1024];
char *s;
do {
if (!(fgets(buf, sizeof(buf), f)))
return NULL;
linenum++;
} while (*buf == '#' || *buf == CR || *buf == LF);
s = buf + strlen(buf)-1;
if (*s == LF)
*s-- = 0;
if (*s == CR)
*s = 0;
return buf;
}
/*************************************************************************/
/* Write a 32-bit value to a file in big-endian order. Returns 0 on
* success, -1 on error.
*/
static int fput32(long val, FILE *f)
{
if (fputc(val>>24, f) == EOF ||
fputc(val>>16, f) == EOF ||
fputc(val>> 8, f) == EOF ||
fputc(val , f) == EOF
) {
return -1;
} else {
return 0;
}
}
/*************************************************************************/
int main(int ac, char **av)
{
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 maxerr = 50; /* Max errors before we bail out */
long pos, totalsize;
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 = readline(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;
}
}
}
fclose(in);
if (retval != 0) {
if (maxerr == 0)
fprintf(stderr, "%s:%d: Too many errors!\n", filename, linenum);
fclose(out);
unlink(outfile);
return retval;
}
totalsize = 0;
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])
totalsize += strlen(strings[i]) + 1;
} else if (warn) {
fprintf(stderr, "%s: String `%s' missing\n", filename,
stringnames[i]);
}
}
if (fput32(numstrings, out) < 0 || fput32(totalsize, out) < 0) {
perror("fwrite()");
retval = 1;
}
for (i = 0; i < numstrings && retval == 0; i++) {
if (strings[i] && *strings[i]) {
if (fwrite(strings[i], strlen(strings[i])+1, 1, out) != 1) {
perror("fwrite()");
retval = 1;
}
}
}
pos = 0;
for (i = 0; i < numstrings && retval == 0; i++) {
if (strings[i] && *strings[i]) {
if (fput32(pos, out) < 0) {
perror("fwrite()");
retval = 1;
}
pos += strlen(strings[i]) + 1;
} else {
if (fput32(-1, out) < 0) {
perror("fwrite()");
retval = 1;
}
}
}
if (fclose(out) == EOF && retval == 0) {
perror("fclose()");
retval = 1;
}
if (retval)
unlink(outfile);
return retval;
}
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

2487
lang/langstrs.h Normal file

File diff suppressed because it is too large Load Diff

22
lang/make-langstrs-h.pl Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
print STDERR "Generating langstrs.h... ";
$i = 0;
@list = ();
open F, "<index" or die "index: $!\n";
while (<F>) {
chop;
push @list, $_;
printf "#define %-32s %d\n", $_, $i++;
}
close F;
print "\n#define NUM_BASE_STRINGS $i\n";
print "\n#ifdef LANGSTR_ARRAY\n";
print "static const char * const base_langstrs[] = {\n";
foreach $s (@list) {
print " \"$s\",\n";
}
print "};\n#endif\n";
print STDERR "$i strings\n";

5350
lang/nl.l Normal file

File diff suppressed because it is too large Load Diff

4806
lang/ru.l Normal file

File diff suppressed because it is too large Load Diff

4998
lang/tr.l Normal file

File diff suppressed because it is too large Load Diff

107
tools/Makefile Normal file
View File

@ -0,0 +1,107 @@
# Makefile for Services tools directory.
#
# IRC Services is copyright (c) 1996-2009 Andrew Church.
# E-mail: <achurch@achurch.org>
# Parts written by Andrew Kempe and others.
# This program is free but copyrighted software; see the file GPL.txt for
# details.
include ../Makefile.inc
TOPDIR = ..
CFLAGS_CONVERT_DB = $(CFLAGS) -I$(TOPDIR) -DCONVERT_DB
###########################################################################
ifneq ($(VSNPRINTF_O),)
CONVERT_DB_VSNPRINTF_O = $(TOPDIR)/vsnprintf.o
endif
# These aren't "modules" in the real sense; this is just a convenient way
# to list the object files that handle each database format.
CONVERT_DB_MODULES = \
convert-cygnus.o \
convert-epona.o \
convert-hybserv.o \
convert-magick.o \
convert-ptlink.o \
convert-sirv.o \
convert-trircd.o \
convert-ver8.o
CONVERT_DB_OBJS = convert-db.o $(CONVERT_DB_MODULES) \
fileutil-x.o misc-x.o xml-export-x.o $(TOPDIR)/compat.o \
$(CONVERT_DB_VSNPRINTF_O)
.c.o:
$(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@
###########################################################################
.PHONY: all install clean spotless
all: convert-db$(EXE_SUFFIX) $(PROGRAM)-chk
install:
$(INSTALL_EXE) convert-db$(EXE_SUFFIX) "$(INSTALL_PREFIX)$(DATDEST)/convert-db$(EXE_SUFFIX)"
$(INSTALL_EXE) $(PROGRAM)-chk "$(INSTALL_PREFIX)$(BINDEST)/$(PROGRAM)-chk"
clean:
rm -f *.o convert-db$(EXE_SUFFIX) $(PROGRAM)-chk
spotless: clean
###########################################################################
convert-db$(EXE_SUFFIX): $(CONVERT_DB_OBJS)
$(CC) $(LFLAGS) $(CONVERT_DB_OBJS) $(LIBS) -o $@
$(PROGRAM)-chk: ircservices-chk.in Makefile $(TOPDIR)/Makefile.inc
PROGRAM=`echo "$(PROGRAM)" | sed 's,/,\\\\/,g'` ; \
BINDEST=`echo "$(BINDEST)" | sed 's,/,\\\\/,g'` ; \
DATDEST=`echo "$(DATDEST)" | sed 's,/,\\\\/,g'` ; \
sed -e "s/@BINDEST@/$$BINDEST/g" -e "s/@DATDEST@/$$DATDEST/g" -e "s/@PROGRAM@/$$PROGRAM/g" <ircservices-chk.in >$(PROGRAM)-chk
chmod a+x $(PROGRAM)-chk
$(CONVERT_DB_OBJS): Makefile $(TOPDIR)/Makefile.inc convert-db.h \
$(TOPDIR)/services.h $(TOPDIR)/encrypt.h \
$(TOPDIR)/modules/database/fileutil.h \
$(TOPDIR)/modules/nickserv/nickserv.h \
$(TOPDIR)/modules/chanserv/chanserv.h \
$(TOPDIR)/modules/memoserv/memoserv.h \
$(TOPDIR)/modules/operserv/operserv.h \
$(TOPDIR)/modules/operserv/maskdata.h \
$(TOPDIR)/modules/operserv/news.h \
$(TOPDIR)/modules/statserv/statserv.h
convert-db.o: convert-db.c $(TOPDIR)/language.h $(TOPDIR)/modules/misc/xml.h \
$(TOPDIR)/modules/nickserv/util.c $(TOPDIR)/modules/chanserv/util.c
convert-cygnus.o: convert-cygnus.c
convert-epona.o: convert-epona.c
convert-magick.o: convert-magick.c
convert-ptlink.o: convert-ptlink.c $(TOPDIR)/language.h
convert-sirv.o: convert-sirv.c
convert-trircd.o: convert-trircd.c
convert-ver8.o: convert-ver8.c
fileutil-x.o: $(TOPDIR)/modules/database/fileutil.c $(TOPDIR)/services.h \
$(TOPDIR)/modules/database/fileutil.h
$(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@
misc-x.o: $(TOPDIR)/misc.c $(TOPDIR)/services.h
$(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@
xml-export-x.o: $(TOPDIR)/modules/misc/xml-export.c $(TOPDIR)/services.h \
$(TOPDIR)/language.h \
$(TOPDIR)/modules/nickserv/nickserv.h \
$(TOPDIR)/modules/chanserv/chanserv.h \
$(TOPDIR)/modules/memoserv/memoserv.h \
$(TOPDIR)/modules/operserv/operserv.h \
$(TOPDIR)/modules/operserv/maskdata.h \
$(TOPDIR)/modules/operserv/news.h \
$(TOPDIR)/modules/statserv/statserv.h
$(CC) $(CFLAGS_CONVERT_DB) -c $< -o $@
$(TOPDIR)/compat.o $(TOPDIR)/misc.o $(TOPDIR)/vsnprintf.o:
$(MAKE) -C $(TOPDIR) $(notdir $@)
###########################################################################

1449
tools/convert-cygnus.c Normal file

File diff suppressed because it is too large Load Diff

943
tools/convert-db.c Normal file
View File

@ -0,0 +1,943 @@
/* Convert other programs' databases to XML.
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#define CONVERT_DB_MAIN
#define STANDALONE_NICKSERV
#define STANDALONE_CHANSERV
#include "convert-db.h"
#include "language.h"
#include "modules/misc/xml.h"
/*************************************************************************/
/* Data read in. */
NickGroupInfo *ngi_list;
NickInfo *ni_list;
ChannelInfo *ci_list;
NewsItem *news_list;
MaskData *md_list[256];
ServerStats *ss_list;
int32 maxusercnt;
time_t maxusertime;
Password supass;
int no_supass = 1;
/* Symbols needed for core's misc.c. */
char **RejectEmail = NULL;
int RejectEmail_count = 0;
/*************************************************************************/
/* NULL-terminated list of supported database types. */
extern DBTypeInfo ALL_DB_TYPES();
static DBTypeInfo *dbtypes[] = {
ALL_DB_TYPES(&),
NULL
};
/*************************************************************************/
/*************************** Exported routines ***************************/
/*************************************************************************/
/* Safe memory allocation and string duplication (from memory.c). */
void *smalloc(long size)
{
void *ptr;
if (!size)
size = 1;
ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return ptr;
}
void *scalloc(long els, long elsize)
{
void *ptr;
if (!(els*elsize))
els = elsize = 1;
ptr = calloc(els, elsize);
if (!ptr) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return ptr;
}
void *srealloc(void *ptr, long size)
{
if (!size)
size = 1;
ptr = realloc(ptr, size);
if (!ptr) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return ptr;
}
char *sstrdup(const char *s)
{
int len = strlen(s)+1;
char *d = smalloc(len);
memcpy(d, s, len);
return d;
}
/*************************************************************************/
/* Initialize or clear a Password structure (from encrypt.c). */
void init_password(Password *password)
{
memset(password, 0, sizeof(*password));
password->cipher = NULL;
}
void clear_password(Password *password)
{
memset(password, 0, sizeof(*password));
free((char *)password->cipher);
password->cipher = NULL;
}
/*************************************************************************/
/* NickInfo/NickGroupInfo allocation (from modules/nickserv/util.c). The
* NickInfo and NickGroupInfo (if appropriate) are added into their
* respective hash tables. Always succeeds (if the memory allocations
* fail, aborts the program).
*/
#include "modules/nickserv/util.c"
NickInfo *makenick(const char *nick, NickGroupInfo **nickgroup_ret)
{
NickInfo *ni = new_nickinfo();
strbcpy(ni->nick, nick);
if (nickgroup_ret) {
NickGroupInfo *ngi = new_nickgroupinfo(ni->nick);
while (get_nickgroupinfo(ngi->id)) {
/* We assume that eventually we'll find one that's not in use */
ngi->id = rand() + rand();
if (ngi->id == 0)
ngi->id = 1;
}
ni->nickgroup = ngi->id;
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[0], nick);
add_nickgroupinfo(ngi);
*nickgroup_ret = ngi;
}
add_nickinfo(ni);
return ni;
}
/*************************************************************************/
/* ChannelInfo allocation. The channel is added to the hash table. */
#include "modules/chanserv/util.c"
ChannelInfo *makechan(const char *name)
{
ChannelInfo *ci = new_channelinfo();
strbcpy(ci->name, name);
add_channelinfo(ci);
return ci;
}
/*************************************************************************/
/* Open a (Services pre-5.0 style) data file and check the version number.
* Prints an error message and exits with 1 if either the file cannot be
* opened or the version number is wrong. If `version_ret' is non-NULL,
* the version number is stored there.
*/
dbFILE *open_db_ver(const char *dir, const char *name, int32 min_version,
int32 max_version, int32 *version_ret)
{
char filename[PATH_MAX+1];
dbFILE *f;
int32 ver;
snprintf(filename, sizeof(filename), "%s/%s", dir, name);
f = open_db(filename, "r", 0);
if (!f) {
fprintf(stderr, "Can't open %s for reading: %s\n", filename,
strerror(errno));
exit(1);
}
if (read_int32(&ver, f) < 0) {
fprintf(stderr, "Error reading version number on %s\n", filename);
exit(1);
}
if (ver < min_version || ver > max_version) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
if (version_ret)
*version_ret = ver;
return f;
}
/*************************************************************************/
/* Retrieve the NickGroupInfo structure for the given nick. Returns NULL
* if the nick does not exist or is forbidden (i.e. has no NickGroupInfo).
*/
NickGroupInfo *get_nickgroupinfo_by_nick(const char *nick)
{
NickInfo *ni = get_nickinfo(nick);
return ni ? get_nickgroupinfo(ni->nickgroup) : NULL;
}
/*************************************************************************/
/* Set the OperServ privilege level (os_priv) for the nickgroup associated
* with `nick' to `level', if it is not already greater than `level'. Does
* nothing if `nick' is NULL or does not have an associated nickgroup.
*/
void set_os_priv(const char *nick, int16 level)
{
NickGroupInfo *ngi;
if (!nick)
return;
ngi = get_nickgroupinfo_by_nick(nick);
if (ngi && ngi->os_priv < level)
ngi->os_priv = level;
}
/*************************************************************************/
/* Return the Services 5.0 channel access level that corresponds to the
* given pre-5.0 level. Code taken from modules/database/version4.c
* (convert_old_level()).
*/
int16 convert_acclev(int16 old)
{
if (old < 0)
return -convert_acclev(-old); /* avoid negative division */
else if (old <= 25)
return old*10; /* 0.. 25 -> 0..250 (10x) */
else if (old <= 50)
return 200 + old*2; /* 25.. 50 -> 250..300 ( 2x) */
else if (old <= 100)
return 280 + old*2/5; /* 50.. 100 -> 300..320 ( 0.4x) */
else if (old <= 1000)
return 300 + old/5; /* 100..1000 -> 320..500 ( 0.2x) */
else if (old <= 2000)
return 400 + old/10; /* 1000..2000 -> 500..600 ( 0.1x) */
else
return 500 + old/20; /* 2000..9999 -> 600..999 ( 0.05x) */
}
/*************************************************************************/
/*************************************************************************/
/* Replacements for database functions. add_*() functions are defined as
* macros in convert-db.h. */
/*************************************************************************/
static NickGroupInfo *ngi_iter;
NickGroupInfo *get_nickgroupinfo(uint32 id)
{
NickGroupInfo *ngi;
if (!id)
return NULL;
LIST_SEARCH_SCALAR(ngi_list, id, id, ngi);
return ngi;
}
NickGroupInfo *first_nickgroupinfo(void)
{
ngi_iter = ngi_list;
return next_nickgroupinfo();
}
NickGroupInfo *next_nickgroupinfo(void)
{
NickGroupInfo *retval = ngi_iter;
if (ngi_iter)
ngi_iter = ngi_iter->next;
return retval;
}
/*************************************************************************/
static NickInfo *ni_iter;
NickInfo *get_nickinfo(const char *nick)
{
NickInfo *ni;
LIST_SEARCH(ni_list, nick, nick, stricmp, ni);
return ni;
}
NickInfo *first_nickinfo(void)
{
ni_iter = ni_list;
return next_nickinfo();
}
NickInfo *next_nickinfo(void)
{
NickInfo *retval = ni_iter;
if (ni_iter)
ni_iter = ni_iter->next;
return retval;
}
/*************************************************************************/
static ChannelInfo *ci_iter;
ChannelInfo *get_channelinfo(const char *channel)
{
ChannelInfo *ci;
LIST_SEARCH(ci_list, name, channel, stricmp, ci);
return ci;
}
ChannelInfo *first_channelinfo(void)
{
ci_iter = ci_list;
return next_channelinfo();
}
ChannelInfo *next_channelinfo(void)
{
ChannelInfo *retval = ci_iter;
if (ci_iter)
ci_iter = ci_iter->next;
return retval;
}
/*************************************************************************/
static NewsItem *news_iter;
NewsItem *first_news(void)
{
news_iter = news_list;
return next_news();
}
NewsItem *next_news(void)
{
NewsItem *retval = news_iter;
if (news_iter)
news_iter = news_iter->next;
return retval;
}
/*************************************************************************/
static MaskData *md_iter[256];
MaskData *first_maskdata(uint8 type)
{
md_iter[type] = md_list[type];
return next_maskdata(type);
}
MaskData *next_maskdata(uint8 type)
{
MaskData *retval = md_iter[type];
if (md_iter[type])
md_iter[type] = md_iter[type]->next;
return retval;
}
/*************************************************************************/
static ServerStats *ss_iter;
ServerStats *first_serverstats(void)
{
ss_iter = ss_list;
return next_serverstats();
}
ServerStats *next_serverstats(void)
{
ServerStats *retval = ss_iter;
if (ss_iter)
ss_iter = ss_iter->next;
return retval;
}
/*************************************************************************/
int get_operserv_data(int what, void *ptr)
{
switch (what) {
case OSDATA_MAXUSERCNT:
*(int32 *)ptr = maxusercnt;
break;
case OSDATA_MAXUSERTIME:
*(time_t *)ptr = maxusertime;
break;
case OSDATA_SUPASS:
*(Password **)ptr = no_supass ? NULL : &supass;
break;
default:
return 0;
}
return 1;
}
/*************************************************************************/
/*************************************************************************/
/* Perform sanity checks on the data after it's been read in. */
static void sanity_check_nicks(void);
static void sanity_check_nickgroups(void);
static void sanity_check_channels(void);
static void sanity_check_maskdata(void);
static void sanity_checks(void)
{
sanity_check_nicks();
sanity_check_nickgroups();
sanity_check_channels();
sanity_check_maskdata();
}
/*************************************************************************/
static void sanity_check_nicks(void)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *s;
int i;
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
/* Forbidden nicks should have no other data associated with them. */
if (ni->status & NS_VERBOTEN) {
ni->status &= ~(NS_VERBOTEN);
ni->last_usermask = NULL;
ni->last_realmask = NULL;
ni->last_realname = NULL;
ni->last_quit = NULL;
ni->last_seen = 0;
if (ni->nickgroup) {
fprintf(stderr, "BUG: Forbidden nickname %s associated with"
" nickgroup %u! Clearing nickgroup field.\n",
ni->nick, ni->nickgroup);
ni->nickgroup = 0;
}
ni->id_stamp = 0;
continue;
}
/* The nick isn't a forbidden nick. First make sure it has the
* right nickgroup. */
if (!ni->nickgroup) {
fprintf(stderr, "BUG: Nickname %s has no nickgroup! Deleting.\n",
ni->nick);
del_nickinfo(ni);
continue;
}
ngi = get_nickgroupinfo(ni->nickgroup);
if (!ngi) {
fprintf(stderr, "BUG: Nickname %s points to nonexistent nickgroup"
" %u! Deleting.\n", ni->nick, ni->nickgroup);
del_nickinfo(ni);
} else {
/* Nicknames in the nicks[] array should match those in the
* NickInfo structure, so use strcmp() (this keeps us from
* having to worry about irc_stricmp() idiosyncrasies). */
ARRAY_SEARCH_PLAIN(ngi->nicks, ni->nick, strcmp, i);
if (i >= ngi->nicks_count) {
fprintf(stderr, "BUG: Nickname %s points to nickgroup %u,"
" but the nickgroup doesn't contain the nickname!"
" Deleting.\n", ni->nick, ni->nickgroup);
del_nickinfo(ni);
}
}
/* Clear unknown flags. */
ni->status &= NS_PERMANENT;
/* Make sure usermasks actually have non-empty user and host parts. */
if (ni->last_usermask) {
s = strchr(ni->last_usermask, '@');
if (!s || s==ni->last_usermask || !s[1]) {
fprintf(stderr, "Last usermask for nickname %s isn't a valid"
" user@host mask, clearing.\n", ni->nick);
ni->last_usermask = NULL;
}
}
if (ni->last_realmask) {
s = strchr(ni->last_realmask, '@');
if (!s || s==ni->last_realmask || !s[1]) {
fprintf(stderr, "Last real usermask for nickname %s isn't"
" a valid user@host mask, clearing.\n", ni->nick);
ni->last_realmask = NULL;
}
}
/* Make sure last-seen time is not earlier than registered time.
* Allow zero, to accommodate cases where the nickname was
* registered by an outside entity without the user actually
* logging on. */
if (ni->last_seen && ni->last_seen < ni->time_registered) {
fprintf(stderr, "Last-seen time for nickname %s is earlier than"
" registration time! Setting last-seen time to"
" registration time.\n", ni->nick);
ni->last_seen = ni->time_registered;
}
} /* for all nicks */
}
/*************************************************************************/
static void sanity_check_nickgroups(void)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *s;
int i;
for (ngi = first_nickgroupinfo(); ngi; ngi = next_nickgroupinfo()) {
/* Make sure nickgroups don't contain extra nicks. */
ARRAY_FOREACH(i, ngi->nicks) {
ni = get_nickinfo(ngi->nicks[i]);
if (!ni) {
fprintf(stderr, "BUG: Nickgroup %u contains nonexistent"
" nickname %s! Removing nickname from group.\n",
ngi->id, ngi->nicks[i]);
ARRAY_REMOVE(ngi->nicks, i);
if (ngi->mainnick >= i)
ngi->mainnick--;
i--; /* to make sure we don't skip any */
}
}
/* Check for empty nickgroups (possibly from extraneous nickname
* removal above). */
if (ngi->nicks_count == 0) {
fprintf(stderr, "Removing empty nickgroup %u.\n", ngi->id);
del_nickgroupinfo(ngi);
continue;
}
/* Make sure main nick is a valid index. */
if (ngi->mainnick >= ngi->nicks_count) {
fprintf(stderr, "Invalid main nick index in nickgroup %u,"
" resetting.\n", ngi->id);
ngi->mainnick = 0;
}
/* If an authcode is set, make sure the reason is valid. If not,
* clear the auth-related fields. */
if (ngi->authcode && (ngi->authreason < NICKAUTH_MIN
|| ngi->authreason > NICKAUTH_MAX)) {
fprintf(stderr, "Authentication code set for nickgroup %u but"
" reason code invalid, setting to SETAUTH.\n", ngi->id);
ngi->authreason = NICKAUTH_SETAUTH;
} else {
ngi->authset = 0;
ngi->authreason = 0;
}
/* Clear all unknown flags. */
ngi->flags &= NF_ALLFLAGS;
/* Make sure language setting is in range. */
if ((ngi->language < 0 || ngi->language >= NUM_LANGS)
&& ngi->language != LANG_DEFAULT
) {
fprintf(stderr, "Invalid language set for nickgroup %u,"
" resetting to default.\n", ngi->id);
ngi->language = LANG_DEFAULT;
}
/* Make sure access, autojoin, and ignore counts are non-negative. */
if (ngi->access_count < 0) {
fprintf(stderr, "BUG: Access entry count for nickgroup %u is"
" negative! Clearing.\n", ngi->id);
ngi->access = NULL;
ngi->access_count = 0;
}
if (ngi->ajoin_count < 0) {
fprintf(stderr, "BUG: Autojoin entry count for nickgroup %u is"
" negative! Clearing.\n", ngi->id);
ngi->ajoin = NULL;
ngi->ajoin_count = 0;
}
if (ngi->ignore_count < 0) {
fprintf(stderr, "BUG: Ignore entry count for nickgroup %u is"
" negative! Clearing.\n", ngi->id);
ngi->ignore = NULL;
ngi->ignore_count = 0;
}
/* Make sure all access entries have non-empty user and host parts. */
ARRAY_FOREACH (i, ngi->access) {
if (!ngi->access[i]
|| !(s = strchr(ngi->access[i], '@'))
|| s == ngi->access[i]
|| !s[1]
) {
fprintf(stderr, "Access entry %d for nickgroup %u %s,"
" deleting.\n", i, ngi->id,
!ngi->access[i] ? "is empty"
: "isn't a valid user@host mask");
ARRAY_REMOVE(ngi->access, i);
i--;
}
}
/* Make sure memo count is non-negative. */
if (ngi->memos.memos_count < 0) {
fprintf(stderr, "BUG: Memo count for nickgroup %u is negative!"
" Clearing.\n", ngi->id);
ngi->memos.memos = NULL;
ngi->memos.memos_count = 0;
}
/* Clear unknown flags from memos. */
ARRAY_FOREACH (i, ngi->memos.memos)
ngi->memos.memos[i].flags &= MF_ALLFLAGS;
} /* for all nickgroups */
}
/*************************************************************************/
static void sanity_check_channels(void)
{
ChannelInfo *ci;
char *s;
int i;
for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
/* Forbidden channels should have no other data associated with
* them. */
if (ci->flags & CF_VERBOTEN) {
ci->founder = 0;
ci->successor = 0;
init_password(&ci->founderpass);
ci->desc = NULL;
ci->url = NULL;
ci->email = NULL;
ci->last_used = 0;
ci->last_topic = NULL;
memset(ci->last_topic_setter, 0, sizeof(ci->last_topic_setter));
ci->last_topic_time = 0;
ci->flags &= ~(CF_VERBOTEN);
reset_levels(ci);
ci->access = NULL;
ci->access_count = 0;
ci->akick = NULL;
ci->akick_count = 0;
ci->mlock.on = NULL;
ci->mlock.off = NULL;
ci->mlock.limit = 0;
ci->mlock.key = NULL;
ci->mlock.link = NULL;
ci->mlock.flood = NULL;
ci->mlock.joindelay = 0;
ci->mlock.joinrate1 = 0;
ci->mlock.joinrate2 = 0;
ci->entry_message = NULL;
continue;
}
/* Channel is not forbidden. First make sure it has a (valid)
* founder. */
if (!ci->founder) {
fprintf(stderr, "BUG: Channel %s has no founder! Deleting.\n",
ci->name);
del_channelinfo(ci);
} else if (!get_nickgroupinfo(ci->founder)) {
fprintf(stderr, "BUG: Channel %s founder nickgroup %u is"
" missing! Deleting channel.\n", ci->name, ci->founder);
del_channelinfo(ci);
}
/* Make sure that the successor is valid if set. */
if (ci->successor && !get_nickgroupinfo(ci->successor)) {
fprintf(stderr, "BUG: Channel %s successor nickgroup %u is"
" missing! Clearing.", ci->name, ci->successor);
ci->successor = 0;
}
/* Make sure last-used time is not earlier than registered time.
* Allow zero, to accommodate cases where the channel was
* registered by an outside entity. */
if (ci->last_used && ci->last_used < ci->time_registered) {
fprintf(stderr, "Last-used time for channel %s is earlier than"
" registration time! Setting last-used time to"
" registration time.\n", ci->name);
ci->last_used = ci->time_registered;
}
/* If there is no saved topic, clear the topic setter and time. */
if (!ci->last_topic) {
memset(ci->last_topic_setter, 0, sizeof(ci->last_topic_setter));
ci->last_topic_time = 0;
}
/* Clear unknown flags. */
ci->flags &= CF_ALLFLAGS;
/* Check privilege level settings for vaility. */
for (i = 0; i < CA_SIZE; i++) {
if (ci->levels[i] != ACCLEV_DEFAULT
&& ci->levels[i] != ACCLEV_INVALID
&& ci->levels[i] != ACCLEV_FOUNDER
&& (ci->levels[i] < ACCLEV_MIN
|| ci->levels[i] > ACCLEV_MAX)
) {
fprintf(stderr, "Privilege level %d on channel %s is"
"invalid, resetting to default.\n", i, ci->name);
ci->levels[i] = ACCLEV_DEFAULT;
break;
}
}
/* Check access level nickgroups and levels for validity. */
ARRAY_FOREACH (i, ci->access) {
if (!ci->access[i].nickgroup)
continue;
if (!get_nickgroupinfo(ci->access[i].nickgroup)) {
fprintf(stderr, "BUG: Channel %s access entry %d has an"
" invalid nickgroup! Clearing.\n", ci->name, i);
ci->access[i].nickgroup = 0;
ci->access[i].level = 0;
} else if (ci->access[i].level < ACCLEV_MIN
|| ci->access[i].level > ACCLEV_MAX) {
fprintf(stderr, "BUG: Channel %s access entry %d has an"
"out-of-range level (%d)! Clearing.\n",
ci->name, i, ci->access[i].level);
ci->access[i].nickgroup = 0;
ci->access[i].level = 0;
}
}
/* Make sure all autokick entries have non-empty user and host
* parts. */
ARRAY_FOREACH (i, ci->akick) {
if (!ci->akick[i].mask)
continue;
s = strchr(ci->akick[i].mask, '@');
if (!s || s==ci->akick[i].mask || !s[1]) {
fprintf(stderr, "Autokick entry %d for channel %s isn't a"
" valid user@host mask, deleting.\n", i, ci->name);
ci->akick[i].mask = NULL;
}
}
} /* for all channels */
/* Check that channel successors and access list entries have valid
* nickgroup IDs, and that access levels are in range */
for (ci = first_channelinfo(); ci; ci = next_channelinfo()) {
if (ci->flags & CF_VERBOTEN)
continue;
}
}
/*************************************************************************/
static void sanity_check_maskdata(void)
{
MaskData *md;
char *s;
int i;
/* Make sure all MaskData entries actually have masks allocated. */
for (i = 0; i < 256; i++) {
for (md = first_maskdata(i); md; md = next_maskdata(i)) {
if (!md->mask)
del_maskdata(i, md);
}
}
/* Make sure every autokill has a valid user@host mask and a reason. */
for (md = first_maskdata(MD_AKILL); md; md = next_maskdata(MD_AKILL)) {
s = strchr(md->mask, '@');
if (!s || s==md->mask || !s[1]) {
fprintf(stderr, "Autokill %s isn't a valid user@host mask,"
" deleting.\n", md->mask);
del_maskdata(MD_AKILL, md);
continue;
}
if (!md->reason)
md->reason = "Reason unknown";
}
}
/*************************************************************************/
/****************************** Main program *****************************/
/*************************************************************************/
void usage(const char *progname)
{
int i;
fprintf(stderr, "Usage: %s [-v] [+program-name] [options...] dir\n"
"The following program names are known:\n", progname);
for (i = 0; dbtypes[i]; i++)
fprintf(stderr, " %s\n", dbtypes[i]->id);
fprintf(stderr,
"See the manual for options available for each database type.\n");
exit(1);
}
/*************************************************************************/
int main(int ac, char **av)
{
int newac = 0; /* For passing to processing function */
char **newav;
char *dir = NULL; /* Source data file directory */
int verbose = 0; /* Verbose output? */
void (*load)(const char *, int, int, char **) = NULL;
int i;
char oldpath[PATH_MAX+1], newpath[PATH_MAX+1];
#if CLEAN_COMPILE
free_nickinfo(NULL);
free_nickgroupinfo(NULL);
free_channelinfo(NULL);
#endif
init_password(&supass);
/* Parse command-line parameters */
newac = 1;
newav = malloc(sizeof(*newav) * ac);
newav[0] = av[0];
for (i = 1; i < ac; i++) {
if (strcmp(av[i],"-v") == 0) {
verbose++;
} else if (strcmp(av[i],"-h") == 0
|| strcmp(av[i],"-?") == 0
|| strcmp(av[i],"-help") == 0
|| strcmp(av[i],"--help") == 0) {
usage(av[0]);
} else if (av[i][0] == '+') {
int j;
for (j = 0; dbtypes[j]; j++) {
if (stricmp(av[i]+1, dbtypes[j]->id) == 0) {
load = dbtypes[j]->load;
break;
}
}
if (!load) {
fprintf(stderr, "Unknown database type `%s'\n", av[i]+1);
usage(av[0]);
}
} else if (av[i][0] == '-') {
newav[newac++] = av[i];
} else {
if (dir) {
fprintf(stderr, "Only one source directory may be specified\n");
usage(av[0]);
}
dir = av[i];
}
}
/* Make sure that we have a source directory and that it's valid */
if (!dir) {
fprintf(stderr, "Directory name must be specified\n");
usage(av[0]);
}
if (access(dir, R_OK) < 0) {
perror(dir);
exit(1);
}
/* If the source directory name is relative, make it absolute */
if (*dir != '/') {
if (!getcwd(oldpath, sizeof(oldpath))) {
perror("Unable to read current directory name");
fprintf(stderr, "Try using an absolute pathname for the source directory.\n");
return 1;
}
if (strlen(oldpath) + 1 + strlen(dir) + 1 > sizeof(newpath)) {
fprintf(stderr, "Source directory pathname too long\n");
return 1;
}
sprintf(newpath, "%s/%s", oldpath, dir);
dir = newpath;
}
/* If we weren't given a database type, try to figure one out */
if (!load) {
for (i = 0; dbtypes[i]; i++) {
const char *s;
if ((s = dbtypes[i]->check(dir)) != NULL) {
fprintf(stderr, "Found %s databases\n", s);
load = dbtypes[i]->load;
break;
}
}
if (!load) {
fprintf(stderr, "Can't determine database type; use +name option\n");
usage(av[0]);
}
}
/* Actually load the databases. If an error occurs, load() will abort the
* program for us */
load(dir, verbose, newac, newav);
if (verbose)
fprintf(stderr, "Data files successfully loaded.\n");
/* Do sanity checks. */
if (verbose)
fprintf(stderr, "Checking data integrity...\n");
sanity_checks();
/* Write the database to standard output in XML format */
if (verbose)
fprintf(stderr, "Writing converted data...\n");
xml_export((xml_writefunc_t)fprintf, stdout);
/* Success */
if (verbose)
fprintf(stderr, "Done.\n");
return 0;
}
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

183
tools/convert-db.h Normal file
View File

@ -0,0 +1,183 @@
/* External declarations for convert-db.
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#ifndef CONVERT_DB_H
#define CONVERT_DB_H
/*************************************************************************/
/* Common includes. */
#include "services.h"
#include "language.h"
#include "encrypt.h"
#include "modules/database/fileutil.h"
#include "modules/nickserv/nickserv.h"
#include "modules/chanserv/chanserv.h"
#include "modules/memoserv/memoserv.h"
#include "modules/operserv/operserv.h"
#include "modules/operserv/maskdata.h"
#include "modules/operserv/news.h"
#include "modules/statserv/statserv.h"
/*************************************************************************/
/*************************************************************************/
/* Structure with information about each supported database type. */
typedef struct {
/* Identifier (used with +xyz command-line option) */
const char *id;
/* Routine to check whether databases for this program are in the given
* directory; returns a program/database-type name for use in the
* "Found XYZ databases" message if databases are found, NULL if not */
const char *(*check)(const char *dir);
/* Routine to load databases from the given directory; prints an
* appropriate error message and calls exit(1) if an error occurs.
* ac/av are loaded with all option arguments passed to the program
* not parsed out by the main code; av[0] will contain the program
* name as usual */
void (*load)(const char *dir, int verbose, int ac, char **av);
} DBTypeInfo;
/* List of all available types. This macro is used twice in convert-db.c:
* once with an empty PREFIX to declare all of the structures extern, and
* once more with a PREFIX of & to define an array of pointers to the
* structures. */
#define ALL_DB_TYPES(PREFIX) \
PREFIX dbtype_anope, \
PREFIX dbtype_auspice, \
PREFIX dbtype_bolivia, \
PREFIX dbtype_cygnus, \
PREFIX dbtype_daylight, \
PREFIX dbtype_epona, \
PREFIX dbtype_hybserv, \
PREFIX dbtype_ircs_1_2, \
PREFIX dbtype_magick_14b2, \
PREFIX dbtype_ptlink, \
PREFIX dbtype_sirv, \
PREFIX dbtype_trircd_4_26, \
PREFIX dbtype_wrecked_1_2
/*************************************************************************/
/*************************************************************************/
/* Converted data. */
extern NickGroupInfo *ngi_list;
extern NickInfo *ni_list;
extern ChannelInfo *ci_list;
extern NewsItem *news_list;
extern MaskData *md_list[256];
extern ServerStats *ss_list;
extern int32 maxusercnt;
extern time_t maxusertime;
extern Password supass;
extern int no_supass;
/*************************************************************************/
/* Safe memory allocation and string duplication. */
extern void *smalloc(long size);
extern void *scalloc(long els, long elsize);
extern void *srealloc(void *ptr, long size);
extern char *sstrdup(const char *s);
/* Initialize or clear a Password structure. */
extern void init_password(Password *password);
extern void clear_password(Password *password);
/* Allocate a new, initialized NickInfo (and possibly NickGroupInfo)
* structure. */
extern NickInfo *makenick(const char *nick, NickGroupInfo **nickgroup_ret);
/* Allocate a new, initialized ChannelInfo structure. */
extern ChannelInfo *makechan(const char *name);
/* Open a (Services pre-5.0 style) data file and check the version number.
* Prints an error message and exits with 1 if either the file cannot be
* opened or the version number is wrong. If `version_ret' is non-NULL,
* the version number is stored there. */
extern dbFILE *open_db_ver(const char *dir, const char *name,
int32 min_version, int32 max_version,
int32 *version_ret);
/* Retrieve the NickGroupInfo structure for the given nick. Returns NULL
* if the nick does not exist or is forbidden (i.e. has no NickGroupInfo). */
extern NickGroupInfo *get_nickgroupinfo_by_nick(const char *nick);
/* Set the OperServ privilege level (os_priv) for the nickgroup associated
* with `nick' to `level', if it is not already greater than `level'. Does
* nothing if `nick' is NULL or does not have an associated nickgroup. */
extern void set_os_priv(const char *nick, int16 level);
/* Return the Services 5.0 channel access level that corresponds to the
* given pre-5.0 level. */
extern int16 convert_acclev(int16 old);
/* Add or remove various things to or from the appropriate lists. */
#define add_nickgroupinfo(ngi) LIST_INSERT((ngi), ngi_list)
#define add_nickinfo(ni) LIST_INSERT((ni), ni_list)
#define add_channelinfo(ci) LIST_INSERT((ci), ci_list)
#define add_news(news) LIST_INSERT((news), news_list)
#define add_maskdata(type,md) LIST_INSERT((md), md_list[(type)])
#define add_serverstats(ss) LIST_INSERT((ss), ss_list)
#define del_nickgroupinfo(ngi) LIST_REMOVE((ngi), ngi_list)
#define del_nickinfo(ni) LIST_REMOVE((ni), ni_list)
#define del_channelinfo(ci) LIST_REMOVE((ci), ci_list)
#define del_news(news) LIST_REMOVE((news), news_list)
#define del_maskdata(type,md) LIST_REMOVE((md), md_list[(type)])
#define del_serverstats(ss) LIST_REMOVE((ss), ss_list)
/*************************************************************************/
#ifdef CONVERT_DB_MAIN
/* Macro to handle write errors. */
#define SAFE(x) do { \
if ((x) < 0) { \
fprintf(stderr, "Write error on %s: %s\n", \
f->filename, strerror(errno)); \
exit(1); \
} \
} while (0)
#else /* !CONVERT_DB_MAIN */
/* Macro to handle read errors. */
#define SAFE(x) do { \
if ((x) < 0) { \
fprintf(stderr, "Read error on %s\n", f->filename); \
exit(1); \
} \
} while (0)
/* Macro to read in a variable in machine format. */
#define read_variable(var,f) (read_db((f),&(var),sizeof(var)) == sizeof(var))
#endif /* CONVERT_DB_MAIN */
/*************************************************************************/
/* Miscellaneous externs. */
extern void usage(const char *progname);
/*************************************************************************/
#endif /* CONVERT_DB_H */
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

966
tools/convert-epona.c Normal file
View File

@ -0,0 +1,966 @@
/* Conversion routines for Epona/Anope databases (version 1.3.0 and later).
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#include "convert-db.h"
#if NICKMAX < 32
# error NICKMAX too small (must be >=32)
#elif CHANMAX < 64
# error CHANMAX too small (must be >=64)
#elif PASSMAX < 32
# error PASSMAX too small (must be >=32)
#endif
/* Server type selected with -ircd=XXX */
static enum servertype_enum {
IRCD_UNKNOWN = 0,
IRCD_BAHAMUT, /* or dreamforge, solidircd */
IRCD_INSPIRCD,
IRCD_PLEXUS,
IRCD_PTLINK,
IRCD_RAGE,
IRCD_SHADOW,
IRCD_ULTIMATE2,
IRCD_ULTIMATE3,
IRCD_UNREAL,
IRCD_VIAGRA,
} servertype = IRCD_UNKNOWN;
/* Encryption type selected with -encryption=XXXX */
static enum enctype_enum {
ENC_UNKNOWN = 0, /* Pre-1.7.18: use nick/channel flags to select cipher */
ENC_NONE,
ENC_MD5,
ENC_SHA1,
} enctype = ENC_UNKNOWN;
/* Option names for -ircd=XXXX */
static struct {
const char *name;
enum servertype_enum type;
} servertype_names[] = {
{ "bahamut", IRCD_BAHAMUT },
{ "dreamforge", IRCD_BAHAMUT }, /* +R/+r only */
{ "hybrid", IRCD_UNKNOWN }, /* no special modes */
{ "inspircd", IRCD_INSPIRCD },
{ "plexus", IRCD_PLEXUS },
{ "ptlink", IRCD_PTLINK },
{ "rageircd", IRCD_RAGE },
{ "ratbox", IRCD_UNKNOWN }, /* no special modes */
{ "shadowircd", IRCD_SHADOW },
{ "solidircd", IRCD_BAHAMUT }, /* shared modes */
{ "ultimate2", IRCD_ULTIMATE2 },
{ "ultimate3", IRCD_ULTIMATE3 },
{ "unreal31", IRCD_UNREAL },
{ "unreal32", IRCD_UNREAL },
{ "viagra", IRCD_VIAGRA },
{ NULL }
};
/*************************************************************************/
static void epona_load_nick(const char *dir)
{
dbFILE *f;
int32 ver;
int i, j, c;
int16 tmp16;
int32 tmp32;
NickInfo *ni;
NickGroupInfo *ngi;
char *s;
f = open_db_ver(dir, "nick.db", 13, 13, &ver);
/* Nick cores (nick core = nickname + NickGroupInfo) */
for (i = 0; i < 1024; i++) {
while ((c = getc_db(f)) == 1) {
char nickbuf[32];
SAFE(read_string(&s, f));
ni = makenick(s, &ngi);
SAFE(read_string(&s, f));
/* For some reason nick cores can get null passwords (???) */
if (!s) {
fprintf(stderr, "Warning: nick `%s' has null password."
" Setting password to nickname.\n", ni->nick);
s = ni->nick;
}
init_password(&ngi->pass);
strbcpy(ngi->pass.password, s);
SAFE(read_string(&ngi->email, f));
SAFE(read_string(&s, f)); /* greet */
SAFE(read_int32(&tmp32, f)); /* icq */
SAFE(read_string(&ngi->url, f));
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ngi->flags |= NF_KILLPROTECT;
if (tmp32 & 0x00000002)
ngi->flags |= NF_SECURE;
if (tmp32 & 0x00000008)
ngi->flags |= NF_MEMO_HARDMAX;
if (tmp32 & 0x00000010)
ngi->flags |= NF_MEMO_SIGNON;
if (tmp32 & 0x00000020)
ngi->flags |= NF_MEMO_RECEIVE;
if (tmp32 & 0x00000040)
ngi->flags |= NF_PRIVATE;
if (tmp32 & 0x00000080)
ngi->flags |= NF_HIDE_EMAIL;
if (tmp32 & 0x00000100)
ngi->flags |= NF_HIDE_MASK;
if (tmp32 & 0x00000200)
ngi->flags |= NF_HIDE_QUIT;
if (tmp32 & 0x00000400)
ngi->flags |= NF_KILL_QUICK;
if (tmp32 & 0x00000800)
ngi->flags |= NF_KILL_IMMED;
if (tmp32 & 0x0000A000) /* NI_SERVICES_{ADMIN,ROOT} */
ngi->os_priv = NP_SERVADMIN;
else if (tmp32 & 0x00001000) /* NI_SERVICES_OPER */
ngi->os_priv = NP_SERVOPER;
if (enctype == ENC_UNKNOWN && (tmp32 & 0x00004000))
ngi->pass.cipher = sstrdup("md5");
else if (enctype == ENC_MD5)
ngi->pass.cipher = sstrdup("md5");
else if (enctype == ENC_SHA1)
ngi->pass.cipher = sstrdup("sha1");
else
ngi->pass.cipher = NULL;
if (tmp32 & 0x00080000)
ngi->flags |= NF_NOOP;
SAFE(read_int16(&tmp16, f));
switch (tmp16) {
case 0: ngi->language = LANG_EN_US; break;
case 2: ngi->language = LANG_JA_EUC; break;
case 3: ngi->language = LANG_JA_SJIS; break;
case 4: ngi->language = LANG_ES; break;
case 5: ngi->language = LANG_PT; break;
case 6: ngi->language = LANG_FR; break;
case 7: ngi->language = LANG_TR; break;
case 8: ngi->language = LANG_IT; break;
case 9: ngi->language = LANG_DE; break;
case 10: /* Catalan */ break;
case 11: /* Greek */ break;
case 12: ngi->language = LANG_NL; break;
}
SAFE(read_int16(&ngi->access_count, f));
if (ngi->access_count) {
char **access;
access = scalloc(sizeof(char *), ngi->access_count);
ngi->access = access;
for (j = 0; j < ngi->access_count; j++, access++)
SAFE(read_string(access, f));
}
SAFE(read_int16(&ngi->memos.memos_count, f));
SAFE(read_int16(&ngi->memos.memomax, f));
if (ngi->memos.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), ngi->memos.memos_count);
ngi->memos.memos = memos;
for (j = 0; j < ngi->memos.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_int16(&tmp16, f)); /* channelcount */
SAFE(read_int16(&tmp16, f)); /* channelmax */
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
/* Nick aliases */
for (i = 0; i < 1024; i++) {
while ((c = getc_db(f)) == 1) {
int islink = 0;
SAFE(read_string(&s, f)); /* nick */
ni = get_nickinfo(s);
if (!ni) {
islink = 1;
ni = makenick(s, NULL);
}
SAFE(read_string(&ni->last_usermask, f));
if (!ni->last_usermask)
ni->last_usermask = (char *)"@";
SAFE(read_string(&ni->last_realname, f));
if (!ni->last_realname)
ni->last_realname = (char *)"";
SAFE(read_string(&ni->last_quit, f));
SAFE(read_int32(&tmp32, f));
ni->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ni->last_seen = tmp32;
SAFE(read_int16(&tmp16, f)); /* status */
if (tmp16 & 0x0002) {
ni->status |= NS_VERBOTEN;
ni->nickgroup = 0;
}
if (tmp16 & 0x0004)
ni->status |= NS_NOEXPIRE;
SAFE(read_string(&s, f));
if (islink) {
NickInfo *root = get_nickinfo(s);
if (!root) {
fprintf(stderr,
"Warning: nick alias %s has no core, discarding\n",
ni->nick);
continue;
}
ni->nickgroup = root->nickgroup;
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi) {
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick);
} else {
fprintf(stderr, "Warning: Nick group %d for nick %s not"
" found -- program bug? Output may be corrupt.",
ni->nickgroup, ni->nick);
}
} else {
if (stricmp(s, ni->nick) != 0) {
fprintf(stderr, "Warning: display %s for nick alias %s"
" different from nick core\n", s, ni->nick);
}
}
}
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
}
close_db(f);
}
/*************************************************************************/
static struct {
int32 flag;
char mode;
} epona_cmodes_common[] = {
{ 0x00000001, 'i' },
{ 0x00000002, 'm' },
{ 0x00000004, 'n' },
{ 0x00000008, 'p' },
{ 0x00000010, 's' },
{ 0x00000020, 't' },
{ 0x00000040, 'k' },
{ 0x00000080, 'l' },
{ 0, 0 }
}, epona_cmodes_none[] = { /* for servers with no special modes */
{ 0, 0 }
}, epona_cmodes_bahamut[] = { /* also for dreamforge, solidircd */
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'M' },
{ 0x00001000, 'j' },
{ 0x00002000, 'S' },
{ 0x00004000, 'N' },
{ 0x00008000, 'O' },
{ 0, 0 }
}, epona_cmodes_inspircd[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'A' },
{ 0x00001000, 'H' },
{ 0x00002000, 'K' },
{ 0x00004000, 'L' },
{ 0x00008000, 'O' },
{ 0x00010000, 'Q' },
{ 0x00020000, 'S' },
{ 0x00040000, 'V' },
{ 0x00080000, 'f' },
{ 0x00100000, 'G' },
{ 0x00200000, 'C' },
{ 0x00400000, 'u' },
{ 0x00800000, 'z' },
{ 0x01000000, 'N' },
{ 0, 0 }
}, epona_cmodes_plexus[] = {
{ 0x00000400, 'a' },
{ 0x00000800, 'Z' },
{ 0x00001000, 'M' },
{ 0x00002000, 'c' },
{ 0x00004000, 'O' },
{ 0x00008000, 'R' },
{ 0x00010000, 'N' },
{ 0, 0 }
}, epona_cmodes_ptlink[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'A' },
{ 0x00000800, 'B' },
{ 0x00001000, 'c' },
{ 0x00002000, 'd' },
{ 0x00004000, 'f' },
{ 0x00008000, 'K' },
{ 0x00010000, 'O' },
{ 0x00020000, 'q' },
{ 0x00040000, 'S' },
{ 0x00080000, 'N' },
{ 0, 0 }
}, epona_cmodes_rage[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'M' },
{ 0x00001000, 'N' },
{ 0x00002000, 'S' },
{ 0x00004000, 'C' },
{ 0x00008000, 'A' },
{ 0x00010000, 'O' },
{ 0, 0 }
}, epona_cmodes_shadow[] = {
{ 0x00000100, 'K' },
{ 0x00000200, 'A' },
{ 0x00000400, 0 }, /* 'r', never set in mlock */
{ 0x00000800, 'z' },
{ 0x00001000, 'S' },
{ 0x00002000, 'c' },
{ 0x00004000, 'E' },
{ 0x00008000, 'F' },
{ 0x00010000, 'G' },
{ 0x00020000, 'L' },
{ 0x00040000, 'N' },
{ 0x00080000, 'O' },
{ 0x00100000, 'P' },
{ 0x00200000, 'R' },
{ 0x00400000, 'T' },
{ 0x00800000, 'V' },
{ 0, 0 }
}, epona_cmodes_ultimate2[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'f' },
{ 0x00000800, 'x' },
{ 0x00001000, 'A' },
{ 0x00002000, 'I' },
{ 0x00004000, 'K' },
{ 0x00008000, 'L' },
{ 0x00010000, 'O' },
{ 0x00020000, 'S' },
{ 0, 0 }
}, epona_cmodes_ultimate3[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'A' },
{ 0x00001000, 'N' },
{ 0x00002000, 'S' },
{ 0x00004000, 'K' },
{ 0x00008000, 'O' },
{ 0x00010000, 'q' },
{ 0x00020000, 'M' },
{ 0, 0 }
}, epona_cmodes_unreal[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'A' },
{ 0x00001000, 'H' },
{ 0x00002000, 'K' },
{ 0x00004000, 'L' },
{ 0x00008000, 'O' },
{ 0x00010000, 'Q' },
{ 0x00020000, 'S' },
{ 0x00040000, 'V' },
{ 0x00080000, 'f' },
{ 0x00100000, 'G' },
{ 0x00200000, 'C' },
{ 0x00800000, 'z' },
{ 0x01000000, 'N' },
{ 0x02000000, 'M' },
{ 0x04000000, 'T' },
{ 0, 0 }
}, epona_cmodes_viagra[] = {
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'M' },
{ 0x00001000, 'H' },
{ 0x00008000, 'O' },
{ 0x00020000, 'S' },
{ 0x01000000, 'N' },
{ 0x02000000, 'P' },
{ 0x04000000, 'x' },
{ 0, 0 }
}, *epona_cmode_index[] = {
/* IRCD_UNKNOWN */ epona_cmodes_none,
/* IRCD_BAHAMUT */ epona_cmodes_bahamut,
/* IRCD_INSPIRCD */ epona_cmodes_inspircd,
/* IRCD_PLEXUS */ epona_cmodes_plexus,
/* IRCD_PTLINK */ epona_cmodes_ptlink,
/* IRCD_RAGE */ epona_cmodes_rage,
/* IRCD_SHADOW */ epona_cmodes_shadow,
/* IRCD_ULTIMATE2 */ epona_cmodes_ultimate2,
/* IRCD_ULTIMATE3 */ epona_cmodes_ultimate3,
/* IRCD_UNREAL */ epona_cmodes_unreal,
/* IRCD_VIAGRA */ epona_cmodes_viagra,
};
/************************************/
static void epona_load_chan(const char *dir)
{
dbFILE *f;
int32 ver;
int i, j, c;
ChannelInfo *ci;
NickInfo *ni;
int32 tmp32, mlock_on, mlock_off;
char *on, *off;
MemoInfo tmpmi;
f = open_db_ver(dir, "chan.db", 14, 17, &ver);
for (i = 0; i < 256; i++) {
int16 tmp16;
char *s;
while ((c = getc_db(f)) == 1) {
char namebuf[64], passbuf[32], nickbuf[32];
SAFE(read_buffer(namebuf, f));
ci = makechan(namebuf);
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr,
"Warning: Founder %s for channel %s not found\n",
s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Founder %s for channel %s is a"
" forbidden nick\n", s, ci->name);
} else {
ci->founder = ni->nickgroup;
}
}
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" not found\n", s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is a forbidden nick\n", s, ci->name);
} else if (ni->nickgroup == ci->founder) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is the same as the founder, clearing\n",
s, ci->name);
} else {
ci->successor = ni->nickgroup;
}
}
SAFE(read_buffer(passbuf, f));
init_password(&ci->founderpass);
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf));
SAFE(read_string(&ci->desc, f));
if (!ci->desc)
ci->desc = (char *)"";
SAFE(read_string(&ci->url, f));
SAFE(read_string(&ci->email, f));
SAFE(read_int32(&tmp32, f));
ci->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ci->last_used = tmp32;
SAFE(read_string(&ci->last_topic, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(ci->last_topic_setter, nickbuf);
SAFE(read_int32(&tmp32, f));
ci->last_topic_time = tmp32;
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ci->flags |= CF_KEEPTOPIC;
if (tmp32 & 0x00000002)
ci->flags |= CF_SECUREOPS;
if (tmp32 & 0x00000004)
ci->flags |= CF_PRIVATE;
if (tmp32 & 0x00000008)
ci->flags |= CF_TOPICLOCK;
if (tmp32 & 0x00000010)
ci->flags |= CF_RESTRICTED;
if (tmp32 & 0x00000040)
ci->flags |= CF_SECURE;
if (tmp32 & 0x00000080)
ci->flags |= CF_VERBOTEN;
if (enctype == ENC_UNKNOWN && (tmp32 & 0x00000100))
ci->founderpass.cipher = sstrdup("md5");
else if (enctype == ENC_MD5)
ci->founderpass.cipher = sstrdup("md5");
else if (enctype == ENC_SHA1)
ci->founderpass.cipher = sstrdup("sha1");
else
ci->founderpass.cipher = NULL;
if (tmp32 & 0x00000200)
ci->flags |= CF_NOEXPIRE;
if (tmp32 & 0x00000800)
ci->flags |= CF_OPNOTICE;
if (tmp32 & 0x00010000) {
ci->flags |= CF_SUSPENDED;
strbcpy(ci->suspend_who, "<unknown>");
ci->suspend_reason =
(char *)"Unknown (imported from Anope Services)";
ci->suspend_time = time(NULL);
ci->suspend_expires = 0;
}
SAFE(read_string(&s, f)); /* forbidby */
SAFE(read_string(&s, f)); /* forbidreason */
SAFE(read_int16(&tmp16, f)); /* bantype */
SAFE(read_int16(&tmp16, f));
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&ci->access_count, f));
if (ci->access_count) {
ci->access = scalloc(ci->access_count, sizeof(ChanAccess));
for (j = 0; j < ci->access_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&ci->access[j].level, f));
SAFE(read_string(&s, f));
SAFE(read_int32(&tmp32, f)); /* last used */
ci->access[j].level =
convert_acclev(ci->access[j].level);
if (s) {
ni = get_nickinfo(s);
if (ni)
ci->access[j].nickgroup = ni->nickgroup;
}
}
}
}
SAFE(read_int16(&ci->akick_count, f));
if (ci->akick_count) {
ci->akick = scalloc(ci->akick_count, sizeof(AutoKick));
for (j = 0; j < ci->akick_count; j++) {
int16 is_nick = 0;
SAFE(read_int16(&tmp16, f)); /* in_use */
if (ver > 14) {
is_nick = tmp16 & 2;
tmp16 &= 1;
}
if (tmp16) {
if (ver == 14)
SAFE(read_int16(&is_nick, f));
SAFE(read_string(&s, f));
if (is_nick && s) {
ci->akick[j].mask = smalloc(strlen(s)+5);
sprintf(ci->akick[j].mask, "%s!*@*", s);
} else {
ci->akick[j].mask = s;
}
SAFE(read_string(&s, f));
if (ci->akick[j].mask)
ci->akick[j].reason = s;
SAFE(read_string(&s, f));
if (ci->akick[j].mask)
strbcpy(ci->akick[j].who, s);
SAFE(read_int32(&tmp32, f));
if (ci->akick[j].mask)
ci->akick[j].set = tmp32;
}
}
}
SAFE(read_int32(&mlock_on, f));
SAFE(read_int32(&mlock_off, f));
ci->mlock.on = on = scalloc(64, 1);
ci->mlock.off = off = scalloc(64, 1);
for (j = 0; epona_cmodes_common[j].flag != 0; j++) {
if (mlock_on & epona_cmodes_common[j].flag)
*on++ = epona_cmodes_common[j].mode;
if (mlock_off & epona_cmodes_common[j].flag)
*off++ = epona_cmodes_common[j].mode;
}
for (j = 0; epona_cmode_index[servertype][j].flag != 0; j++) {
if (mlock_on & epona_cmode_index[servertype][j].flag)
*on++ = epona_cmode_index[servertype][j].mode;
if (mlock_off & epona_cmode_index[servertype][j].flag)
*off++ = epona_cmode_index[servertype][j].mode;
}
SAFE(read_int32(&ci->mlock.limit, f));
SAFE(read_string(&ci->mlock.key, f));
SAFE(read_string(&ci->mlock.flood, f));
if (ver >= 17) {
char *s;
SAFE(read_string(&s, f));
if (s) {
unsigned long rate1, rate2;
if (sscanf(s, "%lu:%lu", &rate1, &rate2) == 2
&& rate1 > 0 && rate1 < 0x7FFFFFFFUL
&& rate2 > 0 && rate2 < 0x7FFFFFFFUL
) {
ci->mlock.joinrate1 = rate1;
ci->mlock.joinrate2 = rate2;
} else {
fprintf(stderr, "MLOCK +j setting for %s is"
" invalid, discarding", ci->name);
}
free(s);
}
}
SAFE(read_string(&ci->mlock.link, f));
SAFE(read_int16(&tmpmi.memos_count, f));
SAFE(read_int16(&tmp16, f)); /* memomax */
if (tmpmi.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), tmpmi.memos_count);
tmpmi.memos = memos;
for (j = 0; j < tmpmi.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_string(&ci->entry_message, f));
/* BotServ-related */
SAFE(read_string(&s, f));
SAFE(read_int32(&tmp32, f));
SAFE(read_int16(&tmp16, f));
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&tmp16, f));
for (j = tmp16; j > 0; j--) {
SAFE(read_int16(&tmp16, f));
if (tmp16) {
SAFE(read_string(&s, f));
SAFE(read_int16(&tmp16, f));
}
}
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) {
fprintf(stderr, "Ignoring channel %s (missing founder)\n",
ci->name);
del_channelinfo(ci);
}
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
}
/*************************************************************************/
static void epona_load_oper(const char *dir)
{
dbFILE *f;
int32 ver;
int16 i, n, tmp16;
int32 tmp32;
char *s;
MaskData *md;
f = open_db_ver(dir, "oper.db", 11, 13, &ver);
if (ver == 12) {
fprintf(stderr, "Unsupported version number (%d) on oper.db.\n"
"Are you using a beta version of Epona?\n", ver);
exit(1);
}
/* stats */
SAFE(read_int32(&maxusercnt, f));
SAFE(read_int32(&tmp32, f));
maxusertime = tmp32;
/* akills */
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char *user, *host;
SAFE(read_string(&user, f));
SAFE(read_string(&host, f));
s = smalloc(strlen(user)+strlen(host)+2);
sprintf(s, "%s@%s", user, host);
md[i].mask = s;
SAFE(read_string(&s, f));
strbcpy(md[i].who, s);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
/* sglines */
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&s, f));
strbcpy(md[i].who, s);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_SGLINE, &md[i]);
}
if (ver >= 13) {
/* sqlines */
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&s, f));
strbcpy(md[i].who, s);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_SQLINE, &md[i]);
}
}
/* szlines */
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&s, f));
strbcpy(md[i].who, s);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_SZLINE, &md[i]);
}
if (ver >= 13) {
/* proxy (open-relay) host cache */
for (i = 0; i < 1024; i++) {
int8 c;
if (read_int8(&c, f) < 0) /* 1.7 doesn't save this data */
break;
while (c) {
SAFE(read_string(&s, f)); /* host */
SAFE(read_int16(&tmp16, f)); /* status */
SAFE(read_int32(&tmp32, f)); /* used */
SAFE(read_int8(&c, f));
}
}
}
close_db(f);
}
/*************************************************************************/
static void epona_load_exception(const char *dir)
{
dbFILE *f;
int32 ver;
int16 i, n;
int32 tmp32;
MaskData *md;
f = open_db_ver(dir, "exception.db", 9, 9, &ver);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_string(&md[i].mask, f));
SAFE(read_int16(&md[i].limit, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(md[i].who, nickbuf);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
md[i].num = i;
if (md[i].mask)
add_maskdata(MD_EXCEPTION, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void epona_load_news(const char *dir)
{
dbFILE *f;
int32 ver;
int16 i, n;
int32 tmp32;
NewsItem *news;
f = open_db_ver(dir, "news.db", 9, 9, &ver);
SAFE(read_int16(&n, f));
news = scalloc(sizeof(*news), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_int16(&news[i].type, f));
SAFE(read_int32(&news[i].num, f));
SAFE(read_string(&news[i].text, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(news[i].who, nickbuf);
SAFE(read_int32(&tmp32, f));
news[i].time = tmp32;
add_news(&news[i]);
}
close_db(f);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_epona(const char *dir)
{
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/bot.db", dir);
if (access(buf, R_OK) == 0) {
FILE *f;
snprintf(buf, sizeof(buf), "%s/chan.db", dir);
f = fopen(buf, "rb");
if (f) {
int32 ver;
ver = fgetc(f)<<24;
ver |= fgetc(f)<<16;
ver |= fgetc(f)<< 8;
ver |= fgetc(f);
fclose(f);
switch (ver) {
case 14: return "Epona 1.3.x";
case 15: return "Epona 1.4.0";
case 16: return "Epona 1.4.1-1.4.14 / Anope";
case 17: return "Epona 1.4.15+";
}
}
}
return NULL;
}
static void load_epona(const char *dir, int verbose, int ac, char **av)
{
int i;
for (i = 1; i < ac; i++) {
if (strncmp(av[i],"-ircd=",6) == 0) {
const char *ircd = av[i]+6;
int j;
for (j = 0; servertype_names[j].name != NULL; j++) {
if (stricmp(servertype_names[j].name, ircd) == 0)
break;
}
if (servertype_names[j].name) {
servertype = servertype_names[j].type;
} else {
fprintf(stderr, "Unrecognized IRC server type %s\n", ircd);
fprintf(stderr, "Valid IRC server types are:\n");
for (j = 0; servertype_names[j].name != NULL; j++)
fprintf(stderr, " %s\n", servertype_names[j].name);
exit(1);
}
} else if (strncmp(av[i],"-encryption=",12) == 0) {
const char *encryption = av[i]+12;
/* Allow Anope module names as well */
if (strnicmp(encryption, "enc_", 4) == 0) {
encryption += 4;
}
if (stricmp(encryption, "none") == 0) {
enctype = ENC_NONE;
} else if (stricmp(encryption, "md5") == 0
|| stricmp(encryption, "old") == 0) {
enctype = ENC_MD5;
} else if (stricmp(encryption, "sha1") == 0) {
enctype = ENC_SHA1;
} else {
fprintf(stderr, "Unsupported encryption type %s\n",
encryption);
fprintf(stderr, "Supported encryption types are:"
" none, md5, old, sha1\n");
exit(1);
}
} else {
fprintf(stderr, "Unrecognized option %s\n", av[i]);
usage(av[0]);
}
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
epona_load_nick(dir);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
epona_load_chan(dir);
if (verbose)
fprintf(stderr, "Loading oper.db...\n");
epona_load_oper(dir);
if (verbose)
fprintf(stderr, "Loading exception.db...\n");
epona_load_exception(dir);
if (verbose)
fprintf(stderr, "Loading news.db...\n");
epona_load_news(dir);
}
/*************************************************************************/
/*************************************************************************/
DBTypeInfo dbtype_epona = {
"epona",
check_epona,
load_epona
};
DBTypeInfo dbtype_anope = {
"anope",
check_epona,
load_epona
};
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

1062
tools/convert-hybserv.c Normal file

File diff suppressed because it is too large Load Diff

696
tools/convert-magick.c Normal file
View File

@ -0,0 +1,696 @@
/* Conversion routines for Magick 1.4b2 and Wrecked 1.2 databases.
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#include "convert-db.h"
#if NICKMAX < 32
# error NICKMAX too small (must be >=32)
#elif CHANMAX < 64
# error CHANMAX too small (must be >=64)
#elif PASSMAX < 32
# error PASSMAX too small (must be >=32)
#endif
/*************************************************************************/
static void m14_load_nick(const char *dir, int32 version)
{
dbFILE *f;
long i, j;
int c;
NickInfo *ni;
NickGroupInfo *ngi;
struct oldni_ {
struct oldni_ *next, *prev;
char nick[32];
char pass[32];
char *email;
char *url;
char *usermask;
char *realname;
time_t reg;
time_t seen;
long naccess;
char **access;
long nignore;
char **ignore;
long flags;
long resv[4];
} oldni;
f = open_db_ver(dir, "nick.db", version, version, NULL);
for (i = 33; i < 256; i++) {
while ((c = getc_db(f)) == 1) {
SAFE(read_variable(oldni, f));
if (version == 6) {
time_t last_signon;
long uin;
SAFE(read_variable(last_signon, f));
SAFE(read_variable(uin, f));
}
if (oldni.email)
SAFE(read_string(&oldni.email, f));
if (oldni.url)
SAFE(read_string(&oldni.url, f));
SAFE(read_string(&oldni.usermask, f));
SAFE(read_string(&oldni.realname, f));
ni = makenick(oldni.nick, &ngi);
ni->last_usermask = oldni.usermask;
ni->last_realname = oldni.realname;
ni->last_quit = NULL;
ni->time_registered = oldni.reg;
ni->last_seen = oldni.seen;
init_password(&ngi->pass);
strbcpy(ngi->pass.password, oldni.pass);
ngi->url = oldni.url;
ngi->email = oldni.email;
ngi->access_count = oldni.naccess;
ngi->ignore_count = oldni.nignore;
if (version == 5)
oldni.flags &= 0x000000FF;
if (oldni.flags & 0x00000001)
ngi->flags |= NF_KILLPROTECT;
if (oldni.flags & 0x00000002)
ngi->flags |= NF_SECURE;
if (oldni.flags & 0x00000004) {
ni->status |= NS_VERBOTEN;
ni->nickgroup = 0;
}
if (oldni.flags & 0x00004008)
ni->status |= NS_NOEXPIRE;
if (oldni.flags & 0x00000010)
ngi->flags |= NF_PRIVATE;
if (oldni.flags & 0x00000020) {
strbcpy(ngi->suspend_who, "<unknown>");
ngi->suspend_reason = (char *)(
version==6 ? "Unknown (imported from Wrecked IRC Services)"
: "Unknown (imported from Magick IRC Services)"
);
ngi->suspend_time = time(NULL);
ngi->suspend_expires = 0;
ngi->flags |= NF_SUSPENDED;
}
if (oldni.flags & 0x00000080) {
ni->status |= 0x8000; /* Flag: this is a linked nick */
ni->nickgroup = 0;
}
if (oldni.flags & 0x00000100)
ngi->memos.memomax = 0;
if (oldni.flags & 0x00000200)
ngi->flags |= NF_HIDE_EMAIL;
ngi->access = smalloc(ngi->access_count * sizeof(char *));
for (j = 0; j < ngi->access_count; j++)
SAFE(read_string(&ngi->access[j], f));
ngi->ignore = smalloc(ngi->ignore_count * sizeof(char *));
for (j = 0; j < ngi->ignore_count; j++)
SAFE(read_string(&ngi->ignore[j], f));
} /* while more entries */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for 33..256 */
close_db(f);
/* Resolve links */
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
NickInfo *ni2;
const char *last_nick;
if (ni->status & 0x8000) {
ni->status &= ~0x8000;
ni2 = ni;
/* Find root nick (this will actually stop at the first nick
* in the path to the root that isn't marked as linked, but
* that's okay because such a nick will already have its
* nickgroup ID set correctly) */
do {
last_nick = ni2->last_usermask;
ni2 = get_nickinfo(last_nick);
} while (ni2 && (ni2->status & 0x8000));
/* Set nickgroup and last usermask field, or delete nick if an
* error occurred */
if (ni2 == ni) {
fprintf(stderr,
"Warning: dropping nick %s with circular link\n",
ni->nick);
del_nickinfo(ni);
} else if (!ni2) {
fprintf(stderr, "Warning: dropping nick %s linked to"
" nonexistent nick %s\n", ni->nick, last_nick);
del_nickinfo(ni);
} else {
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi)
del_nickgroupinfo(ngi);
ni->nickgroup = ni2->nickgroup;
ni->last_usermask = ni2->last_usermask;
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi) {
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick);
} else if (ni->nickgroup != 0) {
fprintf(stderr, "Warning: Nick group %d for nick %s not"
" found -- program bug? Output may be corrupt.",
ni->nickgroup, ni->nick);
}
}
}
}
}
/*************************************************************************/
static int16 magick_convert_level(int16 lev) {
if (lev >= 20)
return lev-10;
else if (lev >= 5)
return lev/2;
else if (lev >= 1)
return (lev+1)/2;
else
return lev;
};
static int16 wrecked_convert_level(int16 lev) {
if (lev >= 25)
return lev-15;
else if (lev >= 15)
return (lev-5)/10;
else if (lev >= 10)
return 4;
else if (lev >= 5)
return 3;
else if (lev >= 1)
return (lev+1) / 2;
else
return lev;
};
static void m14_load_chan(const char *dir, int32 version)
{
char *s;
dbFILE *f;
long i, j;
int c;
int16 tmp16;
int16 (*my_convert_level)(int16);
ChannelInfo *ci;
NickInfo *ni;
struct access_ {
short level;
short is_nick;
char *name;
} access;
struct akick_ {
short is_nick;
short pad;
char *name;
char *reason;
} akick;
struct oldci_ {
struct oldci_ *next, *prev;
char name[64];
char founder[32];
char pass[32];
char *desc;
char *url;
time_t reg;
time_t used;
long naccess;
struct access_ *access;
long nakick;
struct akick_ *akick;
char mlock_on[64], mlock_off[64];
long mlock_limit;
char *mlock_key;
char *topic;
char topic_setter[32];
time_t topic_time;
long flags;
short *levels;
long resv[3];
} oldci;
if (version == 6)
my_convert_level = wrecked_convert_level;
else
my_convert_level = magick_convert_level;
f = open_db_ver(dir, "chan.db", version, version, NULL);
for (i = 33; i < 256; i++) {
while ((c = getc_db(f)) == 1) {
SAFE(read_variable(oldci, f));
SAFE(read_string(&oldci.desc, f));
if (oldci.url)
SAFE(read_string(&oldci.url, f));
if (oldci.mlock_key)
SAFE(read_string(&oldci.mlock_key, f));
if (oldci.topic)
SAFE(read_string(&oldci.topic, f));
ci = makechan(oldci.name);
if (*oldci.founder) {
ni = get_nickinfo(oldci.founder);
if (!ni) {
fprintf(stderr,
"Warning: Founder %s for channel %s not found\n",
oldci.founder, oldci.name);
} else if (ni->status & NS_VERBOTEN) {
fprintf(stderr, "Warning: Founder %s for channel %s is a"
" forbidden nick\n", oldci.founder, oldci.name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Founder %s for channel %s has"
" an invalid nickname record (bug?)\n",
oldci.founder, oldci.name);
} else {
ci->founder = ni->nickgroup;
}
}
init_password(&ci->founderpass);
strbcpy(ci->founderpass.password, oldci.pass);
ci->desc = oldci.desc;
ci->url = oldci.url;
ci->time_registered = oldci.reg;
ci->last_used = oldci.used;
ci->access_count = oldci.naccess;
ci->akick_count = oldci.nakick;
ci->mlock.on = scalloc(64, 1);
strscpy(ci->mlock.on, oldci.mlock_on, 64);
ci->mlock.off = scalloc(64, 1);
strscpy(ci->mlock.off, oldci.mlock_off, 64);
ci->mlock.limit = oldci.mlock_limit;
ci->mlock.key = oldci.mlock_key;
ci->last_topic = oldci.topic;
strbcpy(ci->last_topic_setter, oldci.topic_setter);
ci->last_topic_time = oldci.topic_time;
if (version == 5)
oldci.flags &= 0x000003FF;
if (oldci.flags & 0x00000001)
ci->flags |= CF_KEEPTOPIC;
if (oldci.flags & 0x00000002)
ci->flags |= CF_SECUREOPS;
if (oldci.flags & 0x00000004)
ci->flags |= CF_PRIVATE;
if (oldci.flags & 0x00000008)
ci->flags |= CF_TOPICLOCK;
if (oldci.flags & 0x00000010)
ci->flags |= CF_RESTRICTED;
if (oldci.flags & 0x00000020)
ci->flags |= CF_LEAVEOPS;
if (oldci.flags & 0x00000040)
ci->flags |= CF_SECURE;
if (oldci.flags & 0x00000080)
ci->flags |= CF_VERBOTEN;
if (oldci.flags & 0x00000100) {
ci->flags |= CF_SUSPENDED;
strbcpy(ci->suspend_who, "<unknown>");
ci->suspend_reason = (char *)(
version==6 ? "Unknown (imported from Wrecked IRC Services)"
: "Unknown (imported from Magick IRC Services)"
);
ci->suspend_time = time(NULL);
ci->suspend_expires = 0;
}
if (oldci.flags & 0x00000400)
ci->flags |= CF_NOEXPIRE;
ci->access = scalloc(sizeof(ChanAccess), ci->access_count);
for (j = 0; j < oldci.naccess; j++) {
SAFE(read_variable(access, f));
ci->access[j].nickgroup = (access.is_nick == 1); /* in_use */
ci->access[j].level =
convert_acclev(my_convert_level(access.level));
}
for (j = 0; j < oldci.naccess; j++) {
SAFE(read_string(&s, f));
if (!s) {
ci->access[j].nickgroup = 0;
continue;
}
if (ci->access[j].nickgroup) {
ni = get_nickinfo(s);
ci->access[j].nickgroup = ni ? ni->nickgroup : 0;
}
}
ci->akick = scalloc(sizeof(AutoKick), oldci.nakick);
for (j = 0; j < oldci.nakick; j++) {
SAFE(read_variable(akick, f));
/* `lastused' field temporarily used to hold `is_nick' */
ci->akick[j].lastused = akick.is_nick;
ci->akick[j].reason = akick.reason;
strbcpy(ci->akick[j].who, "<unknown>");
ci->akick[j].set = time(NULL);
}
for (j = 0; j < oldci.nakick; j++) {
SAFE(read_string(&ci->akick[j].mask, f));
if (ci->akick[j].lastused) { /* was `is_nick' */
char *s = smalloc(strlen(ci->akick[j].mask)+5);
sprintf(s, "%s!*@*", ci->akick[j].mask);
free(ci->akick[j].mask);
ci->akick[j].mask = s;
}
ci->akick[j].lastused = 0;
if (ci->akick[j].reason) {
SAFE(read_string(&ci->akick[j].reason, f));
if (!ci->akick[j].mask && ci->akick[j].reason)
ci->akick[j].reason = NULL;
}
}
SAFE(read_int16(&tmp16, f));
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f));
/* Remove from list if founder does not exist and channel is
* not forbidden */
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) {
fprintf(stderr, "Ignoring channel %s (missing founder)\n",
ci->name);
del_channelinfo(ci);
}
} /* while more entries */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for 33..256 */
close_db(f);
}
/*************************************************************************/
static void m14_load_memo(const char *dir, int32 version)
{
char *s;
dbFILE *f;
struct memo_ {
char sender[32];
long number;
time_t time;
char *text;
long resv[4];
} memo;
struct memolist_ {
struct memolist_ *next, *prev;
char nick[32];
long n_memos;
Memo *memos;
long resv[4];
} memolist;
NickGroupInfo *ngi;
Memo *m = NULL;
long i, j, flags = 0;
int c;
f = open_db_ver(dir, "memo.db", version, version, NULL);
for (i = 33; i < 256; i++) {
while ((c = getc_db(f)) == 1) {
SAFE(read_variable(memolist, f));
ngi = get_nickgroupinfo_by_nick(memolist.nick);
if (ngi) {
ngi->memos.memos_count = memolist.n_memos;
m = scalloc(sizeof(*m), ngi->memos.memos_count);
ngi->memos.memos = m;
}
for (j = 0; j < memolist.n_memos; j++) {
SAFE(read_variable(memo, f));
if (version == 6) {
SAFE(read_variable(flags, f));
flags = memo.resv[0] & 1;
}
if (ngi) {
m[j].number = memo.number;
if (flags & 1)
m[j].flags |= MF_UNREAD;
m[j].time = memo.time;
strbcpy(m[j].sender, memo.sender);
}
}
for (j = 0; j < memolist.n_memos; j++) {
SAFE(read_string(&s, f));
if (ngi)
m[j].text = s;
}
}
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
}
close_db(f);
}
/*************************************************************************/
static void m14_load_sop(const char *dir, int32 version)
{
char nick[32];
dbFILE *f;
int16 n, i;
f = open_db_ver(dir, "sop.db", version, version, NULL);
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_buffer(nick, f));
set_os_priv(nick, NP_SERVADMIN);
}
close_db(f);
}
/*************************************************************************/
static void m14_load_akill(const char *dir, int32 version)
{
dbFILE *f;
int16 i, n;
MaskData *md;
struct akill_ {
char *mask;
char *reason;
char who[32];
time_t time;
} akill;
f = open_db_ver(dir, "akill.db", version, version, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
SAFE(read_variable(akill, f));
strbcpy(md[i].who, akill.who);
md[i].time = akill.time;
md[i].expires = 0;
}
for (i = 0; i < n; i++) {
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void m14_load_clone(const char *dir, int32 version)
{
dbFILE *f;
int16 i, n;
MaskData *md;
struct allow_ {
char *host;
int amount;
char *reason;
char who[32];
time_t time;
} allow;
f = open_db_ver(dir, "clone.db", version, version, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
SAFE(read_variable(allow, f));
strbcpy(md[i].who, allow.who);
md[i].limit = allow.amount;
md[i].time = allow.time;
md[i].expires = 0;
md[i].num = i+1;
}
for (i = 0; i < n; i++) {
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
add_maskdata(MD_EXCEPTION, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void m14_load_message(const char *dir, int32 version)
{
dbFILE *f;
int16 i, n;
NewsItem *news;
struct message_ {
char *text;
int type;
char who[32];
time_t time;
} msg;
f = open_db_ver(dir, "message.db", version, version, NULL);
SAFE(read_int16(&n, f));
news = scalloc(sizeof(*news), n);
for (i = 0; i < n; i++) {
SAFE(read_variable(msg, f));
news[i].type = msg.type;
strbcpy(news[i].who, msg.who);
news[i].time = msg.time;
}
for (i = 0; i < n; i++) {
SAFE(read_string(&news[i].text, f));
add_news(&news[i]);
}
close_db(f);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_magick_14b2(const char *dir)
{
FILE *f;
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/message.db", dir);
f = fopen(buf, "rb");
if (f) {
int ver;
ver = fgetc(f)<<24;
ver |= fgetc(f)<<16;
ver |= fgetc(f)<<8;
ver |= fgetc(f);
fclose(f);
if (ver == 5)
return "Magick 1.4b2";
}
return NULL;
}
static void load_magick_14b2(const char *dir, int verbose, int ac,
char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
m14_load_nick(dir, 5);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
m14_load_chan(dir, 5);
if (verbose)
fprintf(stderr, "Loading memo.db...\n");
m14_load_memo(dir, 5);
if (verbose)
fprintf(stderr, "Loading sop.db...\n");
m14_load_sop(dir, 5);
if (verbose)
fprintf(stderr, "Loading akill.db...\n");
m14_load_akill(dir, 5);
if (verbose)
fprintf(stderr, "Loading clone.db...\n");
m14_load_clone(dir, 5);
if (verbose)
fprintf(stderr, "Loading message.db...\n");
m14_load_message(dir, 5);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_wrecked_1_2(const char *dir)
{
FILE *f;
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/message.db", dir);
f = fopen(buf, "rb");
if (f) {
int ver;
ver = fgetc(f)<<24;
ver |= fgetc(f)<<16;
ver |= fgetc(f)<<8;
ver |= fgetc(f);
fclose(f);
if (ver == 6)
return "Wrecked 1.2.0";
}
return NULL;
}
static void load_wrecked_1_2(const char *dir, int verbose, int ac,
char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
m14_load_nick(dir, 6);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
m14_load_chan(dir, 6);
if (verbose)
fprintf(stderr, "Loading memo.db...\n");
m14_load_memo(dir, 6);
if (verbose)
fprintf(stderr, "Loading sop.db...\n");
m14_load_sop(dir, 6);
if (verbose)
fprintf(stderr, "Loading akill.db...\n");
m14_load_akill(dir, 6);
if (verbose)
fprintf(stderr, "Loading clone.db...\n");
m14_load_clone(dir, 6);
if (verbose)
fprintf(stderr, "Loading message.db...\n");
m14_load_message(dir, 6);
}
/*************************************************************************/
/*************************************************************************/
DBTypeInfo dbtype_magick_14b2 = {
"magick-1.4",
check_magick_14b2,
load_magick_14b2
};
DBTypeInfo dbtype_wrecked_1_2 = {
"wrecked-1.2",
check_wrecked_1_2,
load_wrecked_1_2
};
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

782
tools/convert-ptlink.c Normal file
View File

@ -0,0 +1,782 @@
/* Conversion routines for PTlink >= 2.13.x databases.
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#include "convert-db.h"
#if NICKMAX < 32
# error NICKMAX too small (must be >=32)
#elif CHANMAX < 64
# error CHANMAX too small (must be >=64)
#elif PASSMAX < 32
# error PASSMAX too small (must be >=32)
#endif
/*************************************************************************/
static void ptlink_load_nick(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int i, j, c, delete;
int16 tmp16, ver;
int32 tmp32, total, count;
NickInfo *ni;
NickGroupInfo *ngi;
char *s;
signed char ch;
snprintf(filename, sizeof(filename), "%s/nick.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&ver, f));
if (ch != -1 || ver < 6 || ver > 11) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int32(&total, f));
count = 0;
#if CLEAN_COMPILE
c = 0;
#endif
for (i = 0; i < 256; i++) {
while (ver >= 10 || (c = getc_db(f)) == 1) {
char nickbuf[32], passbuf[32], authbuf[16];
if (ver >= 9) {
int res = read_int32(&tmp32, f); /* SUID (broken) / SNID */
if (res < 0) {
if (ver >= 10) /* v10: no more int8 markers */
break;
else
SAFE(res);
}
}
SAFE(read_buffer(nickbuf, f));
/* The source (v2.26-eol.1) claims that duplicate nicknames can
* get stored in the database for unknown reasons, so watch for
* and delete them as needed */
delete = (get_nickinfo(nickbuf) != NULL);
ni = makenick(nickbuf, &ngi);
/* Use the SNID (file version 11) as a nickname group ID only
* if it's nonzero and unique. Never use the SUID (versions 9
* and 10) as the source code claims that it's broken. */
if (ver >= 11 && tmp32 && !get_nickgroupinfo(tmp32))
ni->nickgroup = ngi->id = (uint32)tmp32;
SAFE(read_buffer(passbuf, f));
init_password(&ngi->pass);
memcpy(ngi->pass.password, passbuf, sizeof(passbuf));
if (ver >= 7)
SAFE(read_buffer(authbuf, f));
SAFE(read_string(&ngi->url, f));
if (ver >= 7)
SAFE(read_string(&s, f)); /* temporary, unauthed E-mail */
else
s = NULL;
SAFE(read_string(&ngi->email, f));
if (s) {
ngi->last_email = ngi->email;
ngi->email = s;
}
SAFE(read_string(&s, f)); /* icq_number */
SAFE(read_string(&s, f)); /* location */
SAFE(read_string(&ni->last_usermask, f));
if (!ni->last_usermask)
ni->last_usermask = (char *)"@";
SAFE(read_string(&ni->last_realname, f));
if (!ni->last_realname)
ni->last_realname = (char *)"";
SAFE(read_string(&ni->last_quit, f));
SAFE(read_int32(&tmp32, f));
ni->time_registered = tmp32;
SAFE(read_int32(&tmp32, f)); /* last_identify */
SAFE(read_int32(&tmp32, f));
ni->last_seen = tmp32;
if (ver >= 7)
SAFE(read_int32(&tmp32, f)); /* last_email_request */
SAFE(read_int32(&tmp32, f)); /* birth_date */
SAFE(read_int16(&tmp16, f)); /* status */
if (tmp16 & 0x0002) {
ni->status |= NS_VERBOTEN;
del_nickgroupinfo(ngi);
ni->nickgroup = 0;
}
if (tmp16 & 0x0004)
ni->status |= NS_NOEXPIRE;
SAFE(read_int16(&tmp16, f)); /* crypt_method */
switch (tmp16) {
case 0: break;
case 2: ngi->pass.cipher = sstrdup("unix-crypt"); break;
case 3: ngi->pass.cipher = sstrdup("md5"); break;
case 1:
fprintf(stderr, "%s: `%s' password encrypted with"
" unsupported method JP2, resetting password"
" to nickname", filename, nickbuf);
/* fall through */
default:
if (tmp16 != 1) {
fprintf(stderr, "%s: `%s' password encrypted with"
" unsupported method %d, resetting password"
" to nickname", filename, nickbuf, tmp16);
}
strbcpy(ngi->pass.password, nickbuf);
break;
}
SAFE(read_int32(&tmp32, f)); /* news_mask */
SAFE(read_int16(&tmp16, f)); /* news_status */
SAFE(read_string(&ni->last_realmask, f)); /* link */
SAFE(read_int16(&tmp16, f)); /* linkcount */
if (ni->last_realmask) {
ni->nickgroup = 0;
SAFE(read_int16(&tmp16, f)); /* channelcount */
} else {
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ngi->flags |= NF_KILLPROTECT;
if (tmp32 & 0x00004002)
ngi->flags |= 0x80000000; /* suspended */
if (tmp32 & 0x00000008)
ngi->flags |= NF_MEMO_HARDMAX;
if (tmp32 & 0x00000010)
ngi->flags |= NF_MEMO_SIGNON;
if (tmp32 & 0x00000020)
ngi->flags |= NF_MEMO_RECEIVE;
if (tmp32 & 0x00000040)
ngi->flags |= NF_PRIVATE;
if (tmp32 & 0x00000080)
ngi->flags |= NF_HIDE_EMAIL;
if (tmp32 & 0x00000100)
ngi->flags |= NF_HIDE_MASK;
if (tmp32 & 0x00000200)
ngi->flags |= NF_HIDE_QUIT;
if (tmp32 & 0x00000400)
ngi->flags |= NF_KILL_QUICK;
if (tmp32 & 0x00000800)
ngi->flags |= NF_KILL_IMMED;
SAFE(read_int32(&tmp32, f)); /* online */
if (ngi->flags & 0x80000000) {
ngi->flags &= ~0x80000000;
SAFE(read_int32(&tmp32, f)); /* expires */
strbcpy(ngi->suspend_who, "<unknown>");
ngi->suspend_reason =
(char *)"Unknown (imported from PTlink IRC Services)";
ngi->suspend_time = time(NULL);
ngi->suspend_expires = tmp32;
ngi->flags |= NF_SUSPENDED;
}
SAFE(read_int16(&ngi->ajoin_count, f));
ngi->ajoin = scalloc(sizeof(char *), ngi->ajoin_count);
for (j = 0; j < ngi->ajoin_count; j++)
SAFE(read_string(&ngi->ajoin[j], f));
SAFE(read_int16(&ngi->memos.memos_count, f));
SAFE(read_int16(&ngi->memos.memomax, f));
if (ngi->memos.memos_count) {
Memo *memos;
memos = scalloc(sizeof(*memos), ngi->memos.memos_count);
ngi->memos.memos = memos;
for (j = 0; j < ngi->memos.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_int16(&tmp16, f)); /* notes.count */
j = tmp16;
SAFE(read_int16(&tmp16, f)); /* notes.max */
while (j--) /* notes.note[] */
SAFE(read_string(&s, f));
SAFE(read_int16(&tmp16, f)); /* channelcount */
SAFE(read_int16(&tmp16, f)); /* channelmax */
SAFE(read_int16(&tmp16, f));
switch (tmp16) {
case 0: ngi->language = LANG_EN_US; break;
case 1: ngi->language = LANG_PT; break;
case 2: ngi->language = LANG_TR; break;
case 3: ngi->language = LANG_DE; break;
case 4: ngi->language = LANG_IT; break;
}
}
if (delete) {
del_nickgroupinfo(ngi);
del_nickinfo(ni);
}
count++;
} /* while (getc_db(f) == 1) */
if (ver < 10 && c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
if (count != total) {
fprintf(stderr, "%s: warning: expected %d nicks, got %d\n",
filename, total, count);
fprintf(stderr, " This means that your data files may be corrupt."
" It may also be the\n"
" result of a bug in some versions of PTlink Services.\n");
}
/* Resolve links */
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
NickInfo *ni2;
const char *last_nick;
if (ni->last_realmask) {
ni2 = ni;
/* Find root nick (this will actually stop at the first nick
* in the path to the root that isn't marked as linked, but
* that's okay because such a nick will already have its
* nickgroup ID set correctly) */
do {
last_nick = ni2->last_realmask;
ni2 = get_nickinfo(last_nick);
} while (ni2 && ni2 != ni && ni2->last_realmask);
ni->last_realmask = NULL;
/* Set nickgroup, or delete nick if an error occurred */
if (ni2 == ni) {
fprintf(stderr,
"Warning: dropping nick %s with circular link\n",
ni->nick);
del_nickinfo(ni);
} else if (!ni2) {
fprintf(stderr, "Warning: dropping nick %s linked to"
" nonexistent nick %s\n", ni->nick, last_nick);
del_nickinfo(ni);
} else {
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi)
del_nickgroupinfo(ngi);
ni->nickgroup = ni2->nickgroup;
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi) {
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick);
} else if (ni->nickgroup != 0) {
fprintf(stderr, "Warning: Nick group %d for nick %s not"
" found -- program bug? Output may be corrupt.",
ni->nickgroup, ni->nick);
}
}
}
}
}
/*************************************************************************/
static struct {
int32 flag;
char mode;
} ptlink_cmodes[] = {
{ 0x00000001, 'i' },
{ 0x00000002, 'm' },
{ 0x00000004, 'n' },
{ 0x00000008, 'p' },
{ 0x00000010, 's' },
{ 0x00000020, 't' },
{ 0x00000040, 'k' },
{ 0x00000080, 'l' },
{ 0x00000200, 'R' },
{ 0x00000400, 'c' },
{ 0x00001000, 'O' },
{ 0x00002000, 'A' },
{ 0x00008000, 0 }, /* Like Unreal 'f': no dup lines within 10 secs */
{ 0, 0 }
};
static void ptlink_load_chan(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int i, j, c, C_MAX;
ChannelInfo *ci;
NickInfo *ni;
signed char ch;
int16 tmp16, ver;
int32 tmp32, total, count, mlock_on, mlock_off;
char *on, *off;
MemoInfo tmpmi;
snprintf(filename, sizeof(filename), "%s/chan.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&ver, f));
if (ch != -1 || ver < 7 || ver > 10) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
if (ver >= 9)
SAFE(read_int32(&total, f));
count = 0;
C_MAX = (ver<9 ? 256 : 65535);
for (i = 0; i < C_MAX; i++) {
char *s;
while ((c = getc_db(f)) == 1) {
char namebuf[64], passbuf[32], nickbuf[32];
if (ver >= 10)
SAFE(read_int32(&tmp32, f)); /* SCID */
SAFE(read_buffer(namebuf, f));
ci = makechan(namebuf);
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr,
"Warning: Founder %s for channel %s not found\n",
s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Founder %s for channel %s is a"
" forbidden nick\n", s, ci->name);
} else {
ci->founder = ni->nickgroup;
}
}
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" not found\n", s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is a forbidden nick\n", s, ci->name);
} else if (ni->nickgroup == ci->founder) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is the same as the founder, clearing\n",
s, ci->name);
} else {
ci->successor = ni->nickgroup;
}
}
SAFE(read_int16(&tmp16, f)); /* maxusers */
SAFE(read_int32(&tmp32, f)); /* maxtime */
SAFE(read_buffer(passbuf, f));
init_password(&ci->founderpass);
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf));
SAFE(read_string(&ci->desc, f));
if (!ci->desc)
ci->desc = (char *)"";
SAFE(read_string(&ci->url, f));
SAFE(read_string(&ci->email, f));
SAFE(read_int32(&tmp32, f));
ci->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ci->last_used = tmp32;
SAFE(read_string(&ci->last_topic, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(ci->last_topic_setter, nickbuf);
SAFE(read_int32(&tmp32, f));
ci->last_topic_time = tmp32;
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ci->flags |= CF_KEEPTOPIC;
if (tmp32 & 0x00000002)
ci->flags |= CF_SECUREOPS;
if (tmp32 & 0x00000004)
ci->flags |= CF_PRIVATE;
if (tmp32 & 0x00000008)
ci->flags |= CF_TOPICLOCK;
if (tmp32 & 0x00000010)
ci->flags |= CF_RESTRICTED;
if (tmp32 & 0x00000020)
ci->flags |= CF_LEAVEOPS;
if (tmp32 & 0x00000080)
ci->flags |= CF_VERBOTEN;
if (tmp32 & 0x00000200)
ci->flags |= CF_NOEXPIRE;
if (tmp32 & 0x00000800)
ci->flags |= CF_OPNOTICE;
SAFE(read_int16(&tmp16, f)); /* crypt_method */
switch (tmp16) {
case 0: break;
case 2: ci->founderpass.cipher = sstrdup("unix-crypt"); break;
case 3: ci->founderpass.cipher = sstrdup("md5"); break;
case 1:
fprintf(stderr, "%s: `%s' password encrypted with"
" unsupported method JP2, resetting password"
" to channel name", filename, namebuf);
/* fall through */
default:
if (tmp16 != 1) {
fprintf(stderr, "%s: `%s' password encrypted with"
" unsupported method %d, resetting password"
" to channel name", filename, namebuf, tmp16);
}
strbcpy(ci->founderpass.password, namebuf);
break;
}
if (tmp32 & 0x1000)
SAFE(read_int32(&tmp32, f)); /* drop_time */
SAFE(read_int16(&tmp16, f)); /* levels[] */
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&ci->access_count, f));
if (ci->access_count) {
ci->access = scalloc(ci->access_count, sizeof(ChanAccess));
for (j = 0; j < ci->access_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&ci->access[j].level, f));
SAFE(read_string(&s, f));
ci->access[j].level =
convert_acclev(ci->access[j].level);
if (s) {
ni = get_nickinfo(s);
if (ni)
ci->access[j].nickgroup = ni->nickgroup;
}
SAFE(read_string(&s, f)); /* who */
}
}
}
SAFE(read_int16(&ci->akick_count, f));
if (ci->akick_count) {
ci->akick = scalloc(ci->akick_count, sizeof(AutoKick));
for (j = 0; j < ci->akick_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_string(&ci->akick[j].mask, f));
SAFE(read_string(&ci->akick[j].reason, f));
SAFE(read_string(&s, f)); /* who */
strbcpy(ci->akick[j].who, s);
ci->akick[j].set = time(NULL);
SAFE(read_int32(&tmp32, f)); /* last_kick */
ci->akick[j].lastused = tmp32;
}
}
}
if (ver < 8) {
SAFE(read_int16(&tmp16, f));
mlock_on = (int32)tmp16 & 0xFFFF;
SAFE(read_int16(&tmp16, f));
mlock_off = (int32)tmp16 & 0xFFFF;
} else {
SAFE(read_int32(&mlock_on, f));
SAFE(read_int32(&mlock_off, f));
}
ci->mlock.on = on = scalloc(64, 1);
ci->mlock.off = off = scalloc(64, 1);
for (j = 0; ptlink_cmodes[j].flag != 0; j++) {
if (mlock_on & ptlink_cmodes[j].flag)
*on++ = ptlink_cmodes[j].mode;
if (mlock_off & ptlink_cmodes[j].flag)
*off++ = ptlink_cmodes[j].mode;
}
*on = 0;
*off = 0;
SAFE(read_int32(&ci->mlock.limit, f));
SAFE(read_string(&ci->mlock.key, f));
SAFE(read_int16(&tmpmi.memos_count, f));
SAFE(read_int16(&tmp16, f)); /* memomax */
if (tmpmi.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), tmpmi.memos_count);
tmpmi.memos = memos;
for (j = 0; j < tmpmi.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_string(&ci->entry_message, f));
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) {
fprintf(stderr, "Ignoring channel %s (missing founder)\n",
ci->name);
del_channelinfo(ci);
}
count++;
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
if (ver >= 9 && count != total) {
fprintf(stderr, "%s: warning: expected %d channels, got %d\n",
filename, total, count);
fprintf(stderr, " This means that your data files may be corrupt."
" It may also be the\n"
" result of a bug in some versions of PTlink Services.\n");
}
}
/*************************************************************************/
static void ptlink_load_oper(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int16 i, n, tmp16;
int32 tmp32;
char *s;
signed char ch;
snprintf(filename, sizeof(filename), "%s/oper.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&tmp16, f));
if (ch != -1 || tmp16 < 1 || tmp16 > 2) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVADMIN);
}
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVOPER);
}
SAFE(read_int32(&maxusercnt, f));
SAFE(read_int32(&tmp32, f));
maxusertime = tmp32;
close_db(f);
}
/*************************************************************************/
static void ptlink_load_akill(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int16 tmp16, i, n;
int32 tmp32;
signed char ch;
MaskData *md;
snprintf(filename, sizeof(filename), "%s/akill.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&tmp16, f));
if (ch != -1 || tmp16 != 1) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(md[i].who, nickbuf);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void ptlink_load_sqline(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int16 tmp16, i, n;
int32 tmp32;
signed char ch;
MaskData *md;
snprintf(filename, sizeof(filename), "%s/sqline.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&tmp16, f));
if (ch != -1 || tmp16 != 1) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(md[i].who, nickbuf);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_SQLINE, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void ptlink_load_sxline(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int16 tmp16, i, n;
int32 tmp32;
signed char ch;
MaskData *md;
snprintf(filename, sizeof(filename), "%s/sxline.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&tmp16, f));
if (ch != -1 || tmp16 != 1) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(md[i].who, nickbuf);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_SGLINE, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void ptlink_load_news(const char *dir)
{
char filename[PATH_MAX+1];
dbFILE *f;
int16 tmp16, i, n;
int32 tmp32;
signed char ch;
NewsItem *news;
snprintf(filename, sizeof(filename), "%s/news.db", dir);
if (!(f = open_db(filename, "r", 0)))
return;
SAFE(read_int8(&ch, f));
SAFE(read_int16(&tmp16, f));
if (ch != -1 || tmp16 != 1) {
fprintf(stderr, "Wrong version number on %s\n", filename);
exit(1);
}
SAFE(read_int16(&n, f));
news = scalloc(sizeof(*news), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
SAFE(read_int16(&news[i].type, f));
SAFE(read_int32(&news[i].num, f));
SAFE(read_string(&news[i].text, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(news[i].who, nickbuf);
SAFE(read_int32(&tmp32, f));
news[i].time = tmp32;
add_news(&news[i]);
}
close_db(f);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_ptlink(const char *dir)
{
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/vline.db", dir);
if (access(buf, R_OK) == 0)
return "PTlink";
return NULL;
}
static void load_ptlink(const char *dir, int verbose, int ac, char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
ptlink_load_nick(dir);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
ptlink_load_chan(dir);
if (verbose)
fprintf(stderr, "Loading oper.db...\n");
ptlink_load_oper(dir);
if (verbose)
fprintf(stderr, "Loading akill.db...\n");
ptlink_load_akill(dir);
if (verbose)
fprintf(stderr, "Loading sqline.db...\n");
ptlink_load_sqline(dir);
if (verbose)
fprintf(stderr, "Loading sxline.db...\n");
ptlink_load_sxline(dir);
if (verbose)
fprintf(stderr, "Loading news.db...\n");
ptlink_load_news(dir);
}
/*************************************************************************/
/*************************************************************************/
DBTypeInfo dbtype_ptlink = {
"ptlink",
check_ptlink,
load_ptlink
};
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

1230
tools/convert-sirv.c Normal file

File diff suppressed because it is too large Load Diff

836
tools/convert-trircd.c Normal file
View File

@ -0,0 +1,836 @@
/* Conversion routines for trircd Services program (version 4.26).
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#include "convert-db.h"
#if NICKMAX < 32
# error NICKMAX too small (must be >=32)
#elif CHANMAX < 64
# error CHANMAX too small (must be >=64)
#elif PASSMAX < 32
# error PASSMAX too small (must be >=32)
#endif
/*************************************************************************/
static void trircd_load_nick(const char *dir)
{
dbFILE *f;
int i, j, c;
int16 tmp16;
int32 tmp32;
NickInfo *ni;
NickGroupInfo *ngi;
f = open_db_ver(dir, "nick.db", 22, 25, NULL);
for (i = 0; i < 256; i++) {
while ((c = getc_db(f)) == 1) {
char nickbuf[32], passbuf[32];
SAFE(read_buffer(nickbuf, f));
ni = makenick(nickbuf, &ngi);
SAFE(read_buffer(passbuf, f));
init_password(&ngi->pass);
memcpy(ngi->pass.password, passbuf, sizeof(passbuf));
SAFE(read_string(&ngi->url, f));
SAFE(read_string(&ngi->email, f));
SAFE(read_string(&ni->last_usermask, f));
if (!ni->last_usermask)
ni->last_usermask = (char *)"@";
SAFE(read_string(&ni->last_realname, f));
if (!ni->last_realname)
ni->last_realname = (char *)"";
SAFE(read_string(&ni->last_quit, f));
SAFE(read_int32(&tmp32, f));
ni->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ni->last_seen = tmp32;
SAFE(read_int16(&tmp16, f)); /* status */
if (tmp16 & 0x0001)
ngi->pass.cipher = sstrdup("md5");
if (tmp16 & 0x0002) {
ni->status |= NS_VERBOTEN;
del_nickgroupinfo(ngi);
ni->nickgroup = 0;
}
if (tmp16 & 0x0004)
ni->status |= NS_NOEXPIRE;
SAFE(read_string(&ni->last_realmask, f)); /* link */
SAFE(read_int16(&tmp16, f)); /* linkcount */
if (ni->last_realmask) {
ni->nickgroup = 0;
SAFE(read_int16(&tmp16, f)); /* channelcount */
} else {
void *tmpptr;
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ngi->flags |= NF_KILLPROTECT;
if (tmp32 & 0x00000002)
ngi->flags |= NF_SECURE;
if (tmp32 & 0x00000008)
ngi->flags |= NF_MEMO_HARDMAX;
if (tmp32 & 0x00000010)
ngi->flags |= NF_MEMO_SIGNON;
if (tmp32 & 0x00000020)
ngi->flags |= NF_MEMO_RECEIVE;
if (tmp32 & 0x00000040)
ngi->flags |= NF_PRIVATE;
if (tmp32 & 0x00000080)
ngi->flags |= NF_HIDE_EMAIL;
if (tmp32 & 0x00000100)
ngi->flags |= NF_HIDE_MASK;
if (tmp32 & 0x00000200)
ngi->flags |= NF_HIDE_QUIT;
if (tmp32 & 0x00000400)
ngi->flags |= NF_KILL_QUICK;
if (tmp32 & 0x00000800)
ngi->flags |= NF_KILL_IMMED;
if (tmp32 & 0x80000000)
ngi->flags |= NF_MEMO_FWD | NF_MEMO_FWDCOPY;
SAFE(read_ptr(&tmpptr, f));
if (tmpptr) {
SAFE(read_buffer(nickbuf, f));
strbcpy(ngi->suspend_who, nickbuf);
SAFE(read_string(&ngi->suspend_reason, f));
SAFE(read_int32(&tmp32, f));
ngi->suspend_time = tmp32;
SAFE(read_int32(&tmp32, f));
ngi->suspend_expires = tmp32;
ngi->flags |= NF_SUSPENDED;
}
SAFE(read_int16(&ngi->access_count, f));
if (ngi->access_count) {
char **access;
access = scalloc(sizeof(char *), ngi->access_count);
ngi->access = access;
for (j = 0; j < ngi->access_count; j++, access++)
SAFE(read_string(access, f));
}
SAFE(read_int16(&ngi->memos.memos_count, f));
SAFE(read_int16(&ngi->memos.memomax, f));
if (ngi->memos.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), ngi->memos.memos_count);
ngi->memos.memos = memos;
for (j = 0; j < ngi->memos.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_int16(&tmp16, f)); /* channelcount */
SAFE(read_int16(&tmp16, f)); /* channelmax */
SAFE(read_int16(&ngi->language, f));
}
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
/* Resolve links */
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
NickInfo *ni2;
const char *last_nick;
if (ni->last_realmask) {
ni2 = ni;
/* Find root nick (this will actually stop at the first nick
* in the path to the root that isn't marked as linked, but
* that's okay because such a nick will already have its
* nickgroup ID set correctly) */
do {
last_nick = ni2->last_realmask;
ni2 = get_nickinfo(last_nick);
} while (ni2 && ni2 != ni && ni2->last_realmask);
ni->last_realmask = NULL;
/* Set nickgroup, or delete nick if an error occurred */
if (ni2 == ni) {
fprintf(stderr,
"Warning: dropping nick %s with circular link\n",
ni->nick);
del_nickinfo(ni);
} else if (!ni2) {
fprintf(stderr, "Warning: dropping nick %s linked to"
" nonexistent nick %s\n", ni->nick, last_nick);
del_nickinfo(ni);
} else {
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi)
del_nickgroupinfo(ngi);
ni->nickgroup = ni2->nickgroup;
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi) {
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick);
} else if (ni->nickgroup != 0) {
fprintf(stderr, "Warning: Nick group %d for nick %s not"
" found -- program bug? Output may be corrupt.",
ni->nickgroup, ni->nick);
}
}
}
}
}
/*************************************************************************/
static void trircd_load_ajoin(const char *dir)
{
dbFILE *f;
int c;
int16 j, tmp16;
int32 tmp32;
void *tmpptr;
char *s;
NickGroupInfo *ngi;
f = open_db_ver(dir, "ajoin.db", 25, 25, NULL);
while ((c = getc_db(f)) == 1) {
int is_root; /* is this a root nick (should we store data)? */
char nickbuf[32];
SAFE(read_buffer(nickbuf, f));
ngi = get_nickgroupinfo_by_nick(nickbuf);
is_root = ngi && stricmp(nickbuf, ngi_mainnick(ngi)) == 0;
SAFE(read_int16(&tmp16, f)); /* ajoincount */
if (is_root) {
ngi->ajoin_count = tmp16;
ngi->ajoin = scalloc(sizeof(char *), tmp16);
for (j = 0; j < tmp16; j++)
SAFE(read_string(&ngi->ajoin[j], f));
} else {
for (j = 0; j < tmp16; j++)
SAFE(read_string(&s, f));
}
SAFE(read_ptr((void *)&tmpptr, f)); /* forbidinfo */
if (tmpptr) {
SAFE(read_buffer(nickbuf, f)); /* forbidder */
SAFE(read_string(&s, f)); /* forbid_message */
}
SAFE(read_int32(&tmp32, f)); /* authcode */
SAFE(read_int16(&tmp16, f)); /* authmode */
if (tmp16 & 3) /* NH_AUTHENTIC | NH_OLDAUTH */
tmp32 = 0;
if (is_root) {
ngi->authcode = tmp32;
ngi->authset = time(NULL);
}
SAFE(read_int16(&tmp16, f)); /* ignorecount */
if (is_root) {
ngi->ignore_count = tmp16;
ngi->ignore = scalloc(sizeof(char *), tmp16);
for (j = 0; j < ngi->ignore_count; j++) {
SAFE(read_int16(&tmp16, f));
if (tmp16)
SAFE(read_string(&ngi->ignore[j], f));
}
} else {
for (j = tmp16; j > 0; j--) {
SAFE(read_int16(&tmp16, f));
if (tmp16)
SAFE(read_string(&s, f));
}
}
SAFE(read_string(&s, f)); /* infomsg */
if (is_root)
ngi->info = s;
SAFE(read_int32(&tmp32, f)); /* expiredelay */
SAFE(read_int16(&tmp16, f)); /* count for memo expire */
for (j = 0; j < tmp16; j++)
SAFE(read_int32(&tmp32, f)); /* memo.expiration */
} /* while (getc_db(f) == 1) */
if (c != -1)
fprintf(stderr, "Warning: %s may be corrupt.\n", f->filename);
close_db(f);
}
/*************************************************************************/
static struct {
int32 flag;
char mode;
} cmodes[] = {
{ 0x00000001, 'i' },
{ 0x00000002, 'm' },
{ 0x00000004, 'n' },
{ 0x00000008, 'p' },
{ 0x00000010, 's' },
{ 0x00000020, 't' },
{ 0x00000040, 'k' },
{ 0x00000080, 'l' },
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'c' },
{ 0x00000800, 'O' },
{ 0x00001000, 'A' },
{ 0x00002000, 'z' },
{ 0x00004000, 'Q' },
{ 0x00008000, 'K' },
{ 0x00010000, 'V' },
{ 0x00020000, 'H' },
{ 0x00040000, 'C' },
{ 0x00080000, 'N' },
{ 0x00100000, 'S' },
{ 0x00200000, 'G' },
{ 0x00400000, 'u' },
{ 0x00800000, 'f' },
{ 0x01000000, 'M' },
{ 0, 0 }
};
static void trircd_load_chan(const char *dir)
{
dbFILE *f;
int i, j, c;
ChannelInfo *ci;
NickInfo *ni;
int32 tmp32, mlock_on, mlock_off;
MemoInfo tmpmi;
void *tmpptr;
f = open_db_ver(dir, "chan.db", 22, 25, NULL);
for (i = 0; i < 256; i++) {
int16 tmp16;
char *s, *on, *off;
char namebuf[64], passbuf[32], nickbuf[32];
while ((c = getc_db(f)) == 1) {
SAFE(read_buffer(namebuf, f));
ci = makechan(namebuf);
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr,
"Warning: Founder %s for channel %s not found\n",
s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Founder %s for channel %s is a"
" forbidden nick\n", s, ci->name);
} else {
ci->founder = ni->nickgroup;
}
}
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" not found\n", s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is a forbidden nick\n", s, ci->name);
} else if (ni->nickgroup == ci->founder) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is the same as the founder, clearing\n",
s, ci->name);
} else {
ci->successor = ni->nickgroup;
}
}
SAFE(read_buffer(passbuf, f));
init_password(&ci->founderpass);
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf));
SAFE(read_string(&ci->desc, f));
if (!ci->desc)
ci->desc = (char *)"";
SAFE(read_string(&ci->url, f));
SAFE(read_string(&ci->email, f));
SAFE(read_int32(&tmp32, f));
ci->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ci->last_used = tmp32;
SAFE(read_string(&ci->last_topic, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(ci->last_topic_setter, nickbuf);
SAFE(read_int32(&tmp32, f));
ci->last_topic_time = tmp32;
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ci->flags |= CF_KEEPTOPIC;
if (tmp32 & 0x00000002)
ci->flags |= CF_SECUREOPS;
if (tmp32 & 0x00000004)
ci->flags |= CF_PRIVATE;
if (tmp32 & 0x00000008)
ci->flags |= CF_TOPICLOCK;
if (tmp32 & 0x00000010)
ci->flags |= CF_RESTRICTED;
if (tmp32 & 0x00000020)
ci->flags |= CF_LEAVEOPS;
if (tmp32 & 0x00000040)
ci->flags |= CF_SECURE;
if (tmp32 & 0x00000080)
ci->flags |= CF_VERBOTEN;
if (tmp32 & 0x00000100)
ci->founderpass.cipher = sstrdup("md5");
if (tmp32 & 0x00000200)
ci->flags |= CF_NOEXPIRE;
if (tmp32 & 0x01000000)
ci->flags |= CF_HIDE_TOPIC;
if (tmp32 & 0x04000000)
ci->flags |= CF_HIDE_MLOCK;
if (tmp32 & 0x80000000)
ci->flags |= CF_HIDE_EMAIL;
SAFE(read_ptr((void **)&tmpptr, f));
if (tmpptr) {
SAFE(read_buffer(nickbuf, f));
strbcpy(ci->suspend_who, nickbuf);
SAFE(read_string(&ci->suspend_reason, f));
SAFE(read_int32(&tmp32, f));
ci->suspend_time = tmp32;
SAFE(read_int32(&tmp32, f));
ci->suspend_expires = tmp32;
ci->flags |= CF_SUSPENDED;
}
SAFE(read_int16(&tmp16, f)); /* n_levels */
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f)); /* levels */
SAFE(read_int16(&ci->access_count, f));
if (ci->access_count) {
ci->access = scalloc(ci->access_count, sizeof(ChanAccess));
for (j = 0; j < ci->access_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&ci->access[j].level, f));
SAFE(read_string(&s, f));
ci->access[j].level =
convert_acclev(ci->access[j].level);
if (s) {
ni = get_nickinfo(s);
if (ni)
ci->access[j].nickgroup = ni->nickgroup;
}
}
}
}
SAFE(read_int16(&ci->akick_count, f));
if (ci->akick_count) {
ci->akick = scalloc(ci->akick_count, sizeof(AutoKick));
for (j = 0; j < ci->akick_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&tmp16, f)); /* is_nick */
SAFE(read_string(&s, f));
if (tmp16 && s) {
ci->akick[j].mask = smalloc(strlen(s)+5);
sprintf(ci->akick[j].mask, "%s!*@*", s);
} else {
ci->akick[j].mask = s;
}
SAFE(read_string(&s, f));
SAFE(read_buffer(nickbuf, f));
if (ci->akick[j].mask) {
ci->akick[j].reason = s;
strbcpy(ci->akick[j].who, nickbuf);
ci->akick[j].set = time(NULL);
}
}
}
}
SAFE(read_int32(&mlock_on, f));
SAFE(read_int32(&mlock_off, f));
ci->mlock.on = on = scalloc(64, 1);
ci->mlock.off = off = scalloc(64, 1);
for (j = 0; cmodes[j].flag != 0; j++) {
if (mlock_on & cmodes[j].flag)
*on++ = cmodes[j].mode;
if (mlock_off & cmodes[j].flag)
*off++ = cmodes[j].mode;
}
*on = 0;
*off = 0;
SAFE(read_int32(&ci->mlock.limit, f));
SAFE(read_string(&ci->mlock.key, f));
SAFE(read_int16(&tmpmi.memos_count, f));
SAFE(read_int16(&tmp16, f)); /* memomax */
if (tmpmi.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), tmpmi.memos_count);
tmpmi.memos = memos;
for (j = 0; j < tmpmi.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&memos->flags, f));
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_string(&ci->entry_message, f));
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) {
fprintf(stderr, "Ignoring channel %s (missing founder)\n",
ci->name);
del_channelinfo(ci);
}
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
}
/*************************************************************************/
static void trircd_load_cforbid(const char *dir)
{
dbFILE *f;
int c;
f = open_db_ver(dir, "cforbid.db", 25, 25, NULL);
while ((c = getc_db(f)) == 1) {
char chanbuf[64];
void *tmpptr;
int8 tmp8;
int16 i, tmp16;
int32 tmp32;
char *s;
ChannelInfo *ci;
SAFE(read_buffer(chanbuf, f));
ci = get_channelinfo(chanbuf);
if (!ci) {
fprintf(stderr, "Warning: cforbid data for nonexistent channel"
" %s, ignoring\n", chanbuf);
}
SAFE(read_ptr(&tmpptr, f)); /* forbidinfo */
if (tmpptr) {
char nickbuf[32];
SAFE(read_buffer(nickbuf, f)); /* forbidder */
SAFE(read_string(&s, f)); /* forbid_message */
}
SAFE(read_int16(&tmp16, f)); /* akickcount */
if (ci && tmp16 != ci->akick_count) {
fprintf(stderr, "Warning: autokick count mismatch (chan.db: %d,"
" cforbid.db: %d); databases may be corrupt\n",
ci->akick_count, tmp16);
}
for (i = 0; i < tmp16; i++) {
int16 in_use;
SAFE(read_int16(&in_use, f));
if (in_use) {
if (ci && i < ci->akick_count) {
SAFE(read_int32(&tmp32, f));
ci->akick[i].set = tmp32;
SAFE(read_int32(&tmp32, f));
ci->akick[i].lastused = tmp32;
} else {
SAFE(read_int32(&tmp32, f));
SAFE(read_int32(&tmp32, f));
}
SAFE(read_int32(&tmp32, f)); /* expires */
}
}
SAFE(read_int16(&tmp16, f)); /* accesscount */
for (i = tmp16; i > 0; i--) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16)
SAFE(read_int32(&tmp32, f)); /* last_used */
}
SAFE(read_int8(&tmp8, f));
if (tmp8 != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* while (getc_db(f) == 1) */
if (c != -1)
fprintf(stderr, "Warning: %s may be corrupt.\n", f->filename);
close_db(f);
}
/*************************************************************************/
static void trircd_load_oper(const char *dir)
{
dbFILE *f;
int16 i, n;
int32 tmp32;
int8 tmp8;
char *s;
f = open_db_ver(dir, "oper.db", 22, 25, NULL);
/* servadmin */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVADMIN);
}
/* servoper */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVOPER);
}
SAFE(read_int32(&maxusercnt, f));
SAFE(read_int32(&tmp32, f));
maxusertime = tmp32;
SAFE(read_int8(&tmp8, f));
no_supass = tmp8;
if (!no_supass) {
char passbuf[32];
SAFE(read_buffer(passbuf, f));
memcpy(supass.password, passbuf, sizeof(passbuf));
}
close_db(f);
}
/*************************************************************************/
static void trircd_load_akill(const char *dir)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "akill.db", 22, 25, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void trircd_load_exclude(const char *dir)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "exclude.db", 22, 25, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_EXCLUDE, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void trircd_load_exception(const char *dir)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "exception.db", 22, 25, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_int16(&md[i].limit, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void trircd_load_news(const char *dir)
{
dbFILE *f;
int16 i, n;
NewsItem *news;
f = open_db_ver(dir, "news.db", 22, 25, NULL);
SAFE(read_int16(&n, f));
news = scalloc(sizeof(*news), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_int16(&news[i].type, f));
SAFE(read_int32(&news[i].num, f));
SAFE(read_string(&news[i].text, f));
SAFE(read_buffer(nick, f));
strbcpy(news[i].who, nick);
SAFE(read_int32(&tmp32, f));
news[i].time = tmp32;
add_news(&news[i]);
}
close_db(f);
}
/*************************************************************************/
static void trircd_load_sline(const char *dir, const unsigned char type)
{
char filenamebuf[16];
dbFILE *f;
int32 ver;
int16 i, n;
MaskData *md;
snprintf(filenamebuf, sizeof(filenamebuf), "s%cline.db", type);
f = open_db_ver(dir, filenamebuf, 22, 25, &ver);
read_int16(&n, f);
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nickbuf[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(md[i].who, nickbuf);
if (ver >= 23) {
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
} else {
md[i].time = time(NULL);
}
if (md[i].mask)
add_maskdata(type, &md[i]);
}
close_db(f);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_trircd(const char *dir)
{
char buf[PATH_MAX+1];
FILE *f;
snprintf(buf, sizeof(buf), "%s/cforbid.db", dir);
if ((f = fopen(buf, "rb")) != NULL) {
int32 ver;
ver = fgetc(f)<<24;
ver |= fgetc(f)<<16;
ver |= fgetc(f)<< 8;
ver |= fgetc(f);
fclose(f);
if (ver == 25)
return "trircd-4.26";
}
return NULL;
}
static void load_trircd(const char *dir, int verbose, int ac, char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
trircd_load_nick(dir);
if (verbose)
fprintf(stderr, "Loading ajoin.db...\n");
trircd_load_ajoin(dir);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
trircd_load_chan(dir);
if (verbose)
fprintf(stderr, "Loading cforbid.db...\n");
trircd_load_cforbid(dir);
if (verbose)
fprintf(stderr, "Loading oper.db...\n");
trircd_load_oper(dir);
if (verbose)
fprintf(stderr, "Loading akill.db...\n");
trircd_load_akill(dir);
if (verbose)
fprintf(stderr, "Loading exclude.db...\n");
trircd_load_exclude(dir);
if (verbose)
fprintf(stderr, "Loading exception.db...\n");
trircd_load_exception(dir);
if (verbose)
fprintf(stderr, "Loading news.db...\n");
trircd_load_news(dir);
if (verbose)
fprintf(stderr, "Loading sgline.db...\n");
trircd_load_sline(dir, 'g');
if (verbose)
fprintf(stderr, "Loading sqline.db...\n");
trircd_load_sline(dir, 'q');
if (verbose)
fprintf(stderr, "Loading szline.db...\n");
trircd_load_sline(dir, 'z');
}
/*************************************************************************/
/*************************************************************************/
DBTypeInfo dbtype_trircd_4_26 = {
"trircd-4.26",
check_trircd,
load_trircd
};
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

734
tools/convert-ver8.c Normal file
View File

@ -0,0 +1,734 @@
/* Conversion routines for datafile version 8 based databases (Daylight and
* IRCS 1.2).
*
* IRC Services is copyright (c) 1996-2009 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file GPL.txt for
* details.
*/
#include "convert-db.h"
#if NICKMAX < 32
# error NICKMAX too small (must be >=32)
#elif CHANMAX < 204
# error CHANMAX too small (must be >=204)
#elif PASSMAX < 32
# error PASSMAX too small (must be >=32)
#endif
#define TYPE_DAYLIGHT 0
#define TYPE_IRCS 1
/*************************************************************************/
static void ver8_load_nick(const char *dir, int type)
{
dbFILE *f;
int i, j, c;
int16 tmp16;
int32 tmp32;
NickInfo *ni;
NickGroupInfo *ngi;
f = open_db_ver(dir, "nick.db", 8, 8, NULL);
for (i = 0; i < 256; i++) {
while ((c = getc_db(f)) == 1) {
char nickbuf[32];
SAFE(read_buffer(nickbuf, f));
ni = makenick(nickbuf, &ngi);
init_password(&ngi->pass);
if (type == TYPE_IRCS) {
char passbuf[16];
SAFE(read_buffer(passbuf, f));
memcpy(ngi->pass.password, passbuf, sizeof(passbuf));
} else {
char passbuf[32];
SAFE(read_buffer(passbuf, f));
memcpy(ngi->pass.password, passbuf, sizeof(passbuf));
}
SAFE(read_string(&ngi->url, f));
SAFE(read_string(&ngi->email, f));
SAFE(read_string(&ni->last_usermask, f));
if (!ni->last_usermask)
ni->last_usermask = (char *)"@";
SAFE(read_string(&ni->last_realname, f));
if (!ni->last_realname)
ni->last_realname = (char *)"";
SAFE(read_string(&ni->last_quit, f));
SAFE(read_int32(&tmp32, f));
ni->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ni->last_seen = tmp32;
SAFE(read_int16(&tmp16, f)); /* status */
if (tmp16 & 0x0001)
ngi->pass.cipher = sstrdup("md5");
if (tmp16 & 0x0002) {
ni->status |= NS_VERBOTEN;
del_nickgroupinfo(ngi);
ni->nickgroup = 0;
}
if (tmp16 & 0x0004)
ni->status |= NS_NOEXPIRE;
SAFE(read_string(&ni->last_realmask, f)); /* link */
SAFE(read_int16(&tmp16, f)); /* linkcount */
if (ni->last_realmask) {
ni->nickgroup = 0;
SAFE(read_int16(&tmp16, f)); /* channelcount */
} else {
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ngi->flags |= NF_KILLPROTECT;
if (tmp32 & 0x00000002)
ngi->flags |= NF_SECURE;
if (tmp32 & 0x00000008)
ngi->flags |= NF_MEMO_HARDMAX;
if (tmp32 & 0x00000010)
ngi->flags |= NF_MEMO_SIGNON;
if (tmp32 & 0x00000020)
ngi->flags |= NF_MEMO_RECEIVE;
if (tmp32 & 0x00000040)
ngi->flags |= NF_PRIVATE;
if (tmp32 & 0x00000080)
ngi->flags |= NF_HIDE_EMAIL;
if (tmp32 & 0x00000100)
ngi->flags |= NF_HIDE_MASK;
if (tmp32 & 0x00000200)
ngi->flags |= NF_HIDE_QUIT;
if (tmp32 & 0x00000400)
ngi->flags |= NF_KILL_QUICK;
if (tmp32 & 0x00000800)
ngi->flags |= NF_KILL_IMMED;
SAFE(read_int16(&ngi->access_count, f));
if (ngi->access_count) {
char **access;
access = scalloc(sizeof(char *), ngi->access_count);
ngi->access = access;
for (j = 0; j < ngi->access_count; j++, access++)
SAFE(read_string(access, f));
}
SAFE(read_int16(&ngi->memos.memos_count, f));
SAFE(read_int16(&ngi->memos.memomax, f));
if (ngi->memos.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), ngi->memos.memos_count);
ngi->memos.memos = memos;
for (j = 0; j < ngi->memos.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&tmp16, f));
if (tmp16 & 1)
memos->flags |= MF_UNREAD;
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_int16(&tmp16, f)); /* channelcount */
SAFE(read_int16(&tmp16, f)); /* channelmax */
SAFE(read_int16(&tmp16, f));
switch (tmp16) {
case 0: ngi->language = LANG_EN_US; break;
case 2: ngi->language = LANG_JA_EUC; break;
case 3: ngi->language = LANG_JA_SJIS; break;
case 4: ngi->language = LANG_ES; break;
case 5: ngi->language = LANG_PT; break;
case 6: ngi->language = LANG_FR; break;
case 7: ngi->language = LANG_TR; break;
case 8: ngi->language = LANG_IT; break;
}
}
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
/* Resolve links */
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
NickInfo *ni2;
const char *last_nick;
if (ni->last_realmask) {
ni2 = ni;
/* Find root nick (this will actually stop at the first nick
* in the path to the root that isn't marked as linked, but
* that's okay because such a nick will already have its
* nickgroup ID set correctly) */
do {
last_nick = ni2->last_realmask;
ni2 = get_nickinfo(last_nick);
} while (ni2 && ni2 != ni && ni2->last_realmask);
ni->last_realmask = NULL;
/* Set nickgroup, or delete nick if an error occurred */
if (ni2 == ni) {
fprintf(stderr,
"Warning: dropping nick %s with circular link\n",
ni->nick);
del_nickinfo(ni);
} else if (!ni2) {
fprintf(stderr, "Warning: dropping nick %s linked to"
" nonexistent nick %s\n", ni->nick, last_nick);
del_nickinfo(ni);
} else {
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi)
del_nickgroupinfo(ngi);
ni->nickgroup = ni2->nickgroup;
ngi = get_nickgroupinfo(ni->nickgroup);
if (ngi) {
ARRAY_EXTEND(ngi->nicks);
strbcpy(ngi->nicks[ngi->nicks_count-1], ni->nick);
} else if (ni->nickgroup != 0) {
fprintf(stderr, "Warning: Nick group %d for nick %s not"
" found -- program bug? Output may be corrupt.",
ni->nickgroup, ni->nick);
}
}
}
}
}
/*************************************************************************/
static struct {
int32 flag;
char mode;
} cmodes[] = {
{ 0x00000001, 'i' },
{ 0x00000002, 'm' },
{ 0x00000004, 'n' },
{ 0x00000008, 'p' },
{ 0x00000010, 's' },
{ 0x00000020, 't' },
{ 0x00000040, 'k' },
{ 0x00000080, 'l' },
{ 0x00000100, 'R' },
{ 0x00000200, 0 }, /* 'r', never set in mlock */
{ 0x00000400, 'K' },
{ 0x00000800, 'V' },
{ 0x00001000, 'Q' },
{ 0x00002000, 'c' },
{ 0x00004000, 'O' },
{ 0x00008000, 'A' },
{ 0x00010000, 'S' },
{ 0x00020000, 'H' },
{ 0x00040000, 'C' },
{ 0x00080000, 'u' },
{ 0x00100000, 'N' },
{ 0x00200000, 'f' },
{ 0x00400000, 'z' },
{ 0, 0 }
};
static void ver8_load_chan(const char *dir, int type)
{
dbFILE *f;
int i, j, c;
ChannelInfo *ci, dummy_ci;
NickInfo *ni;
int32 tmp32, mlock_on, mlock_off;
MemoInfo tmpmi;
f = open_db_ver(dir, "chan.db", 8, type==TYPE_DAYLIGHT?9:8, NULL);
for (i = 0; i < 256; i++) {
int16 tmp16;
char *s, *on, *off;
while ((c = getc_db(f)) == 1) {
char nickbuf[32];
if (type == TYPE_IRCS) {
char namebuf[204];
SAFE(read_buffer(namebuf, f));
#if CHANMAX < 204
if (CHANMAX-1 < strlen(namebuf)) {
fprintf(stderr, "Warning: Channel %s name truncated\n",
namebuf);
namebuf[CHANMAX-1] = 0;
}
#endif
if (get_channelinfo(namebuf)) {
fprintf(stderr, "Channel %s conflicts with existing"
" channel, ignoring\n", namebuf);
ci = &dummy_ci;
} else {
ci = makechan(namebuf);
}
} else {
char namebuf[64];
SAFE(read_buffer(namebuf, f));
if (get_channelinfo(namebuf)) {
fprintf(stderr, "Channel %s conflicts with existing"
" channel, ignoring\n", namebuf);
ci = &dummy_ci;
} else {
ci = makechan(namebuf);
}
}
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr,
"Warning: Founder %s for channel %s not found\n",
s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Founder %s for channel %s is a"
" forbidden nick\n", s, ci->name);
} else {
ci->founder = ni->nickgroup;
}
}
if (type != TYPE_IRCS) {
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (!ni) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" not found\n", s, ci->name);
} else if (!ni->nickgroup) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is a forbidden nick\n", s, ci->name);
} else if (ni->nickgroup == ci->founder) {
fprintf(stderr, "Warning: Successor %s for channel %s"
" is the same as the founder, clearing\n",
s, ci->name);
} else {
ci->successor = ni->nickgroup;
}
}
}
init_password(&ci->founderpass);
if (type == TYPE_IRCS) {
char passbuf[16];
SAFE(read_buffer(passbuf, f));
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf));
} else {
char passbuf[32];
SAFE(read_buffer(passbuf, f));
memcpy(ci->founderpass.password, passbuf, sizeof(passbuf));
}
SAFE(read_string(&ci->desc, f));
if (!ci->desc)
ci->desc = (char *)"";
SAFE(read_string(&ci->url, f));
SAFE(read_string(&ci->email, f));
if (type == TYPE_IRCS)
SAFE(read_int16(&tmp16, f)); /* autoop */
SAFE(read_int32(&tmp32, f));
ci->time_registered = tmp32;
SAFE(read_int32(&tmp32, f));
ci->last_used = tmp32;
SAFE(read_string(&ci->last_topic, f));
SAFE(read_buffer(nickbuf, f));
strbcpy(ci->last_topic_setter, nickbuf);
SAFE(read_int32(&tmp32, f));
ci->last_topic_time = tmp32;
SAFE(read_int32(&tmp32, f)); /* flags */
if (tmp32 & 0x00000001)
ci->flags |= CF_KEEPTOPIC;
if (tmp32 & 0x00000002)
ci->flags |= CF_SECUREOPS;
if (tmp32 & 0x00000004)
ci->flags |= CF_PRIVATE;
if (tmp32 & 0x00000008)
ci->flags |= CF_TOPICLOCK;
if (tmp32 & 0x00000010)
ci->flags |= CF_RESTRICTED;
if (tmp32 & 0x00000020)
ci->flags |= CF_LEAVEOPS;
if (tmp32 & 0x00000040)
ci->flags |= CF_SECURE;
if (tmp32 & 0x00000080)
ci->flags |= CF_VERBOTEN;
if (tmp32 & 0x00000100)
ci->founderpass.cipher = sstrdup("md5");
if (tmp32 & 0x00000200)
ci->flags |= CF_NOEXPIRE;
/* Levels data is ignored */
SAFE(read_int16(&tmp16, f));
for (j = tmp16; j > 0; j--)
SAFE(read_int16(&tmp16, f));
SAFE(read_int16(&ci->access_count, f));
if (ci->access_count) {
ci->access = scalloc(ci->access_count, sizeof(ChanAccess));
for (j = 0; j < ci->access_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&ci->access[j].level, f));
if (type == TYPE_IRCS) {
if (ci->access[j].level >= 10)
ci->access[j].level = 15;
else if (ci->access[j].level >= 7)
ci->access[j].level += 3;
ci->access[j].level =
convert_acclev(ci->access[j].level);
SAFE(read_int16(&tmp16, f)); /* autoop */
}
SAFE(read_string(&s, f));
if (s) {
ni = get_nickinfo(s);
if (ni)
ci->access[j].nickgroup = ni->nickgroup;
}
}
}
}
SAFE(read_int16(&ci->akick_count, f));
if (ci->akick_count) {
ci->akick = scalloc(ci->akick_count, sizeof(AutoKick));
for (j = 0; j < ci->akick_count; j++) {
SAFE(read_int16(&tmp16, f)); /* in_use */
if (tmp16) {
SAFE(read_int16(&tmp16, f)); /* is_nick */
SAFE(read_string(&s, f));
if (tmp16 && s) {
ci->akick[j].mask = smalloc(strlen(s)+5);
sprintf(ci->akick[j].mask, "%s!*@*", s);
} else {
ci->akick[j].mask = s;
}
SAFE(read_string(&s, f));
if (ci->akick[j].mask) {
ci->akick[j].reason = s;
strbcpy(ci->akick[j].who, "<unknown>");
ci->akick[j].set = time(NULL);
}
}
}
}
if (type == TYPE_DAYLIGHT) {
SAFE(read_int32(&mlock_on, f));
SAFE(read_int32(&mlock_off, f));
} else {
SAFE(read_int16(&tmp16, f));
mlock_on = tmp16 & 0x00FF;
SAFE(read_int16(&tmp16, f));
mlock_off = tmp16 & 0x00FF;
}
ci->mlock.on = on = scalloc(64, 1);
ci->mlock.off = off = scalloc(64, 1);
for (j = 0; cmodes[j].flag != 0; j++) {
if (mlock_on & cmodes[j].flag)
*on++ = cmodes[j].mode;
if (mlock_off & cmodes[j].flag)
*off++ = cmodes[j].mode;
}
*on = 0;
*off = 0;
SAFE(read_int32(&ci->mlock.limit, f));
SAFE(read_string(&ci->mlock.key, f));
SAFE(read_int16(&tmpmi.memos_count, f));
SAFE(read_int16(&tmp16, f)); /* memomax */
if (tmpmi.memos_count) {
Memo *memos;
memos = scalloc(sizeof(Memo), tmpmi.memos_count);
tmpmi.memos = memos;
for (j = 0; j < tmpmi.memos_count; j++, memos++) {
SAFE(read_uint32(&memos->number, f));
SAFE(read_int16(&memos->flags, f));
SAFE(read_int32(&tmp32, f));
memos->time = tmp32;
SAFE(read_buffer(nickbuf, f));
strbcpy(memos->sender, nickbuf);
SAFE(read_string(&memos->text, f));
}
}
SAFE(read_string(&ci->entry_message, f));
if (!(ci->flags & CF_VERBOTEN) && !ci->founder) {
fprintf(stderr, "Ignoring channel %s (missing founder)\n",
ci->name);
del_channelinfo(ci);
}
} /* while (getc_db(f) == 1) */
if (c != 0) {
fprintf(stderr, "%s is corrupt, aborting.\n", f->filename);
exit(1);
}
} /* for (i) */
close_db(f);
}
/*************************************************************************/
static void ver8_load_oper(const char *dir, int type)
{
dbFILE *f;
int16 i, n;
int32 tmp32;
char *s;
f = open_db_ver(dir, "oper.db", 8, 8, NULL);
/* servadmin */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVADMIN);
}
if (type == TYPE_IRCS) {
/* senior */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVADMIN);
}
/* junior */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVOPER);
}
/* helper */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVOPER);
}
}
/* servoper */
SAFE(read_int16(&n, f));
for (i = 0; i < n; i++) {
SAFE(read_string(&s, f));
set_os_priv(s, NP_SERVOPER);
}
SAFE(read_int32(&maxusercnt, f));
if (type != TYPE_IRCS) {
SAFE(read_int32(&tmp32, f));
maxusertime = tmp32;
}
close_db(f);
}
/*************************************************************************/
static void ver8_load_akill(const char *dir, int type)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "akill.db", 8, 8, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void ver8_load_exception(const char *dir, int type)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "exception.db", 8, 8, NULL);
SAFE(read_int16(&n, f));
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_string(&md[i].mask, f));
SAFE(read_int16(&md[i].limit, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_string(&md[i].reason, f));
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
static void ver8_load_news(const char *dir, int type)
{
dbFILE *f;
int16 i, n;
NewsItem *news;
f = open_db_ver(dir, "news.db", 8, 8, NULL);
SAFE(read_int16(&n, f));
news = scalloc(sizeof(*news), n);
for (i = 0; i < n; i++) {
char nick[32];
int32 tmp32;
SAFE(read_int16(&news[i].type, f));
SAFE(read_int32(&news[i].num, f));
SAFE(read_string(&news[i].text, f));
SAFE(read_buffer(nick, f));
strbcpy(news[i].who, nick);
SAFE(read_int32(&tmp32, f));
news[i].time = tmp32;
add_news(&news[i]);
}
close_db(f);
}
/*************************************************************************/
static void ircs_load_gline(const char *dir)
{
dbFILE *f;
int16 i, n;
MaskData *md;
f = open_db_ver(dir, "gline.db", 8, 8, NULL);
read_int16(&n, f);
md = scalloc(sizeof(*md), n);
for (i = 0; i < n; i++) {
char *user, *host;
char nick[32];
int32 tmp32;
SAFE(read_string(&user, f));
SAFE(read_string(&host, f));
if (user && host) {
md[i].mask = smalloc(strlen(user)+strlen(host)+2);
sprintf(md[i].mask, "%s@%s", user, host);
} else {
md[i].mask = NULL;
}
SAFE(read_string(&md[i].reason, f));
SAFE(read_buffer(nick, f));
strbcpy(md[i].who, nick);
SAFE(read_int32(&tmp32, f));
md[i].time = tmp32;
SAFE(read_int32(&tmp32, f));
md[i].expires = tmp32;
if (md[i].mask)
add_maskdata(MD_AKILL, &md[i]);
}
close_db(f);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_daylight(const char *dir)
{
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/services.conn", dir);
if (access(buf, R_OK) == 0)
return "Daylight";
return NULL;
}
static void load_daylight(const char *dir, int verbose, int ac,
char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
ver8_load_nick(dir, TYPE_DAYLIGHT);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
ver8_load_chan(dir, TYPE_DAYLIGHT);
if (verbose)
fprintf(stderr, "Loading oper.db...\n");
ver8_load_oper(dir, TYPE_DAYLIGHT);
if (verbose)
fprintf(stderr, "Loading akill.db...\n");
ver8_load_akill(dir, TYPE_DAYLIGHT);
if (verbose)
fprintf(stderr, "Loading exception.db...\n");
ver8_load_exception(dir, TYPE_DAYLIGHT);
if (verbose)
fprintf(stderr, "Loading news.db...\n");
ver8_load_news(dir, TYPE_DAYLIGHT);
}
/*************************************************************************/
/*************************************************************************/
static const char *check_ircs_1_2(const char *dir)
{
char buf[PATH_MAX+1];
snprintf(buf, sizeof(buf), "%s/gline.db", dir);
if (access(buf, R_OK) == 0)
return "IRCS 1.2";
return NULL;
}
static void load_ircs_1_2(const char *dir, int verbose, int ac,
char **av)
{
if (ac > 1) {
fprintf(stderr, "Unrecognized option %s\n", av[1]);
usage(av[0]);
}
if (verbose)
fprintf(stderr, "Loading nick.db...\n");
ver8_load_nick(dir, TYPE_IRCS);
if (verbose)
fprintf(stderr, "Loading chan.db...\n");
ver8_load_chan(dir, TYPE_IRCS);
if (verbose)
fprintf(stderr, "Loading oper.db...\n");
ver8_load_oper(dir, TYPE_IRCS);
if (verbose)
fprintf(stderr, "Loading gline.db...\n");
ircs_load_gline(dir);
}
/*************************************************************************/
/*************************************************************************/
DBTypeInfo dbtype_daylight = {
"daylight",
check_daylight,
load_daylight
};
DBTypeInfo dbtype_ircs_1_2 = {
"ircs-1.2",
check_ircs_1_2,
load_ircs_1_2
};
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/

35
tools/ircservices-chk.in Normal file
View File

@ -0,0 +1,35 @@
#!/bin/sh
#
# Script to check whether IRC Services is running, and restart it if not.
# Usage: ircservices-chk [-q] [ircservices-options]
# -q: don't write any output
# ircservices-options: options to pass to ircservices executable
# If you change PIDFile in ircservices.conf, also change PIDFILE below.
#
# IRC Services is copyright (c) 1996-2009 Andrew Church.
# E-mail: <achurch@achurch.org>
# Parts written by Andrew Kempe and others.
# This program is free but copyrighted software; see the file GPL.txt for
# details.
PIDFILE=@PROGRAM@.pid
if [ "X$1" = "X-q" ] ; then
exec 1>/dev/null
exec 2>/dev/null
shift
fi
ok=
if [ -f "@DATDEST@/$PIDFILE" ] ; then
pid=`cat "@DATDEST@/$PIDFILE"`
if echo "0$pid" | grep -q '[^0-9]' ; then
rm -f "@DATDEST@/$PIDFILE"
elif kill -0 $pid ; then
ok=1
fi
fi
if [ ! "$ok" ] ; then
"@BINDEST@/ircservices" "$@"
fi