/* DBTool Header

   Cygnus IRC Services - Copyright (c) 2001-2002 Darcy Grexton
   Contact: skold@habber.net, skold @ HabberNet

   See doc/LICENSE for licensing details.
 */

#define _GNU_SOURCE

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <grp.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>

#define E extern

/* Channel Modes */
#define CMODE_t		0x00000001
#define CMODE_n		0x00000002
#define CMODE_s		0x00000004
#define CMODE_m		0x00000008
#define CMODE_l		0x00000010
#define CMODE_i		0x00000020
#define CMODE_p		0x00000040
#define CMODE_k		0x00000080
#define CMODE_o		0x00000100
#define CMODE_v		0x00000200
#define CMODE_R		0x00000400
#define CMODE_r		0x00000800
#define CMODE_c		0x00001000
#define CMODE_O		0x00002000
#define CMODE_Q		0x00004000
#define CMODE_S		0x00008000
#define CMODE_K		0x00010000
#define CMODE_V		0x00020000
#define CMODE_f		0x00040000
#define CMODE_H		0x00080000
#define CMODE_G		0x00100000
#define CMODE_C		0x00200000
#define CMODE_u		0x00400000
#define CMODE_z		0x00800000
#define CMODE_N		0x01000000
#define CMODE_L		0x02000000
#define CMODE_A		0x04000000
#define CMODE_h		0x08000000
#define CMODE_a		0x10000000
#define CMODE_q		0x20000000

/* IRCServices 4.5 Modes */
#define IS45_CMODE_i	0x00000001
#define IS45_CMODE_m	0x00000002
#define IS45_CMODE_n	0x00000004
#define IS45_CMODE_p	0x00000008
#define IS45_CMODE_s	0x00000010
#define IS45_CMODE_t	0x00000020
#define IS45_CMODE_k	0x00000040
#define IS45_CMODE_l	0x00000080
#define IS45_CMODE_R	0x00000100
#define IS45_CMODE_r	0x00000200
#define IS45_CMODE_c	0x00000400
#define IS45_CMODE_O	0x00000800
#define IS45_CMODE_A	0x00001000
#define IS45_CMODE_z	0x00002000
#define IS45_CMODE_Q	0x00004000
#define IS45_CMODE_K	0x00008000
#define IS45_CMODE_V	0x00010000
#define IS45_CMODE_H	0x00020000
#define IS45_CMODE_C	0x00040000
#define IS45_CMODE_N	0x00080000
#define IS45_CMODE_S	0x00100000
#define IS45_CMODE_G	0x00200000
#define IS45_CMODE_u	0x00400000
#define IS45_CMODE_f	0x00800000

/* Sirv modes */
#define SIRV_CMODE_I	0x00000001
#define SIRV_CMODE_M	0x00000002
#define SIRV_CMODE_N	0x00000004
#define SIRV_CMODE_P	0x00000008
#define SIRV_CMODE_S	0x00000010
#define SIRV_CMODE_T	0x00000020
#define SIRV_CMODE_K	0x00000040
#define SIRV_CMODE_L	0x00000080
#define SIRV_CMODE_R	0x00000100
#define SIRV_CMODE_J	0x00000200
#define SIRV_CMODE_r	0x00000400
#define SIRV_CMODE_C	0x00000800
#define SIRV_CMODE_o	0x00001000
#define SIRV_CMODE_m	0x00002000

/* Structure for IRCServices->Cygnus and Wrecked->Cygnus modes */
struct flag {
    char mode;
    long flag;
    long is45flag;
    char prefix;
};

