#include "DatabaseLite.h" #include "ClanGnomeCore.h" #include "LL.h" #include #include LL myLL; BotNet_LL myBotNet_LL; Members_LL myMembers_LL; StringToBeReturned MyStringToBeReturned; void CheckDbDir(char *Gateway) { char path[64] = ""; if(!*Gateway) wsprintf(path, "Database\\"); else wsprintf(path, "%s\\", Gateway); if(_access(path, 0)) mkdir(path); } void log(const char *text, ...) { //CheckDbDir(); FILE *f = fopen("Database\\log.txt", "at"); if(f) { char buf[512] = ""; char msg[512] = ""; va_list argptr; va_start(argptr, text); vsprintf(msg, text, argptr); va_end(argptr); SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); wsprintf(buf, "[%02d:%02d:%02d] %s\r\n", stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, msg); fprintf(f, buf); fclose(f); } } LL::LL() { First = NULL; } LL::~LL() { this->ClearList(); } BotNet_LL::BotNet_LL() { First = NULL; } BotNet_LL::~BotNet_LL() { this->ClearList(); } Members_LL::Members_LL() { First = NULL; } Members_LL::~Members_LL() { this->ClearList(); } void LL::AddNode(string Name, unsigned long Flag) { Node *NewNode = new Node; NewNode->Name = Name; NewNode->Flags = Flag; NewNode->Next = First; First = NewNode; } unsigned long LL::ModifyNode(string Name, unsigned long Flag) { Node *TempNode = First; unsigned long Flags; while(TempNode) { if(TempNode->Name == Name) { Flags = TempNode->Flags; TempNode->Flags = Flag; return Flags; } TempNode = TempNode->Next; } AddNode(Name, Flag); return 0; } unsigned long LL::RemoveNode(string Name) { Node *TempNode = First; Node *PrevNode = NULL; while (TempNode) { if (TempNode->Name == Name) { if (PrevNode) { PrevNode->Next = TempNode->Next; } else { First = TempNode->Next; } delete TempNode; return TempNode->Flags; } PrevNode = TempNode; TempNode = TempNode->Next; } return 0; } unsigned long LL::FindNode(string Name) { Node *TempNode = First; char charName[64]; strcpy(charName, Name.c_str()); char charNodeName[64]; unsigned long addFlags = 0; while (TempNode) { strcpy(charNodeName, TempNode->Name.c_str()); if (wildcmp(charNodeName, charName)) { addFlags = TempNode->Flags | addFlags; } TempNode = TempNode->Next; } return addFlags; } unsigned long LL::FindExNode(string Name) { Node *TempNode = First; while(TempNode) { if(TempNode->Name == Name) return TempNode->Flags; TempNode = TempNode->Next; } return 0; } unsigned long LL::FindListNode(string Name) { Node *TempNode = First; char charName[64]; strcpy(charName, Name.c_str()); char charNodeName[64]; string addout; unsigned long addflags = 0; while (TempNode) { strcpy(charNodeName, TempNode->Name.c_str()); if (wildcmp(charNodeName, charName)) { if (addflags) { addout = addout + " " + TempNode->Name; } else { addout = TempNode->Name; } addflags = TempNode->Flags | addflags; } TempNode = TempNode->Next; } if (addflags) { addout = addout + " => "; MyStringToBeReturned.text = addout; MyStringToBeReturned.flags = addflags; return strlen(addout.c_str()); } else { return 0; } } unsigned long LL::FindAttrNode(unsigned long inflags) { Node *TempNode = First; char flags[32]; string sflags; string addout; unsigned long finds = 0; while (TempNode) { for (int i = 1; i < 33; i++) { flags[i] = NULL; } if ((TempNode->Flags & inflags) == inflags) { GetFlags(TempNode->Flags, flags); sflags = flags; addout = addout + TempNode->Name + ": " + sflags + ", "; finds = finds + 1; } TempNode = TempNode->Next; } if (finds) { MyStringToBeReturned.text = addout; return strlen(addout.c_str()) - 2; } else { return 0; } } void LL::ClearList() { Node *ThisNode = First; Node *LastNode = NULL; while (ThisNode) { LastNode = ThisNode; ThisNode = ThisNode->Next; delete LastNode; } First = NULL; } unsigned long BotNet_LL::AddNode(unsigned long botid, string AccountName, char *ReturnAccountName) { BotNet_Node *TempNode = First; while(TempNode) { if(TempNode->botid == botid) { if (ReturnAccountName) strncpy(ReturnAccountName, TempNode->AccountName.c_str(), strlen(TempNode->AccountName.c_str())); TempNode->AccountName = AccountName; return false; } TempNode = TempNode->Next; } BotNet_Node *NewNode = new BotNet_Node; NewNode->botid = botid; NewNode->AccountName = AccountName; NewNode->Next = First; First = NewNode; return true; } unsigned long BotNet_LL::GetAccountName(unsigned long botid, char *AccountName) { BotNet_Node *TempNode = First; while(TempNode) { if(TempNode->botid == botid) { if (AccountName) strncpy(AccountName, TempNode->AccountName.c_str(), strlen(TempNode->AccountName.c_str())); return botid; } TempNode = TempNode->Next; } return 0; } unsigned long BotNet_LL::GetBotID(string AccountName) { BotNet_Node *TempNode = First; char charNodeName[32] = ""; while(TempNode) { strcpy(charNodeName, TempNode->AccountName.c_str()); if(!strcmp(strlwr(charNodeName), AccountName.c_str())) return TempNode->botid; TempNode = TempNode->Next; } return 0; } unsigned long BotNet_LL::RemoveNode(unsigned long botid) { BotNet_Node *TempNode = First; BotNet_Node *PrevNode = NULL; while (TempNode) { if (TempNode->botid == botid) { if (PrevNode) { PrevNode->Next = TempNode->Next; } else { First = TempNode->Next; } delete TempNode; return TempNode->botid; } PrevNode = TempNode; TempNode = TempNode->Next; } return 0; } void BotNet_LL::ClearList() { BotNet_Node *ThisNode = First; BotNet_Node *LastNode = NULL; while (ThisNode) { LastNode = ThisNode; ThisNode = ThisNode->Next; delete LastNode; } First = NULL; } unsigned long Members_LL::AddNode(string username, string clantag, string lastproduct, unsigned long war3level, unsigned long w3xplevel, unsigned long seen, ULONGLONG Date, string seenchannel) { Members_Node *TempNode = First; char charNodeName[32] = ""; bool found = false; while(TempNode) { strcpy(charNodeName, TempNode->username.c_str()); if(!stricmp(charNodeName, username.c_str())) { TempNode->username = username; // update caps TempNode->clantag = clantag; // if this changed, then user is in different clan TempNode->lastproduct = lastproduct; if(!stricmp(lastproduct.c_str(), "WAR3")) TempNode->war3level = war3level; // update level else TempNode->w3xplevel = w3xplevel; // update level //if(TempNode->seen > 100) // TempNode->seen = 100; //else TempNode->seen = TempNode->seen + 1; TempNode->Date = Date; // last seen date TempNode->seenchannel = seenchannel; found = true; } TempNode = TempNode->Next; } if(!found) { Members_Node *NewNode = new Members_Node; NewNode->username = username; NewNode->clantag = clantag; NewNode->lastproduct = lastproduct; if(!stricmp(lastproduct.c_str(), "WAR3")) { NewNode->war3level = war3level; // update level NewNode->w3xplevel = 0; // update level } else { NewNode->war3level = 0; // update level NewNode->w3xplevel = w3xplevel; // update level } NewNode->seen = seen; NewNode->Date = Date; NewNode->seenchannel = seenchannel; NewNode->Next = First; First = NewNode; return true; } else return false; } unsigned long Members_LL::QuickAddNode(string username, string clantag, string lastproduct, unsigned long war3level, unsigned long w3xplevel, unsigned long seen, ULONGLONG Date, string seenchannel) { Members_Node *NewNode = new Members_Node; NewNode->username = username; NewNode->clantag = clantag; NewNode->lastproduct = lastproduct; if(!stricmp(lastproduct.c_str(), "WAR3")) { NewNode->war3level = war3level; // update level NewNode->w3xplevel = 0; // update level } else { NewNode->war3level = 0; // update level NewNode->w3xplevel = w3xplevel; // update level } NewNode->seen = seen; NewNode->Date = Date; NewNode->seenchannel = seenchannel; NewNode->Next = First; First = NewNode; return true; } unsigned long Members_LL::GetMemberInfoA(string clantag, char *msg) { Members_Node *TempNode = First; char charNodeTag[32] = ""; unsigned long countmembers = 0; unsigned long war3HighestLevel = 0; unsigned long w3xpHighestLevel = 0; unsigned long war3AvgLevel = 0; unsigned long w3xpAvgLevel = 0; char war3HighChar[32] = ""; char w3xpHighChar[32] = ""; char war3HighChan[32] = ""; char w3xpHighChan[32] = ""; ULONGLONG war3HighDate = 0; ULONGLONG w3xpHighDate = 0; while(TempNode) { strcpy(charNodeTag, TempNode->clantag.c_str()); if(!stricmp(charNodeTag, clantag.c_str())) { countmembers++; war3AvgLevel = war3AvgLevel + TempNode->war3level; w3xpAvgLevel = w3xpAvgLevel + TempNode->w3xplevel; // check if it's == for multiple top-level players? if(TempNode->war3level > war3HighestLevel) { war3HighestLevel = TempNode->war3level; strcpy(war3HighChar, TempNode->username.c_str()); strcpy(war3HighChan, TempNode->seenchannel.c_str()); war3HighDate = TempNode->Date; } if(TempNode->w3xplevel > w3xpHighestLevel) { w3xpHighestLevel = TempNode->w3xplevel; strcpy(w3xpHighChar, TempNode->username.c_str()); strcpy(w3xpHighChan, TempNode->seenchannel.c_str()); w3xpHighDate = TempNode->Date; } } TempNode = TempNode->Next; } if(countmembers) { // at least 1 member char dateback1[32] = ""; char dateback2[32] = ""; if (war3HighDate) GetDate(*(const FILETIME *)&war3HighDate, dateback1); if (w3xpHighDate) GetDate(*(const FILETIME *)&w3xpHighDate, dateback2); wsprintf(msg, "%d,%d,%d,%s,%s,%s,%d,%d,%s,%s,%s", countmembers, (war3AvgLevel / countmembers), war3HighestLevel, war3HighChar, war3HighChan, dateback1, (w3xpAvgLevel / countmembers), w3xpHighestLevel, w3xpHighChar, w3xpHighChan, dateback2); } else wsprintf(msg, "0,0,0,,,,0,0,,,"); return -1; } unsigned long Members_LL::GetMostSeenUserA(char *msg) { Members_Node *TempNode = First; unsigned long highestseen = 0; char HighName[32] = ""; char HighClan[16] = ""; char HighChan[32] = ""; ULONGLONG HighDate = 0; while(TempNode) { if(TempNode->seen > highestseen) { highestseen = TempNode->seen; strcpy(HighName, TempNode->username.c_str()); strcpy(HighClan, TempNode->clantag.c_str()); HighDate = TempNode->Date; strcpy(HighChan, TempNode->seenchannel.c_str()); } TempNode = TempNode->Next; } if(highestseen > 0) { // at least 1 member char dateback[32] = ""; GetDate(*(const FILETIME *)&HighDate, dateback); wsprintf(msg, "%s,%s,%s,%s", HighName, HighClan, dateback, HighChan); } else wsprintf(msg, ",,,"); return highestseen; } unsigned long Members_LL::GetUserInfoA(string username, char *msg) { Members_Node *TempNode = First; char charNodeUser[64] = ""; bool found = false; unsigned long countnames = 0; unsigned long foundnameid = 0; char dateback[32] = ""; while(TempNode) { countnames++; strcpy(charNodeUser, TempNode->username.c_str()); if(!stricmp(charNodeUser, username.c_str())) { GetDate(*(const FILETIME *)&TempNode->Date, dateback); if(!strcmp(TempNode->clantag.c_str(), "noclan")) wsprintf(msg, "%s was last seen %s in channel %s", TempNode->username.c_str(), dateback, TempNode->seenchannel.c_str()); else wsprintf(msg, "%s (Clan %s) was last seen %s in channel %s", TempNode->username.c_str(), TempNode->clantag.c_str(), dateback, TempNode->seenchannel.c_str()); foundnameid = countnames; found = true; } TempNode = TempNode->Next; } if(!found) wsprintf(msg, "Have not seen %s in past 20 days!", username.c_str()); return -1; } unsigned long Members_LL::GetDbStatsA(char *msg) { Members_Node *TempNode = First; unsigned long countnames = 0; unsigned long noclans = 0; while(TempNode) { countnames++; if(!strcmp(TempNode->clantag.c_str(), "noclan")) noclans++; TempNode = TempNode->Next; } wsprintf(msg, "Database contains %d Warcraft III users (%d of which are not in a clan)", countnames, noclans); return -1; } unsigned long Members_LL::OptimizeNodes() { char charNodeName[32] = ""; ULONGLONG LastSeenDate; ULONGLONG CurrentDate; SYSTEMTIME lpSystemTime; FILETIME lpFileTime; GetSystemTime(&lpSystemTime); SystemTimeToFileTime(&lpSystemTime, &lpFileTime); CurrentDate = *(const ULONGLONG *)&lpFileTime; unsigned long tick=0; unsigned long removeditems = 0; unsigned long totalremoveditems = 0; Members_Node *TempNode = First; Members_Node *PrevNode = NULL; removeditems = 1; while(removeditems) { removeditems = 0; TempNode = First; PrevNode = NULL; while (TempNode) { tick++; //log("%d", tick); // 600,000,000 = 1 minute // 36000000000 = 1 hour // 864000000000 = 1 day // 1728000000000 = 2 days // 4320000000000 = 5 days // 8640000000000 = 10 days! // 17280000000000 = 20 days! LastSeenDate = *(const ULONGLONG *)&TempNode->Date; if((CurrentDate - LastSeenDate) > 17280000000000) { if (PrevNode) { PrevNode->Next = TempNode->Next; } else { First = TempNode->Next; } //log("have not seen %s (of %s) in over 20 days", TempNode->username.c_str(), TempNode->clantag.c_str()); //RemoveNode(TempNode->username); delete TempNode; removeditems++; totalremoveditems++; break; //log("removed %s", removeditems); } PrevNode = TempNode; TempNode = TempNode->Next; } } return totalremoveditems; } unsigned long Members_LL::RemoveNode(string username) { char charNodeName[32] = ""; Members_Node *TempNode = First; Members_Node *PrevNode = NULL; while (TempNode) { strcpy(charNodeName, TempNode->username.c_str()); if(!stricmp(charNodeName, username.c_str())) { if (PrevNode) { PrevNode->Next = TempNode->Next; } else { First = TempNode->Next; } delete TempNode; return true; } PrevNode = TempNode; TempNode = TempNode->Next; } return 0; } void Members_LL::LoadNodes(char *Gateway) { char filepath[64] = ""; if(!*Gateway) wsprintf(filepath, "Database\\members"); else wsprintf(filepath, "%s\\members", Gateway); CheckDbDir(Gateway); FILE *fStream = fopen(filepath, "rt"); if (fStream) { char buf[512]; char username[32] = "", clantag[32] = "", lastproduct[32] = "", seenchannel[32] = ""; unsigned long seen = 0; unsigned long war3level = 0; unsigned long w3xplevel = 0; ULONGLONG Date = 0; while (fgets(buf, sizeof(buf), fStream)) { if (sscanf(buf, "%s %s %s %d %d %d %I64u %[^\n]" , username, clantag, lastproduct, &war3level, &w3xplevel, &seen, &Date, seenchannel)) { // if i no longer want noclans tracked, just check for clantag = noclan here if(strlen(username) > 2) myMembers_LL.QuickAddNode(username, clantag, lastproduct, war3level, w3xplevel, seen, Date, seenchannel); //log("ignoring entry %d %d %d %I64u", war3level, w3xplevel, seen, Date); } } } else fStream = fopen(filepath, "wt"); if (fStream) fclose(fStream); } void Members_LL::SaveNodes(char *Gateway) { char filepath[64] = ""; if(!*Gateway) wsprintf(filepath, "Database\\members"); else wsprintf(filepath, "%s\\members", Gateway); CheckDbDir(Gateway); Members_Node *TempNode = First; FILE *fStream = fopen(filepath, "wt"); while(TempNode) { fprintf(fStream, "%s %s %s %d %d %d %I64u %s\n", TempNode->username.c_str(), TempNode->clantag.c_str(), TempNode->lastproduct.c_str(), TempNode->war3level, TempNode->w3xplevel, TempNode->seen, TempNode->Date, TempNode->seenchannel.c_str()); TempNode = TempNode->Next; } fclose(fStream); } void Members_LL::ClearList() { Members_Node *ThisNode = First; Members_Node *LastNode = NULL; while (ThisNode) { LastNode = ThisNode; ThisNode = ThisNode->Next; delete LastNode; } First = NULL; } void WINAPI AddEntry(char *Name, DWORD Flags) { myLL.AddNode(strlwr(Name), Flags); } DWORD WINAPI ModifyEntry(char *Name, DWORD Flags) { return myLL.ModifyNode(strlwr(Name), Flags); } DWORD WINAPI FindEntry(char *Name) { return myLL.FindNode(strlwr(Name)); } DWORD WINAPI FindExEntry(char *Name) { return myLL.FindExNode(strlwr(Name)); } DWORD WINAPI FindListEntry(char *Name, char *Message) { if (Message) { strcpy(Message, MyStringToBeReturned.text.c_str()); return MyStringToBeReturned.flags; } else { return myLL.FindListNode(strlwr(Name)); } } DWORD WINAPI FindAttrEntry(DWORD Flags, char *Message) { if (Message) { strncpy(Message, MyStringToBeReturned.text.c_str(), strlen(MyStringToBeReturned.text.c_str()) - 2); return 1; } else { return myLL.FindAttrNode(Flags); } } DWORD WINAPI RemoveEntry(char *Name) { return myLL.RemoveNode(strlwr(Name)); } void WINAPI PurgeEntries() { myLL.ClearList(); } DWORD WINAPI BotNet_AddEntry(DWORD botid, char *AccountName, char *ReturnAccountName) { return myBotNet_LL.AddNode(botid, AccountName, ReturnAccountName); } DWORD WINAPI BotNet_GetAccountName(DWORD botid, char *AccountName) { return myBotNet_LL.GetAccountName(botid, AccountName); } DWORD WINAPI BotNet_GetBotID(char *AccountName) { return myBotNet_LL.GetBotID(strlwr(AccountName)); } DWORD WINAPI BotNet_RemoveEntry(DWORD botid) { return myBotNet_LL.RemoveNode(botid); } void WINAPI BotNet_PurgeEntries() { myBotNet_LL.ClearList(); } DWORD WINAPI AddMember(char *username, char *clantag, char *lastproduct, DWORD war3level, DWORD w3xplevel, char *seenchannel) { SYSTEMTIME lpSystemTime; FILETIME lpFileTime; GetSystemTime(&lpSystemTime); SystemTimeToFileTime(&lpSystemTime, &lpFileTime); return myMembers_LL.AddNode(username, clantag, lastproduct, war3level, w3xplevel, 1, *(const ULONGLONG *)&lpFileTime, seenchannel); } void GetDate(FILETIME date, char *back) { SYSTEMTIME st; FileTimeToSystemTime(&date, &st); wsprintf(back, "%02d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); } DWORD WINAPI GetMemberInfo(char *clantag, char *msg) { return myMembers_LL.GetMemberInfoA(clantag, msg); } DWORD WINAPI GetMostSeenUser(char *msg) { return myMembers_LL.GetMostSeenUserA(msg); } DWORD WINAPI GetUserInfo(char *username, char *msg) { return myMembers_LL.GetUserInfoA(username, msg); } DWORD WINAPI GetDbStats(char *msg) { return myMembers_LL.GetDbStatsA(msg); } DWORD WINAPI OptimizeMembers() { return myMembers_LL.OptimizeNodes(); } void WINAPI LoadMembers(char *Gateway) { myMembers_LL.LoadNodes(Gateway); } void WINAPI SaveMembers(char *Gateway) { myMembers_LL.SaveNodes(Gateway); } void WINAPI PurgeMembers() { myMembers_LL.ClearList(); } void WINAPI ParseTickGetVars(LARGE_INTEGER *TickCount, DWORD* Days, DWORD* Hours, DWORD* Minutes, DWORD* Seconds) { ULONGLONG ull = *(const ULONGLONG *)TickCount; ull = ull / 1000; *Days = ull / (3600 * 24); *Hours = (ull % (3600 * 24)) / 3600; *Minutes = (ull % 3600) / 60; *Seconds = (ull % 60); } LARGE_INTEGER WINAPI GetDifferenceL(LARGE_INTEGER *Num1, LARGE_INTEGER *Num2) { ULONGLONG ullNum1 = *(const ULONGLONG *)Num1; ULONGLONG ullNum2 = *(const ULONGLONG *)Num2; ULONGLONG ull = ullNum1 - ullNum2; return *(LARGE_INTEGER *)&ull; } LARGE_INTEGER WINAPI AccuratePerformanceCounter(LARGE_INTEGER *lpPerformanceCount, LARGE_INTEGER *lpFrequency) { ULONGLONG ullPerformanceCount = *(const ULONGLONG *)lpPerformanceCount; ULONGLONG ullFrequency = *(const ULONGLONG *)lpFrequency; ULONGLONG ull = ((ullPerformanceCount * 1000) / ullFrequency); return *(LARGE_INTEGER *)&ull; } DWORD WINAPI SafeText(char *text, char *msg) { if (msg) { strcpy(msg, MyStringToBeReturned.text.c_str()); return 1; } else { string out; if (text) { out = text; int i; // replace all tabs with 4 spaces while((i = out.find('\t')) != -1) out.replace(i, 1, 4, ' '); // replace 1 char at position "i" with 4 of the char ' '... I think? // replace all remaining <0x20 with '.' const char* LowAsciiNotIncludingTab = "\x01\x02\x03\x04\x05\x06\x07\x08\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; while((i = out.find_first_of(LowAsciiNotIncludingTab)) != -1) out[i] = '.'; } else out = ""; MyStringToBeReturned.text = out; return strlen(out.c_str()); } } BOOL WINAPI IsGreaterThan(LARGE_INTEGER *Num1, DWORD Num2) { ULONGLONG ullNum1 = *(const ULONGLONG *)Num1; if (ullNum1 > Num2) { return true; } else { return false; } } DWORD WINAPI RandomNumber() { return rand()<<16|rand(); } int GetFlags(unsigned long dwMask, char *lpszBuffer) { int iPos = 0; int iCount = 0; for(int i = 'A'; i <= 'Z'; i++){ if(CheckFlag(dwMask, (char)i)){ lpszBuffer[iPos++] = i; iCount++; } } lpszBuffer[strlen(lpszBuffer)] = 0; return iCount; } bool CheckFlag(unsigned long dwMask, char bFlag) { if(bFlag < 'A' || bFlag > 'Z') return false; return !!(dwMask & (1 << (bFlag - 'A'))); } int wildcmp(char *wild, char *string) { char *cp, *mp; while ((*string) && (*wild != '*')) { if ((*wild != *string) && (*wild != '?')) { return 0; } wild++; string++; } while (*string) { if (*wild == '*') { if (!*++wild) { return 1; } mp = wild; cp = string+1; } else if ((*wild == *string) || (*wild == '?')) { wild++; string++; } else { wild = mp; string = cp++; } } while (*wild == '*') { wild++; } return !*wild; }