/* * IRC - Internet Relay Chat, epona2anope.c * (C) Copyright 2005-2006, Florian Schulze (Certus) * * Based on the original code of Anope, (C) 2003-2005 Anope Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (see it online * at http://www.gnu.org/copyleft/gpl.html) as published by the Free * Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This program tries to convert epona-1.4.15+ dbs to anope standard dbs. * At the moment this only affects chanserv dbs. * * - Certus * February 26, 2005 * * Added win32 fix. Who needs that anyways? :P * - Certus * July 20, 2006 */ #include #include #include #include #include #include #include #include #include #include #include #ifndef _WIN32 # define C_LBLUE "\033[1;34m" # define C_NONE "\033[m" #else # define C_LBLUE "" # define C_NONE "" #endif #define getc_db(f) (fgetc((f)->fp)) #define read_db(f,buf,len) (fread((buf),1,(len),(f)->fp)) #define read_buffer(buf,f) (read_db((f),(buf),sizeof(buf)) == sizeof(buf)) #define write_int8(val,f) (fputc((val),(f)->fp)==EOF ? -1 : 0) #define write_db(f,buf,len) (fwrite((buf),1,(len),(f)->fp)) #define write_buffer(buf,f) (write_db((f),(buf),sizeof(buf)) == sizeof(buf)) struct dbFILE { int mode; /* 'r' for reading, 'w' for writing */ FILE *fp; /* The normal file descriptor */ FILE *backupfp; /* Open file pointer to a backup copy of the database file (if non-NULL) */ char filename[MAXPATHLEN]; /* Name of the database file */ char backupname[MAXPATHLEN]; /* Name of the backup file */ }; struct MemoEpona { uint32_t number; /* Index number -- not necessarily array position! */ int16_t flags; time_t time; /* When it was sent */ char sender[32]; char *text; }; struct MemoInfoEpona { int16_t memocount, memomax; MemoEpona *memos; }; struct NickCoreEpona { NickCoreEpona *next, *prev; char *display; /* How the nick is displayed */ char *pass; /* Password of the nicks */ char *email; /* E-mail associated to the nick */ char *greet; /* Greet associated to the nick */ uint32_t icq; /* ICQ # associated to the nick */ char *aim; /* Naram added - AIM screen name */ char *msn; /* Naram added - MSN screen name */ char *yahoo; /* Naram added - Yahoo screen name */ char *url; /* URL associated to the nick */ int32_t flags; /* See NI_* below */ uint16_t language; /* Language selected by nickname owner (LANG_*) */ int16_t accesscount; /* # of entries */ char **access; /* Array of strings */ MemoInfoEpona memos; uint16_t channelcount; /* Number of channels currently registered */ uint16_t channelmax; /* Maximum number of channels allowed */ }; struct NickAliasEpona { NickAliasEpona *next, *prev; char *nick; /* Nickname */ char *last_quit; /* Last quit message */ char *last_realname; /* Last realname */ char *last_usermask; /* Last usermask */ time_t time_registered; /* When the nick was registered */ time_t last_seen; /* When it was seen online for the last time */ int16_t status; /* See NS_* below */ char *display; /* I'm an alias of this */ }; struct ChanAccessEpona { int16_t in_use; /* 1 if this entry is in use, else 0 */ int16_t level; NickCoreEpona *nc; /* Guaranteed to be non-NULL if in use, NULL if not */ time_t last_seen; }; struct AutoKickEpona { int16_t in_use; /* Always 0 if not in use */ int16_t is_nick; /* 1 if a regged nickname, 0 if a nick!user@host mask */ int16_t flags; union { char *mask; /* Guaranteed to be non-NULL if in use, NULL if not */ NickCoreEpona *nc; /* Same */ } u; char *reason; char *creator; time_t addtime; }; struct BotInfoEpona { BotInfoEpona *next, *prev; char *nick; /* Nickname of the bot */ char *user; /* Its user name */ char *host; /* Its hostname */ char *real; /* Its real name */ int16_t flags; /* Bot flags -- see BI_* below */ time_t created; /* Birth date ;) */ int16_t chancount; /* Number of channels that use the bot. */ }; struct BadWordEpona { int16_t in_use; char *word; int16_t type; /* BW_* below */ }; struct ChannelInfoEpona { ChannelInfoEpona *next, *prev; char name[64]; NickCoreEpona *founder; NickCoreEpona *successor; /* Who gets the channel if the founder nick is dropped or expires */ char founderpass[32]; char *desc; char *url; char *email; time_t time_registered; time_t last_used; char *last_topic; /* Last topic on the channel */ char last_topic_setter[32]; /* Who set the last topic */ time_t last_topic_time; /* When the last topic was set */ uint32_t flags; /* See below */ char *forbidby; char *forbidreason; int16_t bantype; int16_t *levels; /* Access levels for commands */ uint16_t accesscount; ChanAccessEpona *access; /* List of authorized users */ uint16_t akickcount; AutoKickEpona *akick; /* List of users to kickban */ uint32_t mlock_on, mlock_off; /* See channel modes below */ uint32_t mlock_limit; /* 0 if no limit */ char *mlock_key; /* NULL if no key */ char *mlock_flood; /* NULL if no +f */ char *mlock_redirect; /* NULL if no +L */ char *entry_message; /* Notice sent on entering channel */ MemoInfoEpona memos; /* For BotServ */ BotInfoEpona *bi; /* Bot used on this channel */ uint32_t botflags; /* BS_* below */ int16_t *ttb; /* Times to ban for each kicker */ uint16_t bwcount; BadWordEpona *badwords; /* For BADWORDS kicker */ int16_t capsmin, capspercent; /* For CAPS kicker */ int16_t floodlines, floodsecs; /* For FLOOD kicker */ int16_t repeattimes; /* For REPEAT kicker */ }; struct HostCoreEpona { HostCoreEpona *next; char *nick; /* Owner of the vHost */ char *vHost; /* Vhost for this user */ }; /** * Open the database for reading * @param service If error whom to return the error as * @param filename File to open as the database * @return dbFile struct */ static dbFILE *open_db_read(const char *service, const char *filename) { dbFILE *f; FILE *fp; f = new dbFILE; if (!f) { char tmp[1024]; snprintf(tmp, 1024, "Can't read %s database %s", service, filename); perror(tmp); return NULL; } strlcpy(f->filename, filename, sizeof(f->filename)); f->mode = 'r'; fp = fopen(f->filename, "rb"); if (!fp) { int errno_save = errno; if (errno != ENOENT) { char tmp[1024]; snprintf(tmp, 1024, "Can't read %s database %s", service, f->filename); perror(tmp); } delete f; errno = errno_save; return NULL; } f->fp = fp; f->backupfp = NULL; return f; } /*************************************************************************/ /** * Write the current version number to the file. * @param f dbFile Struct Member * @return 0 on error, 1 on success. */ int write_file_version(dbFILE *f, uint32_t version) { FILE *fp = f->fp; if (fputc(version >> 24 & 0xFF, fp) < 0 || fputc(version >> 16 & 0xFF, fp) < 0 || fputc(version >> 8 & 0xFF, fp) < 0 || fputc(version & 0xFF, fp) < 0) { char tmp[1024]; snprintf(tmp, 1024, "Error writing version number on %s", f->filename); perror(tmp); return 0; } return 1; } /** * Open the database for writting * @param service If error whom to return the error as * @param filename File to open as the database * @param version Database Version * @return dbFile struct */ static dbFILE *open_db_write(const char *service, const char *filename, uint32_t version) { dbFILE *f; int fd; f = new dbFILE; if (!f) { char tmp[1024]; snprintf(tmp, 1024, "Can't read %s database %s", service, filename); perror(tmp); return NULL; } strlcpy(f->filename, filename, sizeof(f->filename)); filename = f->filename; f->mode = 'w'; /* Use open() to avoid people sneaking a new file in under us */ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); f->fp = fdopen(fd, "wb"); /* will fail and return NULL if fd < 0 */ if (!f->fp || !write_file_version(f, version)) { int errno_save = errno; errno = errno_save; char tmp[1024]; snprintf(tmp, 1024, "Can't write to %s database %s", service, filename); perror(tmp); if (f->fp) { fclose(f->fp); unlink(filename); } /* Then the Lord said unto Moses, thou shalt free what thou hast malloced * -- codemastr */ delete f; errno = errno_save; return NULL; } return f; } /*************************************************************************/ /** * Open a database file for reading (*mode == 'r') or writing (*mode == 'w'). * Return the stream pointer, or NULL on error. When opening for write, it * is an error for rename() to return an error (when backing up the original * file) other than ENOENT, if NO_BACKUP_OKAY is not defined; it is an error * if the version number cannot be written to the file; and it is a fatal * error if opening the file for write fails and the backup was successfully * made but cannot be restored. * @param service If error whom to return the error as * @param filename File to open as the database * @param mode Mode for writting or reading * @param version Database Version * @return dbFile struct */ dbFILE *open_db(const char *service, const char *filename, const char *mode, uint32_t version) { if (*mode == 'r') return open_db_read(service, filename); else if (*mode == 'w') return open_db_write(service, filename, version); else { errno = EINVAL; return NULL; } } /** * Return the version number on the file. Return 0 if there is no version * number or the number doesn't make sense (i.e. less than 1 or greater * than FILE_VERSION). * @param f dbFile Struct Member * @return int 0 if failure, 1 > is the version number */ int get_file_version(dbFILE *f) { FILE *fp = f->fp; int version = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp); if (ferror(fp)) { char tmp[1024]; snprintf(tmp, 1024, "Error reading version number on %s", f->filename); perror(tmp); return 0; } else if (feof(fp)) { printf("Error reading version number on %s: End of file detected\n", f->filename); return 0; } else if (version < 1) { printf("Invalid version number (%d) on %s\n", version, f->filename); return 0; } return version; } /** * Close a database file. If the file was opened for write, remove the * backup we (may have) created earlier. * @param dbFile struct * @return void */ void close_db(dbFILE *f) { fclose(f->fp); delete f; } /** * Read and write 2- and 4-byte quantities, pointers, and strings. All * multibyte values are stored in big-endian order (most significant byte * first). A pointer is stored as a byte, either 0 if NULL or 1 if not, * and read pointers are returned as either (void *)0 or (void *)1. A * string is stored with a 2-byte unsigned length (including the trailing * \0) first; a length of 0 indicates that the string pointer is NULL. * Written strings are truncated silently at 65534 bytes, and are always * null-terminated. * * @param ret 16bit integer to write * @param dbFile struct * @return -1 on error, 0 otherwise. */ int read_int16(uint16_t *ret, dbFILE *f) { int c1 = fgetc(f->fp), c2 = fgetc(f->fp); if (c1 == EOF || c2 == EOF) return -1; *ret = c1 << 8 | c2; return 0; } /** * Write a 16bit integer * * @param ret 16bit integer to write * @param dbFile struct * @return -1 on error, 0 otherwise. */ int write_int16(uint16_t val, dbFILE *f) { if (fputc((val >> 8) & 0xFF, f->fp) == EOF || fputc(val & 0xFF, f->fp) == EOF) return -1; return 0; } /** * Read a unsigned 32bit integer * * @param ret unsigned 32bit integer to read * @param dbFile struct * @return -1 on error, 0 otherwise. */ int read_int32(uint32_t *ret, dbFILE *f) { int c1 = fgetc(f->fp), c2 = fgetc(f->fp), c3 = fgetc(f->fp), c4 = fgetc(f->fp); if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF) return -1; *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4; return 0; } /** * Write a unsigned 32bit integer * * @param ret unsigned 32bit integer to write * @param dbFile struct * @return -1 on error, 0 otherwise. */ int write_int32(uint32_t val, dbFILE *f) { if (fputc((val >> 24) & 0xFF, f->fp) == EOF) return -1; if (fputc((val >> 16) & 0xFF, f->fp) == EOF) return -1; if (fputc((val >> 8) & 0xFF, f->fp) == EOF) return -1; if (fputc(val & 0xFF, f->fp) == EOF) return -1; return 0; } /** * Read String * * @param ret string * @param dbFile struct * @return -1 on error, 0 otherwise. */ int read_string(char **ret, dbFILE *f) { uint16_t len; if (read_int16(&len, f) < 0) return -1; if (len == 0) { *ret = NULL; return 0; } char *s = new char[len]; if (len != fread(s, 1, len, f->fp)) { delete [] s; return -1; } *ret = s; return 0; } /** * Write String * * @param ret string * @param dbFile struct * @return -1 on error, 0 otherwise. */ int write_string(const char *s, dbFILE *f) { if (!s) return write_int16(0, f); uint32_t len = strlen(s); if (len > 65534) len = 65534; if (write_int16(static_cast(len + 1), f) < 0) return -1; if (len > 0 && fwrite(s, 1, len, f->fp) != len) return -1; if (fputc(0, f->fp) == EOF) return -1; return 0; } static inline int HASHNICK(const char *nick) { return (tolower(nick[0]) & 31) << 5 | (tolower(nick[1]) & 31); } NickAliasEpona *nalists_Epona[1024]; NickCoreEpona *nclists_Epona[1024]; /* Return the NickCore structure for the given nick, or NULL if the core * doesn't exist. */ NickCoreEpona *findcore_Epona(const char *nick) { NickCoreEpona *nc = nclists_Epona[HASHNICK(nick)]; for (; nc; nc = nc->next) if (!strcasecmp(nc->display, nick)) return nc; return NULL; } /* Deletes an alias. The core will also be deleted if it has no more * nicks attached to it. Easy but powerful. * Well, we must also take care that the nick being deleted is not * the core display, and if so, change it to the next alias in the list, * otherwise weird things will happen. * Returns 1 on success, 0 otherwise. */ int delnick_Epona(NickAliasEpona *na) { /* Remove us from the aliases list */ if (na->next) na->next->prev = na->prev; if (na->prev) na->prev->next = na->next; else nalists_Epona[HASHNICK(na->nick)] = na->next; delete [] na->nick; if (na->last_usermask) delete [] na->last_usermask; if (na->last_realname) delete [] na->last_realname; if (na->last_quit) delete [] na->last_quit; delete na; return 1; } HostCoreEpona *head = NULL; /* head of the HostCore list */ HostCoreEpona *createHostCorelist_Epona(HostCoreEpona *next, char *nick, char *vHost) { next = new HostCoreEpona; if (!next) { printf("HostServ[Epona]: Unable to allocate memory to create the vHost LL, problems i sense..\n"); exit(1); } else { next->nick = new char[strlen(nick) + 1]; next->vHost = new char[strlen(vHost) + 1]; if (!next->nick || !next->vHost) { printf("HostServ[Epona]: Unable to allocate memory to create the vHost LL, problems i sense..\n"); exit(1); } strcpy(next->nick, nick); strcpy(next->vHost, vHost); next->next = NULL; return next; } return NULL; } HostCoreEpona *findHostCore_Epona(HostCoreEpona *list, char *nick, bool *found) { HostCoreEpona *current = list, *previous = current; *found = false; while (current) { if (!strcasecmp(nick, current->nick)) { *found = true; break; } else if (strcasecmp(nick, current->nick) < 0) break; // we know were not gonna find it now.... else { previous = current; current = current->next; } } return current == list ? NULL : previous; } HostCoreEpona *insertHostCore_Epona(HostCoreEpona *list, HostCoreEpona *prev, char *nick, char *vHost) { HostCoreEpona *newCore = new HostCoreEpona, *tmp; if (!newCore) { printf("HostServ[Epona]: Unable to allocate memory to insert into the vHost LL, problems i sense..\n"); exit(1); } else { newCore->nick = new char[strlen(nick) + 1]; newCore->vHost = new char[strlen(vHost) + 1]; if (!newCore->nick || !newCore->vHost) { printf("HostServ[Epona]: Unable to allocate memory to create the vHost LL, problems i sense..\n"); exit(1); } strcpy(newCore->nick, nick); strcpy(newCore->vHost, vHost); tmp = prev ? prev->next : list; if (prev) prev->next = newCore; else list = newCore; newCore->next = tmp; } return list; } HostCoreEpona *deleteHostCore_Epona(HostCoreEpona *list, HostCoreEpona *prev) { HostCoreEpona *tmp = NULL; if (!prev) list = list->next; else { tmp = prev->next; prev->next = tmp->next; } if (tmp) delete tmp; return list; } void addHostCore_Epona(char *nick, char *vhost) { HostCoreEpona *tmp; bool found = false; if (!head) head = createHostCorelist_Epona(head, nick, vhost); else { tmp = findHostCore_Epona(head, nick, &found); if (!found) head = insertHostCore_Epona(head, tmp, nick, vhost); else { head = deleteHostCore_Epona(head, tmp); // delete the old entry addHostCore_Epona(nick, vhost); // recursive call to add new entry } } } BotInfoEpona *botlists_Epona[256]; /* Hash list of bots */ int nbots_Epona = 0; BotInfoEpona *findbot_Epona(char *nick) { BotInfoEpona *bi; if (!nick || !*nick) return NULL; for (bi = botlists_Epona[tolower(*nick)]; bi; bi = bi->next) if (!strcasecmp(nick, bi->nick)) return bi; return NULL; } /* Inserts a bot in the bot list. I can't be much explicit mh? */ static void insert_bot_Epona(BotInfoEpona *bi) { BotInfoEpona *ptr = botlists_Epona[tolower(*bi->nick)], *prev = NULL; for (; ptr && strcasecmp(ptr->nick, bi->nick) < 0; prev = ptr, ptr = ptr->next); bi->prev = prev; bi->next = ptr; if (prev) prev->next = bi; else botlists_Epona[tolower(*bi->nick)] = bi; if (ptr) ptr->prev = bi; } static BotInfoEpona *makebot_Epona(char *nick) { BotInfoEpona *bi = new BotInfoEpona; bi->nick = strdup(nick); insert_bot_Epona(bi); ++nbots_Epona; return bi; } ChannelInfoEpona *chanlists_Epona[256]; /* Indices for cmd_access[]: */ #define CA_INVITE 0 #define CA_AKICK 1 #define CA_SET 2 /* but not FOUNDER or PASSWORD */ #define CA_UNBAN 3 #define CA_AUTOOP 4 #define CA_AUTODEOP 5 /* Maximum, not minimum */ #define CA_AUTOVOICE 6 #define CA_OPDEOP 7 /* ChanServ commands OP and DEOP */ #define CA_ACCESS_LIST 8 #define CA_CLEAR 9 #define CA_NOJOIN 10 /* Maximum */ #define CA_ACCESS_CHANGE 11 #define CA_MEMO 12 #define CA_ASSIGN 13 /* BotServ ASSIGN command */ #define CA_BADWORDS 14 /* BotServ BADWORDS command */ #define CA_NOKICK 15 /* Not kicked by the bot */ #define CA_FANTASIA 16 #define CA_SAY 17 #define CA_GREET 18 #define CA_VOICEME 19 #define CA_VOICE 20 #define CA_GETKEY 21 #define CA_AUTOHALFOP 22 #define CA_AUTOPROTECT 23 #define CA_OPDEOPME 24 #define CA_HALFOPME 25 #define CA_HALFOP 26 #define CA_PROTECTME 27 #define CA_PROTECT 28 #define CA_KICKME 29 #define CA_KICK 30 #define CA_SIGNKICK 31 /* #define CA_AUTOADMIN 32 #define CA_ADMINME 33 #define CA_ADMIN 34 */ #define CA_BANME 32 #define CA_BAN 33 #define CA_TOPIC 34 #define CA_INFO 35 #define AK_USED 0x0001 #define AK_ISNICK 0x0002 static int def_levels[][2] = { { CA_AUTOOP, 5 }, { CA_AUTOVOICE, 3 }, { CA_AUTODEOP, -1 }, { CA_NOJOIN, -2 }, { CA_INVITE, 5 }, { CA_AKICK, 10 }, { CA_SET, -10000 }, { CA_CLEAR, -10000 }, { CA_UNBAN, 5 }, { CA_OPDEOP, 5 }, { CA_ACCESS_LIST, 1 }, { CA_ACCESS_CHANGE, 10 }, { CA_MEMO, 10 }, { CA_ASSIGN, -10000 }, { CA_BADWORDS, 10 }, { CA_NOKICK, 1 }, { CA_FANTASIA, 3 }, { CA_SAY, 5 }, { CA_GREET, 5 }, { CA_VOICEME, 3 }, { CA_VOICE, 5 }, { CA_GETKEY, 5 }, { CA_AUTOHALFOP, 4 }, { CA_AUTOPROTECT, 10 }, { CA_OPDEOPME, 5 }, { CA_HALFOPME, 4 }, { CA_HALFOP, 5 }, { CA_PROTECTME, 10 }, { CA_PROTECT, -10000 }, { CA_KICKME, 5 }, { CA_KICK, 5 }, { CA_SIGNKICK, -10000 }, { CA_BANME, 5 }, { CA_BAN, 5 }, { CA_TOPIC, -10000 }, { CA_INFO, -10000 }, { -1 } }; /* Reset channel access level values to their default state. */ static void reset_levels_Epona(ChannelInfoEpona *ci) { int i = 0; if (ci->levels) delete [] ci->levels; ci->levels = new int16_t[36]; for (; def_levels[i][0] >= 0; i++) ci->levels[def_levels[i][0]] = def_levels[i][1]; } /* Remove a channel from the ChanServ database. Return 1 on success, 0 * otherwise. */ static int delchan_Epona(ChannelInfoEpona *ci) { int i = 0; NickCoreEpona *nc = ci->founder; if (ci->bi) --ci->bi->chancount; if (ci->next) ci->next->prev = ci->prev; if (ci->prev) ci->prev->next = ci->next; else chanlists_Epona[tolower(ci->name[1])] = ci->next; if (ci->desc) delete [] ci->desc; if (ci->mlock_key) delete [] ci->mlock_key; if (ci->mlock_flood) delete [] ci->mlock_flood; if (ci->mlock_redirect) delete [] ci->mlock_redirect; if (ci->last_topic) delete [] ci->last_topic; if (ci->forbidby) delete [] ci->forbidby; if (ci->forbidreason) delete [] ci->forbidreason; if (ci->access) delete [] ci->access; for (; i < ci->akickcount; ++i) { if (!(ci->akick[i].flags & AK_ISNICK) && ci->akick[i].u.mask) delete [] ci->akick[i].u.mask; if (ci->akick[i].reason) delete [] ci->akick[i].reason; if (ci->akick[i].creator) delete [] ci->akick[i].creator; } if (ci->akick) delete [] ci->akick; if (ci->levels) delete [] ci->levels; if (ci->memos.memos) { for (i = 0; i < ci->memos.memocount; i++) if (ci->memos.memos[i].text) delete [] ci->memos.memos[i].text; delete [] ci->memos.memos; } if (ci->ttb) delete [] ci->ttb; for (i = 0; i < ci->bwcount; i++) if (ci->badwords[i].word) delete [] ci->badwords[i].word; if (ci->badwords) delete [] ci->badwords; delete ci; if (nc) --nc->channelcount; return 1; } #define SAFE(x) do \ { \ if ((x) < 0) \ { \ printf("Read error on nick.epona.db\n"); \ exit(1); \ } \ } while (0) void load_nsold_dbase() { dbFILE *f = open_db("NickServ", "nick.epona.db", "r", 14); int ver, i = 0, j, c, failed = 0; NickAliasEpona *na, **nalast, *naprev; NickCoreEpona *nc, **nclast, *ncprev; uint16_t tmp16; uint32_t tmp32; if (!f) return; ver = get_file_version(f); /* First we load nick cores */ for (; i < 1024 && !failed; ++i) { nclast = &nclists_Epona[i]; ncprev = NULL; while ((c = getc_db(f))) { if (c != 1) { printf("Invalid format in nick.epona.db\n"); exit(1); } nc = new NickCoreEpona; *nclast = nc; nclast = &nc->next; nc->prev = ncprev; ncprev = nc; SAFE(read_string(&nc->display, f)); SAFE(read_string(&nc->pass, f)); SAFE(read_string(&nc->email, f)); SAFE(read_string(&nc->greet, f)); SAFE(read_int32(&nc->icq, f)); SAFE(read_string(&nc->aim, f)); SAFE(read_string(&nc->msn, f)); SAFE(read_string(&nc->yahoo, f)); SAFE(read_string(&nc->url, f)); SAFE(read_int32(&tmp32, f)); nc->flags = tmp32; nc->flags &= ~0x00008000; // Remove SERVICES ROOT SAFE(read_int16(&nc->language, f)); SAFE(read_int16(&tmp16, f)); nc->accesscount = tmp16; if (nc->accesscount) { char **access = new char *[nc->accesscount]; nc->access = access; for (j = 0; j < nc->accesscount; ++j, ++access) SAFE(read_string(access, f)); } SAFE(read_int16(&tmp16, f)); nc->memos.memocount = tmp16; SAFE(read_int16(&tmp16, f)); nc->memos.memomax = tmp16; if (nc->memos.memocount) { MemoEpona *memos = new MemoEpona[nc->memos.memocount]; nc->memos.memos = memos; for (j = 0; j < nc->memos.memocount; ++j, ++memos) { SAFE(read_int32(&memos->number, f)); SAFE(read_int16(&tmp16, f)); memos->flags = tmp16; SAFE(read_int32(&tmp32, f)); memos->time = tmp32; SAFE(read_buffer(memos->sender, f)); SAFE(read_string(&memos->text, f)); } } SAFE(read_int16(&nc->channelcount, f)); SAFE(read_int16(&tmp16, f)); nc->channelmax = 20; } /* while (getc_db(f) != 0) */ *nclast = NULL; } /* for (i) */ for (i = 0; i < 1024 && !failed; ++i) { nalast = &nalists_Epona[i]; naprev = NULL; while ((c = getc_db(f))) { if (c != 1) { printf("Invalid format in nick.epona.db\n"); exit(1); } na = new NickAliasEpona; SAFE(read_string(&na->nick, f)); SAFE(read_string(&na->last_usermask, f)); SAFE(read_string(&na->last_realname, f)); SAFE(read_string(&na->last_quit, f)); SAFE(read_int32(&tmp32, f)); na->time_registered = tmp32; SAFE(read_int32(&tmp32, f)); na->last_seen = tmp32; SAFE(read_int16(&tmp16, f)); na->status = tmp16; na->status &= ~0xFF00; SAFE(read_string(&na->display, f)); if (!(na->status & 0x0002)) { if (!na->last_usermask) na->last_usermask = strdup(""); if (!na->last_realname) na->last_realname = strdup(""); } *nalast = na; nalast = &na->next; na->prev = naprev; naprev = na; } /* while (getc_db(f) != 0) */ *nalast = NULL; } /* for (i) */ close_db(f); } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ perror("Write error on nick.db"); \ exit(1); \ } \ } while (0) void save_ns_dbase() { dbFILE *f; int i, j; NickAliasEpona *na; NickCoreEpona *nc; char **access; MemoEpona *memos; if (!(f = open_db("NickServ", "nick.db", "w", 14))) return; for (i = 0; i < 1024; ++i) { for (nc = nclists_Epona[i]; nc; nc = nc->next) { SAFE(write_int8(1, f)); SAFE(write_string(nc->display, f)); char tmp[32]; snprintf(tmp, 32, "%s", nc->pass ? nc->pass : ""); SAFE(write_buffer(tmp, f)); SAFE(write_string(nc->email, f)); SAFE(write_string(nc->greet, f)); SAFE(write_int32(nc->icq, f)); SAFE(write_string(nc->url, f)); SAFE(write_int32(nc->flags, f)); SAFE(write_int16(nc->language, f)); SAFE(write_int16(nc->accesscount, f)); for (j = 0, access = nc->access; j < nc->accesscount; ++j, ++access) SAFE(write_string(*access, f)); SAFE(write_int16(nc->memos.memocount, f)); SAFE(write_int16(nc->memos.memomax, f)); memos = nc->memos.memos; for (j = 0; j < nc->memos.memocount; ++j, ++memos) { SAFE(write_int32(memos->number, f)); SAFE(write_int16(memos->flags, f)); SAFE(write_int32(memos->time, f)); SAFE(write_buffer(memos->sender, f)); SAFE(write_string(memos->text, f)); } SAFE(write_int16(nc->channelcount, f)); SAFE(write_int16(nc->channelmax, f)); } /* for (nc) */ SAFE(write_int8(0, f)); } /* for (i) */ for (i = 0; i < 1024; ++i) { for (na = nalists_Epona[i]; na; na = na->next) { SAFE(write_int8(1, f)); SAFE(write_string(na->nick, f)); SAFE(write_string(na->last_usermask, f)); SAFE(write_string(na->last_realname, f)); SAFE(write_string(na->last_quit, f)); SAFE(write_int32(na->time_registered, f)); SAFE(write_int32(na->last_seen, f)); SAFE(write_int16(na->status, f)); SAFE(write_string(na->display, f)); } /* for (na) */ SAFE(write_int8(0, f)); } /* for (i) */ close_db(f); } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ printf("Read error on hosts.epona.db\n"); \ exit(1); \ } \ } while (0) void load_hsold_dbase() { dbFILE *f = open_db("HostServ", "hosts.epona.db", "r", 1); int c, ver, failed = 0; char *nick, *vHost; if (!f) return; ver = get_file_version(f); while (!failed && (c = getc_db(f))) { if (c != 1) { printf("Invalid format in hosts.epona.db: %d\n", c); exit(1); } SAFE(read_string(&nick, f)); SAFE(read_string(&vHost, f)); addHostCore_Epona(nick, vHost); // could get a speed increase by not searching the list delete [] nick; // as we know the db is in alphabetical order... delete [] vHost; } close_db(f); } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ perror("Write error on hosts.db"); \ exit(1); \ } \ } while (0) void save_hs_dbase() { dbFILE *f; HostCoreEpona *current; if (!(f = open_db("HostServ", "hosts.db", "w", 3))) return; current = head; while (current != NULL) { SAFE(write_int8(1, f)); SAFE(write_string(current->nick, f)); SAFE(write_string(NULL, f)); SAFE(write_string(current->vHost, f)); SAFE(write_string("Unknown", f)); SAFE(write_int32(time(NULL), f)); current = current->next; } SAFE(write_int8(0, f)); close_db(f); } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ printf("Read error on bot.epona.db\n"); \ exit(1); \ } \ } while (0) void load_bsold_dbase() { dbFILE *f = open_db("BotServ", "bot.epona.db", "r", 10); int c, ver, failed = 0; uint16_t tmp16; uint32_t tmp32; BotInfoEpona *bi; if (!f) return; ver = get_file_version(f); while (!failed && (c = getc_db(f))) { char *s; if (c != 1) { printf("Invalid format in bot.epona.db: %d\n", c); exit(1); } SAFE(read_string(&s, f)); bi = makebot_Epona(s); delete [] s; SAFE(read_string(&bi->user, f)); SAFE(read_string(&bi->host, f)); SAFE(read_string(&bi->real, f)); SAFE(read_int16(&tmp16, f)); bi->flags = tmp16; SAFE(read_int32(&tmp32, f)); bi->created = tmp32; SAFE(read_int16(&tmp16, f)); bi->chancount = tmp16; } close_db(f); } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ printf("Read error on chan.epona.db\n"); \ exit(1); \ } \ } while (0) void load_csold_dbase() { dbFILE *f = open_db("ChanServ", "chan.epona.db", "r", 16); int ver, i = 0, j, c, failed = 0; ChannelInfoEpona *ci, **last, *prev; if (!f) return; ver = get_file_version(f); for (; i < 256 && !failed; ++i) { uint16_t tmp16; uint32_t tmp32; int n_levels; char *s; last = &chanlists_Epona[i]; prev = NULL; while ((c = getc_db(f))) { if (c != 1) { printf("Invalid format in chan.epona.db\n"); exit(1); } ci = new ChannelInfoEpona; *last = ci; last = &ci->next; ci->prev = prev; prev = ci; SAFE(read_buffer(ci->name, f)); SAFE(read_string(&s, f)); if (s) { ci->founder = findcore_Epona(s); delete [] s; } else ci->founder = NULL; SAFE(read_string(&s, f)); if (s) { ci->successor = findcore_Epona(s); delete [] s; } else ci->successor = NULL; SAFE(read_buffer(ci->founderpass, f)); SAFE(read_string(&ci->desc, f)); if (!ci->desc) ci->desc = strdup(""); 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(ci->last_topic_setter, f)); SAFE(read_int32(&tmp32, f)); ci->last_topic_time = tmp32; SAFE(read_int32(&ci->flags, f)); /* Temporary flags cleanup */ ci->flags &= ~0x80000000; SAFE(read_string(&ci->forbidby, f)); SAFE(read_string(&ci->forbidreason, f)); SAFE(read_int16(&tmp16, f)); ci->bantype = tmp16; SAFE(read_int16(&tmp16, f)); n_levels = tmp16; ci->levels = new int16_t[36]; reset_levels_Epona(ci); for (j = 0; j < n_levels; ++j) { SAFE(read_int16(&tmp16, f)); if (j < 36) ci->levels[j] = tmp16; } SAFE(read_int16(&ci->accesscount, f)); if (ci->accesscount) { ci->access = new ChanAccessEpona[ci->accesscount]; for (j = 0; j < ci->accesscount; ++j) { SAFE(read_int16(&tmp16, f)); ci->access[j].in_use = tmp16; if (ci->access[j].in_use) { SAFE(read_int16(&tmp16, f)); ci->access[j].level = tmp16; SAFE(read_string(&s, f)); if (s) { ci->access[j].nc = findcore_Epona(s); delete [] s; } if (!ci->access[j].nc) ci->access[j].in_use = 0; SAFE(read_int32(&tmp32, f)); ci->access[j].last_seen = tmp32; } } } else ci->access = NULL; SAFE(read_int16(&ci->akickcount, f)); if (ci->akickcount) { ci->akick = new AutoKickEpona[ci->akickcount]; for (j = 0; j < ci->akickcount; ++j) { SAFE(read_int16(&tmp16, f)); ci->akick[j].flags = tmp16; if (ci->akick[j].flags & AK_USED) { SAFE(read_string(&s, f)); if (ci->akick[j].flags & AK_ISNICK) { ci->akick[j].u.nc = findcore_Epona(s); if (!ci->akick[j].u.nc) ci->akick[j].flags &= ~AK_USED; delete [] s; } else ci->akick[j].u.mask = s; SAFE(read_string(&s, f)); if (ci->akick[j].flags & AK_USED) ci->akick[j].reason = s; else if (s) delete [] s; SAFE(read_string(&s, f)); if (ci->akick[j].flags & AK_USED) ci->akick[j].creator = s; else if (s) delete [] s; SAFE(read_int32(&tmp32, f)); if (ci->akick[j].flags & AK_USED) ci->akick[j].addtime = tmp32; } } } else ci->akick = NULL; SAFE(read_int32(&ci->mlock_on, f)); SAFE(read_int32(&ci->mlock_off, f)); SAFE(read_int32(&ci->mlock_limit, f)); SAFE(read_string(&ci->mlock_key, f)); SAFE(read_string(&ci->mlock_flood, f)); SAFE(read_string(&ci->mlock_redirect, f)); SAFE(read_int16(&tmp16, f)); ci->memos.memocount = tmp16; SAFE(read_int16(&tmp16, f)); ci->memos.memomax = tmp16; if (ci->memos.memocount) { MemoEpona *memos = new MemoEpona[ci->memos.memocount]; ci->memos.memos = memos; for (j = 0; j < ci->memos.memocount; ++j, ++memos) { SAFE(read_int32(&memos->number, f)); SAFE(read_int16(&tmp16, f)); memos->flags = tmp16; SAFE(read_int32(&tmp32, f)); memos->time = tmp32; SAFE(read_buffer(memos->sender, f)); SAFE(read_string(&memos->text, f)); } } SAFE(read_string(&ci->entry_message, f)); /* BotServ options */ int n_ttb; SAFE(read_string(&s, f)); if (s) { ci->bi = findbot_Epona(s); delete [] s; } else ci->bi = NULL; SAFE(read_int32(&tmp32, f)); ci->botflags = tmp32; SAFE(read_int16(&tmp16, f)); n_ttb = tmp16; ci->ttb = new int16_t[8]; for (j = 0; j < n_ttb; ++j) { SAFE(read_int16(&tmp16, f)); if (j < 8) ci->ttb[j] = tmp16; } for (j = n_ttb; j < 8; ++j) ci->ttb[j] = 0; SAFE(read_int16(&tmp16, f)); ci->capsmin = tmp16; SAFE(read_int16(&tmp16, f)); ci->capspercent = tmp16; SAFE(read_int16(&tmp16, f)); ci->floodlines = tmp16; SAFE(read_int16(&tmp16, f)); ci->floodsecs = tmp16; SAFE(read_int16(&tmp16, f)); ci->repeattimes = tmp16; SAFE(read_int16(&ci->bwcount, f)); if (ci->bwcount) { ci->badwords = new BadWordEpona[ci->bwcount]; for (j = 0; j < ci->bwcount; ++j) { SAFE(read_int16(&tmp16, f)); ci->badwords[j].in_use = tmp16; if (ci->badwords[j].in_use) { SAFE(read_string(&ci->badwords[j].word, f)); SAFE(read_int16(&tmp16, f)); ci->badwords[j].type = tmp16; } } } else ci->badwords = NULL; } /* while (getc_db(f) != 0) */ *last = NULL; } /* for (i) */ close_db(f); /* Check for non-forbidden channels with no founder. Makes also other essential tasks. */ for (i = 0; i < 256; ++i) { ChannelInfoEpona *next; for (ci = chanlists_Epona[i]; ci; ci = next) { next = ci->next; if (!(ci->flags & 0x00000080) && !ci->founder) { printf("ChanServ[Epona]: database load: Deleting founderless channel %s\n", ci->name); delchan_Epona(ci); continue; } } } } #undef SAFE #define SAFE(x) do \ { \ if ((x) < 0) \ { \ perror("Write error on chan.db"); \ exit(1); \ } \ } while (0) void save_cs_dbase() { dbFILE *f; int i, j; ChannelInfoEpona *ci; MemoEpona *memos; if (!(f = open_db("ChanServ", "chan.db", "w", 16))) return; for (i = 0; i < 256; ++i) { int16_t tmp16; for (ci = chanlists_Epona[i]; ci; ci = ci->next) { SAFE(write_int8(1, f)); SAFE(write_buffer(ci->name, f)); if (ci->founder) SAFE(write_string(ci->founder->display, f)); else SAFE(write_string(NULL, f)); if (ci->successor) SAFE(write_string(ci->successor->display, f)); else SAFE(write_string(NULL, f)); SAFE(write_buffer(ci->founderpass, f)); SAFE(write_string(ci->desc, f)); SAFE(write_string(ci->url, f)); SAFE(write_string(ci->email, f)); SAFE(write_int32(ci->time_registered, f)); SAFE(write_int32(ci->last_used, f)); SAFE(write_string(ci->last_topic, f)); SAFE(write_buffer(ci->last_topic_setter, f)); SAFE(write_int32(ci->last_topic_time, f)); SAFE(write_int32(ci->flags, f)); SAFE(write_string(ci->forbidby, f)); SAFE(write_string(ci->forbidreason, f)); SAFE(write_int16(ci->bantype, f)); tmp16 = 36; SAFE(write_int16(tmp16, f)); for (j = 0; j < 36; ++j) SAFE(write_int16(ci->levels[j], f)); SAFE(write_int16(ci->accesscount, f)); for (j = 0; j < ci->accesscount; ++j) { SAFE(write_int16(ci->access[j].in_use, f)); if (ci->access[j].in_use) { SAFE(write_int16(ci->access[j].level, f)); SAFE(write_string(ci->access[j].nc->display, f)); SAFE(write_int32(ci->access[j].last_seen, f)); } } SAFE(write_int16(ci->akickcount, f)); for (j = 0; j < ci->akickcount; ++j) { SAFE(write_int16(ci->akick[j].flags, f)); if (ci->akick[j].flags & AK_USED) { if (ci->akick[j].flags & AK_ISNICK) SAFE(write_string(ci->akick[j].u.nc->display, f)); else SAFE(write_string(ci->akick[j].u.mask, f)); SAFE(write_string(ci->akick[j].reason, f)); SAFE(write_string(ci->akick[j].creator, f)); SAFE(write_int32(ci->akick[j].addtime, f)); } } SAFE(write_int32(ci->mlock_on, f)); SAFE(write_int32(ci->mlock_off, f)); SAFE(write_int32(ci->mlock_limit, f)); SAFE(write_string(ci->mlock_key, f)); SAFE(write_string(ci->mlock_flood, f)); SAFE(write_string(ci->mlock_redirect, f)); SAFE(write_int16(ci->memos.memocount, f)); SAFE(write_int16(ci->memos.memomax, f)); memos = ci->memos.memos; for (j = 0; j < ci->memos.memocount; ++j, ++memos) { SAFE(write_int32(memos->number, f)); SAFE(write_int16(memos->flags, f)); SAFE(write_int32(memos->time, f)); SAFE(write_buffer(memos->sender, f)); SAFE(write_string(memos->text, f)); } SAFE(write_string(ci->entry_message, f)); if (ci->bi) SAFE(write_string(ci->bi->nick, f)); else SAFE(write_string(NULL, f)); SAFE(write_int32(ci->botflags, f)); tmp16 = 8; SAFE(write_int16(tmp16, f)); for (j = 0; j < 8; ++j) SAFE(write_int16(ci->ttb[j], f)); SAFE(write_int16(ci->capsmin, f)); SAFE(write_int16(ci->capspercent, f)); SAFE(write_int16(ci->floodlines, f)); SAFE(write_int16(ci->floodsecs, f)); SAFE(write_int16(ci->repeattimes, f)); SAFE(write_int16(ci->bwcount, f)); for (j = 0; j < ci->bwcount; ++j) { SAFE(write_int16(ci->badwords[j].in_use, f)); if (ci->badwords[j].in_use) { SAFE(write_string(ci->badwords[j].word, f)); SAFE(write_int16(ci->badwords[j].type, f)); } } } /* for (chanlists[i]) */ SAFE(write_int8(0, f)); } /* for (i) */ close_db(f); } #undef SAFE int main(int argc, char *argv[]) { printf("\n" C_LBLUE "Epona 1.4.14 to Anope 1.8 DB converter by CyberBotX" C_NONE "\n\n"); printf("Loading Epona 1.4.14 NickServ database..."); load_nsold_dbase(); printf("Loading done!\n"); printf("Loading Epona 1.4.14 HostServ database..."); load_hsold_dbase(); printf("Loading done!\n"); printf("Loading Epona 1.4.14 BotServ database..."); load_bsold_dbase(); // Epona's BotServ does not need converting printf("Loading done!\n"); printf("Loading Epona 1.4.14 ChanServ database..."); load_csold_dbase(); printf("Loading done!\n"); printf("Saving Anope 1.8 NickServ database..."); save_ns_dbase(); printf("Saving done!\n"); printf("Saving Anope 1.8 HostServ database..."); save_hs_dbase(); printf("Saving done!\n"); printf("Saving Anope 1.8 ChanServ database..."); save_cs_dbase(); printf("Saving done!\n"); printf("\nConverting is now done.\n"); return 0; } /* End of main() */