/* Hash table for IRCServices->Cygnus and Wrecked->Cygnus modes */
static const struct flag cmodes[] = {
    {'t',	CMODE_t,	IS45_CMODE_t},
    {'n',	CMODE_n,	IS45_CMODE_n},
    {'s',	CMODE_s,	IS45_CMODE_s},
    {'m',	CMODE_m,	IS45_CMODE_m},
    {'l',	CMODE_l,	IS45_CMODE_l},
    {'i',	CMODE_i,	IS45_CMODE_i},
    {'p',	CMODE_p,	IS45_CMODE_p},
    {'k',	CMODE_k,	IS45_CMODE_k},
    {'r',	CMODE_r,	IS45_CMODE_r},
    {'R',	CMODE_R,	IS45_CMODE_R},
    {'c',	CMODE_c,	IS45_CMODE_c},
    {'O',	CMODE_O,	IS45_CMODE_O},
    {'Q',	CMODE_Q,	IS45_CMODE_Q},
    {'S',	CMODE_S,	IS45_CMODE_S},
    {'K',	CMODE_K,	IS45_CMODE_K},
    {'V',	CMODE_V,	IS45_CMODE_V},
    {'f',	CMODE_f,	IS45_CMODE_f},
    {'H',	CMODE_H,	IS45_CMODE_H},
    {'G',	CMODE_G,	IS45_CMODE_G},
    {'C',	CMODE_C,	IS45_CMODE_C},
    {'u',	CMODE_u,	IS45_CMODE_u},
    {'z',	CMODE_z,	IS45_CMODE_z},
    {'N',	CMODE_N,	IS45_CMODE_N},
    {'L',	CMODE_L,	0},
    {'A',	CMODE_A,	IS45_CMODE_A},
    {0,		0}
};

/* Structure for Sirv->Cygnus modes */
struct flag_sirv {
    char mode;
    long flag;
    long sirvflag;
    char prefix;
};

/* Hash table for Sirv->Cygnus modes */
static const struct flag_sirv cmodes_sirv[] = {
    {'t',	CMODE_t,	SIRV_CMODE_T},
    {'n',	CMODE_n,	SIRV_CMODE_N},
    {'s',	CMODE_s,	SIRV_CMODE_S},
    {'m',	CMODE_m,	SIRV_CMODE_M},
    {'l',	CMODE_l,	SIRV_CMODE_L},
    {'i',	CMODE_i,	SIRV_CMODE_I},
    {'p',	CMODE_p,	SIRV_CMODE_P},
    {'k',	CMODE_k,	SIRV_CMODE_K},
    {'r',	CMODE_r,	SIRV_CMODE_R},
    {'R',	CMODE_R,	SIRV_CMODE_r},
    {'c',	CMODE_c,	SIRV_CMODE_C},
    {'O',	CMODE_O,	SIRV_CMODE_o},
    {0,		0}
};

/* These are identical on one or more supported services
   packages and are reused to save space.
 */

/* Sirv and Wrecked AutoKick struct */
typedef struct autokick AutoKick;
struct autokick {
    short is_nick;
    short pad;
    char *name;
    char *reason;
};

#define	CHANMAX	64
#define	NICKMAX	32
#define	PASSMAX	32

/* Cygnus stuff */
#define CMF_UNREAD	0x00000001
#define CMF_EMAILED	0x00000002

#define CNF_ENFORCE	0x00000001
#define CNF_SECURE	0x00000002
#define CNF_HIDEMAIL	0x00000004
#define CNF_NEVEROP	0x00000010
#define CNF_NOOP	0x00000020
#define CNF_NOSUCCESSOR	0x00000040
#define CNF_PRIVATE	0x00000080
#define CNF_PRIVMSG	0x00000200
#define CNF_NOMEMO	0x00000400
#define CNF_MEMOMAIL	0x00001000
#define CNF_FROZEN	0x00002000
#define CNF_HELD	0x00004000
#define CNF_MARKED	0x00008000
#define CNF_LINKED	0x10000000
#define CNF_CSOP	0x20000000

#define CCF_VERBOSE	0x00000001
#define CCF_VOPALL	0x00000002
#define CCF_SECURE	0x00000004
#define CCF_RESTRICTED	0x00000008
#define CCF_FROZEN	0x00000010
#define CCF_HELD	0x00000020
#define CCF_MARKED	0x00000040

/* WreckedNet Stuff */
E int convert_wrecked_db ();
E int load_wrecked_ns ();
E int load_wrecked_ms ();
E int load_wrecked_cs ();
E int load_wrecked_rs ();
E int save_wrecked_ns ();
E int save_wrecked_cs ();
E int save_wrecked_rs ();

