/* RequiredLibraries: xml2 */ #include "module.h" #include #include #define AUTHOR "DukePyrolator" #define VERSION "0.2 working alpha" #define MY_ENCODING "ISO-8859-1" class DB_XML_Write : public Module { private: xmlBufferPtr membuf; xmlTextWriterPtr writer; xmlChar *tmp; // unsigned char public: DB_XML_Write(const std::string &modname, const std::string &creator) : Module(modname, creator) { this->SetAuthor(AUTHOR); this->SetVersion(VERSION); this->SetType(THIRD); LIBXML_TEST_VERSION // this initialize the library and check potential API mismatches ModuleManager::Attach(I_OnSaveDatabase, this); ModuleManager::Attach(I_OnReload, this); OnSaveDatabase(); } ~DB_XML_Write() { /* * Cleanup function for the XML library. */ xmlCleanupParser(); } void OnSaveDatabase() { alog("[%s]OnSaveDatabase() called", this->name.c_str()); Header(); WriteData(); Close(); // anope WriteToFile("anope.xml"); xmlBufferFree(membuf); } void OnReload(bool starting) { alog("[%s] here we could put some code to read the configuration file (OnReload called)", this->name.c_str()); } /* initializes the file handlers and writes the header of the xml document * instead writing directly to a file, we first create the whole * document in the memory and then save it to the disk. */ void Header() { time_t t; char tbuf[80]; time(&t); membuf = xmlBufferCreate(); writer = xmlNewTextWriterMemory(membuf, 0); xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); xmlTextWriterSetIndent(writer, 1); strftime(tbuf, 80, "%c", localtime(&t)); Start("Anope"); WriteAttrib("date", tbuf); WriteAttrib("version", version_number); WriteAttrib("enc", EncModule); } void Start(const std::string &tagname) { xmlTextWriterStartElement(writer, reinterpret_cast(const_cast(tagname.c_str()))); } void WriteComment(const std::string &comment) { xmlTextWriterWriteComment(writer, reinterpret_cast(const_cast(comment.c_str()))); } void WriteAttrib(const std::string &tagname, const std::string &value) { xmlTextWriterWriteAttribute(writer, reinterpret_cast(const_cast(tagname.c_str())), reinterpret_cast(const_cast(value.c_str()))); } void Write(const std::string &tagname, const std::string &value) { xmlTextWriterWriteElement(writer, reinterpret_cast(const_cast(tagname.c_str())), reinterpret_cast(const_cast(value.c_str()))); } void Close() { xmlTextWriterEndElement(writer); } const std::string MakeString(const char *fmt, ...) { char buf[255]; va_list args; va_start(args, fmt); vsnprintf(buf, 254, fmt , args); va_end(args); return buf; } std::string Pass2Hex(unsigned char *bin) { char hex[PASSMAX*2+2]; int length = PASSMAX; static const char trans[] = "0123456789ABCDEF"; int i; memset(hex,0,length); for (i = 0; i < length; i++) { hex[i << 1] = trans[bin[i] >> 4]; hex[(i << 1) + 1] = trans[bin[i] & 0xf]; } hex[i << 1] = '\0'; return hex; } void WriteModuleData(Extensible *l) { std::deque list; char *moduledata; l->GetExtList(list); Start("ModuleData"); for (unsigned j = 0; j < list.size(); j++) { l->GetExt(list[j].c_str(), moduledata); Write(list[j].c_str(), moduledata); } Close(); // ModuleData } void SyncDB() { // membuf->content is unsigned char char *t, *s = reinterpret_cast(membuf->content); send_cmd(TS6SID, "BURST"); while (*s) { t = s; s += strcspn(s, "\n"); if (*s) *s++ = 0; send_cmd(TS6SID, "ENCAP * XMLSYNC %s", t); } send_cmd(TS6SID, "ENDBURST"); } void WriteToFile(const std::string &xmlfilename) { FILE *fp; xmlTextWriterEndDocument(writer); // make sure all tags are closed xmlFreeTextWriter(writer); fp = fopen(xmlfilename.c_str(), "w"); fprintf(fp, "%s", reinterpret_cast(const_cast(membuf->content))); fclose(fp); } void WriteData() { int i, j; /**************************************************** * NickServ Database part ***************************************************/ NickCore *nc; Start("NickCores"); for (i = 0; i < 1024; i++) { for (nc = nclists[i]; nc; nc = nc->next) { Start("NickCore"); WriteAttrib("display", nc->display); if (nc->pass) Write("pass", Pass2Hex(reinterpret_cast(nc->pass))); if (nc->email) Write("email", nc->email); if (nc->greet) Write("greet", nc->greet); if (nc->icq) Write("icq", MakeString("%i", nc->icq)); if (nc->url) Write("url", nc->url); if (nc->flags) Write("flags", MakeString("%i", nc->flags)); if (nc->language) Write("language", MakeString("%i", nc->language)); Start("accesslist"); WriteAttrib("accesssize", MakeString("%i", nc->access.size())); for (j = 0; j < static_cast(nc->access.size()); ++j) { Start("access"); WriteAttrib("value", nc->GetAccess(j)); Close(); // access } Close(); // accesslist Write("memomax", MakeString("%i", nc->memos.memomax)); Write("channelcount", MakeString("%i", nc->channelcount)); WriteModuleData(nc); Close(); // nickcore } } Close(); // nickcores NickAlias *na; Start("NickAliases"); for (i = 0; i < 1024; i++) { for (na = nalists[i]; na; na = na->next) { Start("NickAlias"); WriteAttrib("nick", na->nick); if (na->last_usermask) Write("last_usermask", na->last_usermask); if (na->last_realname) Write("last_realname", na->last_realname); if (na->last_quit) Write("last_quit", na->last_quit); if (na->time_registered) Write("time_registered", MakeString("%i", na->time_registered)); if (na->last_seen) Write("last_seen", MakeString("%i", na->last_seen)); if (na->status) Write("status", MakeString("%i", na->status)); if (na->nc->display) Write("NickCore", na->nc->display); Close(); // NickAlias } } Close(); // nickaliases NickRequest *nr; Start("NickRequests"); for (i = 0; i < 1024; i++) { for (nr = nrlists[i]; nr; nr = nr->next) { Start("NickRequest"); WriteAttrib("nick", nr->nick); Write("passcode", nr->passcode); Write("password", Pass2Hex(reinterpret_cast(nr->password))); Write("email", nr->email); Write("requested", MakeString("%i", nr->requested)); Close(); // NickRequest } } Close(); // NickRequests /**************************************************** * ChanServ Database part ***************************************************/ ChannelInfo *ci; Start("Channels"); for (i = 0; i < 256; i++) { for (ci = chanlists[i]; ci; ci = ci->next) { Start("Channel"); WriteAttrib("name", ci->name); if (ci->founder) Write("founder", ci->founder->display); if (ci->successor) Write("successor", ci->successor->display); if (ci->founderpass) Write("founderpass", Pass2Hex(reinterpret_cast(ci->founderpass))); if (ci->desc) Write("desc", ci->desc); if (ci->url) Write("url", ci->url); if (ci->email) Write("email", ci->email); Write("time_registered", MakeString("%i", ci->time_registered)); if (ci->last_used) Write("last_used", MakeString("%i", ci->last_used)); if (ci->last_topic) { Write("last_topic", ci->last_topic); Write("last_topic_setter", ci->last_topic_setter); Write("last_topic_time", MakeString("%i", ci->last_topic_time)); } if (ci->forbidby) Write("forbidby", ci->forbidby); if (ci->forbidreason) Write("forbidreason", ci->forbidreason); if (ci->bantype) Write("bantype", MakeString("%i", ci->bantype)); Start("Levels"); for (j = 0; j < CA_SIZE; j++) { Start("Level"); WriteAttrib("nr", MakeString("%i",j)); WriteAttrib("value", MakeString("%i", ci->levels[j])); Close(); // Level } Close(); // Levels Start("accesslist"); WriteAttrib("accesssize", MakeString("%i", ci->access.empty() ? 0 : ci->access.size())); for (j = 0; j < static_cast(ci->access.size()); j++) { ChanAccess *access = ci->GetAccess(j); if (!access->in_use) continue; Start("access"); WriteAttrib("nick", access->nc->display); WriteAttrib("level", MakeString("%i", access->level)); if (access->last_seen) WriteAttrib("last_seen", MakeString("%i",access->last_seen)); Close(); // access } Close(); // accesslist Start("ackicklist"); WriteAttrib("akickcount", MakeString("%i", ci->akickcount)); for (j = 0; j < ci->akickcount; j++) { if (!(ci->akick[j].flags & AK_USED)) continue; Start("akick"); WriteAttrib("nr", MakeString("%i", j)); Write("flags", MakeString("%i", ci->akick[j].flags)); if (ci->akick[j].flags & AK_ISNICK) Write("display", ci->akick[j].u.nc->display); else Write("mask", ci->akick[j].u.mask); Write("reason", ci->akick[j].reason); Write("creator", ci->akick[j].creator); Write("addtime", MakeString("%i", ci->akick[j].addtime)); Close(); // akick } Close(); // akicklist if (ci->mlock_on) Write("mlock_on", MakeString("%i", ci->mlock_on)); if (ci->mlock_off) Write("mlock_off", MakeString("%i", ci->mlock_off)); if (ci->mlock_limit) Write("mlock_limit", MakeString("%i", ci->mlock_limit)); if (ci->mlock_key) Write("mlock_key", ci->mlock_key); if (ci->mlock_flood) Write("mlock_flood", ci->mlock_flood); if (ci->mlock_redirect) Write("mlock_redirect", ci->mlock_redirect); if (ci->memos.memomax) Write("memomax", MakeString("%i", ci->memos.memomax)); Start("memolist"); WriteAttrib("memocount", MakeString("%i", ci->memos.memos.size())); for (j = 0; j < static_cast(ci->memos.memos.size()); ++j) { Memo *memo = ci->memos.memos[j]; Start("memo"); WriteAttrib("nr", MakeString("%i", j+1)); Write("number", MakeString("%i", memo->number)); Write("flags", MakeString("%i", memo->flags)); Write("time", MakeString("%i", memo->time)); Write("sender", memo->sender); Write("text", memo->text); Close(); // memo } Close(); // memolist if (ci->entry_message) Write("entry_message", ci->entry_message); if (ci->bi) Write("botservbot", ci->bi->nick); if (ci->botflags) Write("botflags", MakeString("%i", ci->botflags)); if (ci->capsmin) Write("capsmin", MakeString("%i", ci->capsmin)); if (ci->capspercent) Write("capspercent", MakeString("%i", ci->capspercent)); if (ci->floodlines) Write("floodlines", MakeString("%i", ci->floodlines)); if (ci->floodsecs) Write("floodsecs", MakeString("%i", ci->floodsecs)); if (ci->repeattimes) Write("repeattimes", MakeString("%i", ci->repeattimes)); Start("badwordlist"); WriteAttrib("bwcount", MakeString("%i", ci->bwcount)); for (j = 0; j < ci->bwcount; j++) { if (ci->badwords[j].in_use) { Start("badword"); WriteAttrib("word", ci->badwords[j].word); WriteAttrib("type", MakeString("%i", ci->badwords[j].type)); Close(); // badword } } Close(); // bwcount WriteModuleData(ci); Close(); // Channel } } Close(); // Channels /**************************************************** * BotServ Database part ***************************************************/ BotInfo *bi; Start("BotInfos"); for (i = 0; i < 256; i++) { for (bi = botlists[i]; bi; bi = bi->next) { Start("BotInfo"); WriteAttrib("nick", bi->nick); Write("user", bi->user); Write("host", bi->host); Write("real", bi->real); Write("flags", MakeString("%i", bi->flags)); Write("created", MakeString("%i", bi->created)); Write("chancount", MakeString("%i", bi->chancount)); Close(); // BotInfo } } Close(); // BotInfos /**************************************************** * HostServ Database part ***************************************************/ HostCore *hc = NULL; Start("HostCores"); hc = hostCoreListHead(); while (hc != NULL) { Start("HostCore"); WriteAttrib("nick", hc->nick); Write("vIdent", hc->vIdent); Write("vHost", hc->vHost); Write("creator", hc->creator); Write("time", MakeString("%i", hc->time)); Close(); // HostCore hc = hc->next; } Close(); // HostCores /**************************************************** * OperServ Database part ***************************************************/ Akill *ak; SXLine *sx; Start("OperServ"); Write("maxusercnt", MakeString("%i", maxusercnt)); Write("maxusertime", MakeString("%i", maxusertime)); Start("akills"); WriteAttrib("count", MakeString("%i", akills.count)); for (i = 0; i < akills.count; i++) { ak = static_cast(akills.list[i]); Start("akill"); WriteAttrib("nr", MakeString("%i")); if (ak->user) Write("user", ak->user); if (ak->host) Write("host", ak->host); Write("by", ak->by); Write("reason", ak->reason); Write("seton", MakeString("%i", ak->seton)); Write("expires", MakeString("%i", ak->expires)); Close(); // akill } Close(); // akills Start("sglines"); WriteAttrib("count", MakeString("%i", sglines.count)); for (i = 0; i < sglines.count; i++) { sx = static_cast(sglines.list[i]); Start("sgline"); WriteAttrib("nr", MakeString("%i", i)); Write("mask", sx->mask); Write("by", sx->by); Write("reason", sx->reason); Write("seton", MakeString("%i", sx->seton)); Write("expires", MakeString("%i", sx->expires)); Close(); // sgline } Close(); // sglines Start("sqlines"); WriteAttrib("count", MakeString("%i", sqlines.count)); for (i = 0; i < sqlines.count; i++) { sx = static_cast(sqlines.list[i]); Start("sqline"); WriteAttrib("nr", MakeString("%i", i)); Write("mask", sx->mask); Write("by", sx->by); Write("reason", sx->reason); Write("seton", MakeString("%i", sx->seton)); Write("expires", MakeString("%i", sx->expires)); Close(); // sqline } Close(); // sqlines Start("szlines"); WriteAttrib("count", MakeString("%i", szlines.count)); for (i = 0; i < szlines.count; i++) { sx = static_cast(szlines.list[i]); Start("szline"); WriteAttrib("nr", MakeString("%i", i)); Write("mask", sx->mask); Write("by", sx->by); Write("reason", sx->reason); Write("seton", MakeString("%i", sx->seton)); Write("expires", MakeString("%i", sx->expires)); Close(); // szline } Close(); // szlines Start("exceptions"); WriteAttrib("count", MakeString("%i", nexceptions)); for (i = 0; i < nexceptions; i++) { Start("exception"); WriteAttrib("mask", exceptions[i].mask); Write("limit", MakeString("%i", exceptions[i].limit)); Write("who", exceptions[i].who); Write("reason", exceptions[i].reason); Write("time", MakeString("%i", exceptions[i].time)); Write("expires", MakeString("%i", exceptions[i].expires)); Close(); // exception } Close(); // exceptions Start("newslist"); WriteAttrib("count", MakeString("%i", nnews)); for (i = 0; i < nnews; i++) { Start("news"); WriteAttrib("nr", MakeString("%i", i)); Write("type", MakeString("%i", news[i].type)); Write("num", MakeString("%i", news[i].num)); Write("text", news[i].text); Write("who", news[i].who); Write("time", MakeString("%i", news[i].time)); Close(); // news } Close(); // newslist Close(); // OperServ Close(); // Anope } // void WriteData }; MODULE_INIT(DB_XML_Write)