typedef struct nickinfo_wrecked NickInfo_Wrecked;
typedef struct memo_wrecked Memo_Wrecked;
typedef struct memolist_wrecked MemoList_Wrecked;
typedef struct chanaccess_wrecked ChanAccess_Wrecked;
typedef struct chaninfo_wrecked ChannelInfo_Wrecked;
typedef struct akill_wrecked AutoKill_Wrecked;
typedef struct allow_wrecked Allow_Wrecked;
typedef struct sop_wrecked SOP_Wrecked;

#define	WMF_UNREAD	0x00000001
#define WMF_EMAILED	0x00000004

#define	WNI_KILLPROTECT	0x00000001
#define	WNI_SECURE	0x00000002
#define	WNI_VERBOTEN	0x00000004
#define	WNI_PRIVATE	0x00000010
#define	WNI_SUSPENDED	0x00000020
#define	WNI_PRIVMSG	0x00000040
#define WNI_SLAVE	0x00000080
#define WNI_NOMEMO	0x00000100
#define WNI_HIDEMAIL	0x00000200
#define WNI_NEVEROP	0x00000400
#define WNI_NOOP	0x00000800
#define WNI_MARKED	0x00001000
#define WNI_MEMOMAIL	0x00002000
#define WNI_HOLD	0x00004000
#define	WNI_IDENTIFIED	0x80000000
#define	WNI_RECOGNIZED	0x40000000

#define	WCI_SECUREOPS	0x00000002
#define	WCI_TOPICLOCK	0x00000008
#define	WCI_RESTRICTED	0x00000010
#define	WCI_SECURE	0x00000040
#define	WCI_VERBOTEN	0x00000080
#define	WCI_SUSPENDED	0x00000100
#define WCI_HOLD	0x00000400
#define WCI_MARKED	0x00000800
#define WCI_VERBOSE	0x00001000
#define WCI_VOPALL	0x00002000

struct nickinfo_wrecked {
    NickInfo_Wrecked *next, *prev;
    char nick[NICKMAX];
    char pass[PASSMAX];
    char *email;
    char *url;
    char *last_usermask;
    char *last_realname;
    time_t time_registered;
    time_t last_seen;
    long accesscount;
    char **access;
    long ignorecount;
    char **ignore;
    long flags;
    long reserved[4];
    time_t last_signon;
    long uin;
};

struct memo_wrecked {
    char sender[NICKMAX];
    long number;
    time_t time;
    char *text;
    long flags;
    long reserved[4];
};

struct memolist_wrecked {
    MemoList_Wrecked *next, *prev;
    char nick[NICKMAX];
    long n_memos;
    Memo_Wrecked *memos;
    long reserved[4];
};

struct chanaccess_wrecked {
    short level;
    short is_nick;
    char *name;
};

struct chaninfo_wrecked {
    ChannelInfo_Wrecked *next, *prev;
    char name[CHANMAX];
    char founder[NICKMAX];
    char founderpass[PASSMAX];
    char *desc;
    char *url;
    time_t time_registered;
    time_t last_used;
    long accesscount;
    ChanAccess_Wrecked *access;
    long akickcount;
    AutoKick *akick;
    char mlock_on[64], mlock_off[64];
    long mlock_limit;
    char *mlock_key;
    char *last_topic;
    char last_topic_setter[NICKMAX];
    time_t last_topic_time;
    long flags;
    short *cmd_access;
    long reserved[3];
};

struct akill_wrecked {
    char *mask;
    char *reason;
    char who[NICKMAX];
    time_t time;
};

struct allow_wrecked {
    char *host;
    int amount;
    char *reason;
    char who[NICKMAX];
    time_t time;
};

struct sop_wrecked {
    char nick[NICKMAX];
};

/* IRCServices45 Stuff */
E int convert_ircservices45_db ();
E int load_ircservices45_ns ();
E int load_ircservices45_cs ();
E int load_ircservices45_rs ();
E int save_ircservices45_ns ();
E int save_ircservices45_cs ();
E int save_ircservices45_rs ();

typedef struct nickinfo_ircservices45 NickInfo_IRCServices45;
typedef struct memo_ircservices45 Memo_IRCServices45;
typedef struct suspendinfo_ircservices45 SuspendInfo_IRCServices45;
typedef struct chanaccess_ircservices45 ChanAccess_IRCServices45;
typedef struct autokick_ircservices45 AutoKick_IRCServices45;
typedef struct chaninfo_ircservices45 ChannelInfo_IRCServices45;
typedef struct akill_ircservices45 Akill_IRCServices45;
typedef struct exception_ircservices45 Exception_IRCServices45;
typedef struct sop_ircservices45 SOP_IRCServices45;

#define IS45NS_ENCRYPTEDPW	0x00000001
#define IS45NS_VERBOTEN		0x00000002
#define IS45NS_NOEXPIRE		0x00000004

#define	IS45NI_KILLPROTECT	0x00000001
#define	IS45NI_SECURE		0x00000002
#define IS45NI_HIDE_EMAIL	0x00000080
#define IS45NI_HIDE_MASK	0x00000100

#define	IS45CI_SECUREOPS	0x00000002
#define	IS45CI_TOPICLOCK	0x00000008
#define	IS45CI_RESTRICTED	0x00000010
#define	IS45CI_SECURE		0x00000040
#define	IS45CI_VERBOTEN		0x00000080
#define	IS45CI_ENCRYPTEDPW	0x00000100
#define	IS45CI_NOEXPIRE		0x00000200
#define	IS45CI_OPNOTICE		0x00000800

struct nickinfo_ircservices45 {
    NickInfo_IRCServices45 *next, *prev;
    char nick[NICKMAX];
    char pass[PASSMAX];
    char *url;
    char *email;
    char *last_usermask;
    char *last_realname;
    time_t time_registered;
    time_t last_seen;
    int status;
    char *link;
    long flags;
    SuspendInfo_IRCServices45 *suspendinfo;
    int accesscount;
    char **access;
    int memocount;
    int memomax;
    Memo_IRCServices45 *memos;
};

struct memo_ircservices45 {
    long number;
    int flags;
    time_t time;
    char sender[NICKMAX];
    char *text;
};

struct suspendinfo_ircservices45 {
    char who[NICKMAX];
    char *reason;
    time_t suspended;
};

struct chanaccess_ircservices45 {
    int in_use;
    int level;
    char *name;
};

struct autokick_ircservices45 {
    int in_use;
    int is_nick;
    char *mask;
    char *reason;
    char who[NICKMAX];
};

struct chaninfo_ircservices45 {
    ChannelInfo_IRCServices45 *next, *prev;
    char name[CHANMAX];
    char *founder;
    char *successor;
    char founderpass[PASSMAX];
    char *desc;
    char *url;
    time_t time_registered;
    time_t last_used;
    char *last_topic;
    char last_topic_setter[NICKMAX];
    time_t last_topic_time;
    long flags;
    SuspendInfo_IRCServices45 *suspendinfo;
    int *levels;
    int accesscount;
    ChanAccess_IRCServices45 *access;
    int akickcount;
    AutoKick_IRCServices45 *akick;
    long mlock_on, mlock_off;
    long mlock_limit;
    char *mlock_key;
    int memocount;
    char *entry_message;
};

struct akill_ircservices45 {
    char *mask;
    char *reason;
    char who[NICKMAX];
    time_t time;
    time_t expires;
};

struct exception_ircservices45 {
    char *mask;
    int limit;
};

struct sop_ircservices45 {
    char *nick;
};

/* SirvNET Stuff */
E int convert_sirv_db ();
E int load_sirv_ns ();
E int load_sirv_ms ();
E int load_sirv_cs ();
E int load_sirv_rs ();
E int save_sirv_ns ();
E int save_sirv_cs ();
E int save_sirv_rs ();

typedef struct nickinfo_sirv NickInfo_Sirv;
typedef struct memo_sirv Memo_Sirv;
typedef struct memolist_sirv MemoList_Sirv;
typedef struct chanaccess_sirv ChanAccess_Sirv;
typedef struct chaninfo_sirv ChannelInfo_Sirv;
typedef struct akill_sirv AutoKill_Sirv;
typedef struct trigger_sirv Trigger_Sirv;

#define SMF_UNREAD		0x0001
#define SMF_DEL			0x0002

#define SNI_KILLPROTECT		0x00000001
#define SNI_SECURE		0x00000002
#define SNI_VERBOTEN		0x00000004
#define SNI_ENCRYPTEDPW		0x00000008
#define SNI_PRIVATE		0x00000040
#define SNI_HIDE_EMAIL		0x00000080
#define SNI_MARK		0x00000100
#define SNI_HOLD		0x00000200
#define SNI_EMAILMEMOS		0x00000400
#define SNI_NOOP		0x00000800
#define SNI_NOMEMO		0x00001000
#define SNI_NEVEROP		0x00008000
#define SNI_AUTH		0x00020000
#define SNI_IDENTIFIED		0x80000000
#define SNI_RECOGNIZED		0x40000000

#define SCI_OPGUARD		0x00000002
#define SCI_RESTRICTED		0x00000010
#define SCI_IDENT		0x00000040
#define SCI_VERBOTEN		0x00000080
#define SCI_ENCRYPTEDPW		0x00000100
#define SCI_HELDCHAN		0x00000200
#define SCI_MARKCHAN		0x00000400
#define SCI_FREEZECHAN		0x00020000
#define SCI_CLOSED		0x08000000

struct nickinfo_sirv {
    NickInfo_Sirv *next, *prev;
    char nick[NICKMAX];
    char pass[PASSMAX];
    char *last_usermask;
    char *last_realname;
    time_t time_registered;
    time_t last_seen;
    long accesscount;
    char **access;
    long flags;
    time_t id_timestamp;
    unsigned short memomax;
    unsigned short channelcount;
    char *url;
    char *email;
    char *forward;
    char *hold;
    char *mark;
    char *forbid;
    int news;
    char *regemail;
    long icq;
    long auth;
    long reserved[2];
};

struct memo_sirv {
    char sender[NICKMAX];
    long number;
    time_t time;
    char *text;
    char *chan;
    short flags;
    short reserved_s;
    long reserved[3];
};

struct memolist_sirv {
    MemoList_Sirv *next, *prev;
    char nick[NICKMAX];
    long n_memos;
    Memo_Sirv *memos;
    long reserved[4];
};

struct chanaccess_sirv {
    short level;
    short is_nick;
    char *name;
    char *sponser;
};

struct chaninfo_sirv {
    ChannelInfo_Sirv *next, *prev;
    char name[CHANMAX];
    char founder[NICKMAX];
    char founderpass[PASSMAX];
    char *desc;
    time_t time_registered;
    time_t last_used;
    long accesscount;
    ChanAccess_Sirv *access;
    long akickcount;
    AutoKick *akick;
    short mlock_on, mlock_off;
    long mlock_limit;
    char *mlock_key;
    char *last_topic;
    char last_topic_setter[NICKMAX];
    time_t last_topic_time;
    long flags;
    short *levels;
    char *url;
    char *email;
    char *welcome;
    char *hold;
    char *mark;
    char *freeze;
    char *forbid;
    int topic_allow;
    long auth;
    long reserved[4];
};

struct akill_sirv {
    char *mask;
    char *reason;
    char who[NICKMAX];
    time_t time;
    time_t expires;
    long reserved[4];
};

struct trigger_sirv {
    char *mask;
    long tvalue;
    char who[NICKMAX];
    long reserved[4];
};

static int def_levels_sirv[][2] = {
    { 4,	5 },
    { 6,	3 },
    { 5,	-1 },
    { 10,	-1 },
    { 0,	5 },
    { 1,	10 },
    { 2,	13 },
    { 9,	5 },
    { 3,	5 },
    { 7,	5 },
    { 8,	3 },
    { 11,	1 },
    { -1 }
};
