/// Get online time. HK_ERROR HkGetOnLineTime(const wstring &charname, int &iSecs) { wstring wscDir; if(!HKHKSUCCESS(HkGetAccountDirName(charname, wscDir))) return HKE_CHAR_DOES_NOT_EXIST; wstring wscFile; HkGetCharFileName(charname, wscFile); string scCharFile = scAcctPath + wstos(wscDir) + "\\" + wstos(wscFile) + ".fl"; if (HkIsEncoded(scCharFile)) { string scCharFileNew = scCharFile + ".ini"; if (!flc_decode(scCharFile.c_str(), scCharFileNew.c_str())) return HKE_COULD_NOT_DECODE_CHARFILE; iSecs = (int)IniGetF(scCharFileNew, "mPlayer", "total_time_played", 0.0f); DeleteFile(scCharFileNew.c_str()); } else { iSecs = (int)IniGetF(scCharFile, "mPlayer", "total_time_played", 0.0f); } return HKE_OK; }
void LoadUserSettings(uint iClientID) { CAccount *acc = Players.FindAccountFromClientID(iClientID); wstring wscDir; HkGetAccountDirName(acc, wscDir); string scUserFile = scAcctPath + wstos(wscDir) + "\\flhookuser.ini"; // read diemsg settings ClientInfo[iClientID].dieMsg = (DIEMSGTYPE)IniGetI(scUserFile, "settings", "DieMsg", DIEMSG_ALL); ClientInfo[iClientID].dieMsgSize = (CHATSIZE)IniGetI(scUserFile, "settings", "DieMsgSize", CS_DEFAULT); // read chatstyle settings ClientInfo[iClientID].chatSize = (CHATSIZE)IniGetI(scUserFile, "settings", "ChatSize", CS_DEFAULT); ClientInfo[iClientID].chatStyle = (CHATSTYLE)IniGetI(scUserFile, "settings", "ChatStyle", CST_DEFAULT); // read ignorelist ClientInfo[iClientID].lstIgnore.clear(); for(int i = 1; ; i++) { wstring wscIgnore = IniGetWS(scUserFile, "IgnoreList", itos(i), L""); if(!wscIgnore.length()) break; IGNORE_INFO ii; ii.wscCharname = GetParam(wscIgnore, ' ', 0); ii.wscFlags = GetParam(wscIgnore, ' ', 1); ClientInfo[iClientID].lstIgnore.push_back(ii); } }
/** Start automatic zone checking */ void IPBans::AdminCmd_AuthenticateChar(CCmds* cmds, const wstring &wscCharname) { if (!(cmds->rights & RIGHT_SUPERADMIN)) { cmds->Print(L"ERR No permission\n"); return; } // init variables char szDataPath[MAX_PATH]; GetUserDataPath(szDataPath); wstring wscDir; if (HkGetAccountDirName(wscCharname, wscDir)!=HKE_OK) { cmds->Print(L"ERR Account not found\n"); return; } string scPath = string(szDataPath) + "\\Accts\\MultiPlayer\\" + wstos(wscDir) + "\\authenticated"; FILE *fTest = fopen(scPath.c_str(), "w"); if (!fTest) { cmds->Print(L"ERR Writing authentication file\n"); return; } fclose(fTest); cmds->Print(L"OK\n"); }
bool HkAddCheaterLog(const wstring &wscCharname, const wstring &wscReason) { FILE *f = fopen(("./flhook_logs/flhook_cheaters.log"), "at"); if(!f) return false; CAccount *acc = HkGetAccountByCharname(wscCharname); wstring wscAccountDir = L"???"; wstring wscAccountID = L"???"; if(acc) { HkGetAccountDirName(acc, wscAccountDir); wscAccountID = HkGetAccountID(acc); } uint iClientID = HkGetClientIdFromCharname(wscCharname); wstring wscHostName = L"???"; wstring wscIp = L"???"; if(iClientID != -1) { wscHostName = ClientInfo[iClientID].wscHostname; HkGetPlayerIP(iClientID,wscIp); } time_t tNow = time(0); struct tm *stNow = localtime(&tNow); fprintf(f, "%.2d/%.2d/%.4d %.2d:%.2d:%.2d Possible cheating detected (%s) by %s(%s)(%s) [%s %s]\n", stNow->tm_mon + 1, stNow->tm_mday, stNow->tm_year + 1900, stNow->tm_hour, stNow->tm_min, stNow->tm_sec, wstos(wscReason).c_str(), wstos(wscCharname).c_str(), wstos(wscAccountDir).c_str(), wstos(wscAccountID).c_str(), wstos(wscHostName).c_str(), wstos(wscIp).c_str()); fclose(f); return true; }
HK_ERROR HkGetAdmin(const wstring &wscCharname, wstring &wscRights) { wscRights = L""; HK_GET_CLIENTID(iClientID, wscCharname); CAccount *acc; if(iClientID == -1) { flstr *str = CreateWString(wscCharname.c_str()); acc = Players.FindAccountFromCharacterName(*str); FreeWString(str); if(!acc) return HKE_CHAR_DOES_NOT_EXIST;; } else { acc = Players.FindAccountFromClientID(iClientID); } wstring wscDir; HkGetAccountDirName(acc, wscDir); string scAdminFile = scAcctPath + wstos(wscDir) + "\\flhookadmin.ini"; WIN32_FIND_DATA fd; HANDLE hFind = FindFirstFile(scAdminFile.c_str(), &fd); if(hFind == INVALID_HANDLE_VALUE) return HKE_PLAYER_NO_ADMIN;; FindClose(hFind); wscRights = stows(IniGetS(scAdminFile, "admin", "rights", "")); return HKE_OK; }
void LogCheater(uint client, const wstring &reason) { CAccount *acc = Players.FindAccountFromClientID(client); if (!HkIsValidClientID(client) || !acc) { AddLog("ERROR: invalid parameter in log cheater, clientid=%u acc=%08x reason=%s", client, acc, wstos(reason).c_str()); return; } //internal log string scText = wstos(reason); Logging("%s", scText.c_str()); // Set the kick timer to kick this player. We do this to break potential // stack corruption. HkDelayedKick(client, 1); // Ban the account. flstr *flStr = CreateWString(acc->wszAccID); Players.BanAccount(*flStr, true); FreeWString(flStr); // Overwrite the ban file so that it contains the ban reason wstring wscDir; HkGetAccountDirName(acc, wscDir); string scBanPath = scAcctPath + wstos(wscDir) + "\\banned"; FILE *file = fopen(scBanPath.c_str(), "wb"); if (file) { fprintf(file, "Autobanned by Marketfucker\n"); fclose(file); } }
bool HkAddConnectLog(uint iClientID, wstring wscReason, ...) { wchar_t wszBuf[1024*8] = L""; va_list marker; va_start(marker, wscReason); _vsnwprintf(wszBuf, (sizeof(wszBuf) / 2) - 1, wscReason.c_str(), marker); FILE *f = fopen(("./flhook_logs/flhook_connects.log"), "at"); if(!f) return false; const wchar_t *wszCharname = (wchar_t*)Players.GetActiveCharacterName(iClientID); if(!wszCharname) wszCharname = L""; CAccount *acc = Players.FindAccountFromClientID(iClientID); wstring wscAccountDir; HkGetAccountDirName(acc, wscAccountDir); time_t tNow = time(0); struct tm *stNow = localtime(&tNow); fprintf(f, "%.2d/%.2d/%.4d %.2d:%.2d:%.2d Connect (%s): %s(%s)(%s)\n", stNow->tm_mon + 1, stNow->tm_mday, stNow->tm_year + 1900, stNow->tm_hour, stNow->tm_min, stNow->tm_sec, wstos(wszBuf).c_str(), wstos(wszCharname).c_str(), wstos(wscAccountDir).c_str(), wstos(HkGetAccountID(acc)).c_str()); fclose(f); return true; }
HK_ERROR HkGetAccountDirName(const wstring &wscCharname, wstring &wscDir) { HK_GET_CLIENTID(iClientID, wscCharname); CAccount *acc; if(iClientID != -1) acc = Players.FindAccountFromClientID(iClientID); else { if(!(acc = HkGetAccountByCharname(wscCharname))) return HKE_CHAR_DOES_NOT_EXIST; } return HkGetAccountDirName(acc, wscDir); }
/* copy pasta from playercntl as to provide independance*/ string GetUserFilePath(const wstring &wscCharname, const string &scExtension) { // init variables char szDataPath[MAX_PATH]; GetUserDataPath(szDataPath); string scAcctPath = string(szDataPath) + "\\Accts\\MultiPlayer\\"; wstring wscDir; wstring wscFile; if (HkGetAccountDirName(wscCharname, wscDir) != HKE_OK) return ""; if (HkGetCharFileName(wscCharname, wscFile) != HKE_OK) return ""; return scAcctPath + wstos(wscDir) + "\\" + wstos(wscFile) + scExtension; }
/// Return true if this client is has a "Authenticated" file in the /// account directory indicating that the client can connect even if /// they are otherwise on a restricted IP range. static bool IsAuthenticated(uint iClientID) { CAccount *acc = Players.FindAccountFromClientID(iClientID); if (!acc) return false; wstring wscDir; HkGetAccountDirName(acc, wscDir); string scUserFile = scAcctPath + wstos(wscDir) + "\\authenticated"; FILE* fTest = fopen(scUserFile.c_str(), "r"); if (!fTest) return false; fclose(fTest); return true; }
/** Determine the path name of a file in the charname account directory with the provided extension. The resulting path is returned in the path parameter. */ string GetUserFilePath(const wstring &charname) { // init variables char datapath[MAX_PATH]; GetUserDataPath(datapath); string scAcctPath = string(datapath) + "\\Accts\\MultiPlayer\\"; wstring wscDir; wstring wscFile; if (HkGetAccountDirName(charname, wscDir)!=HKE_OK) return ""; if (HkGetCharFileName(charname, wscFile)!=HKE_OK) return ""; return scAcctPath + wstos(wscDir) + "\\" + wstos(wscFile) + ".fl"; }
static bool IsBanned(wstring charname) { char datapath[MAX_PATH]; GetUserDataPath(datapath); wstring dir; HkGetAccountDirName(charname, dir); string banfile = string(datapath) + "\\Accts\\MultiPlayer\\" + wstos(dir) + "\\banned"; // Prevent ships from banned accounts from being moved. FILE *f = fopen(banfile.c_str(), "r"); if (f) { fclose(f); return true; } return false; }
HK_ERROR HkDelAdmin(const wstring &wscCharname) { HK_GET_CLIENTID(iClientID, wscCharname); CAccount *acc; if(iClientID == -1) { flstr *str = CreateWString(wscCharname.c_str()); acc = Players.FindAccountFromCharacterName(*str); FreeWString(str); if(!acc) return HKE_CHAR_DOES_NOT_EXIST;; } else { acc = Players.FindAccountFromClientID(iClientID); } wstring wscDir; HkGetAccountDirName(acc, wscDir); string scAdminFile = scAcctPath + wstos(wscDir) + "\\flhookadmin.ini"; DeleteFile(scAdminFile.c_str()); return HKE_OK; }
void LoadUserCharSettings(uint iClientID) { CAccount *acc = Players.FindAccountFromClientID(iClientID); wstring wscDir; HkGetAccountDirName(acc, wscDir); string scUserFile = scAcctPath + wstos(wscDir) + "\\flhookuser.ini"; // read autobuy wstring wscFilename; HkGetCharFileName(ARG_CLIENTID(iClientID), wscFilename); string scSection = "autobuy_" + wstos(wscFilename); ClientInfo[iClientID].bAutoBuyMissiles = IniGetB(scUserFile, scSection, "missiles", false); ClientInfo[iClientID].bAutoBuyMines = IniGetB(scUserFile, scSection, "mines", false); ClientInfo[iClientID].bAutoBuyTorps = IniGetB(scUserFile, scSection, "torps", false); ClientInfo[iClientID].bAutoBuyCD = IniGetB(scUserFile, scSection, "cd", false); ClientInfo[iClientID].bAutoBuyCM = IniGetB(scUserFile, scSection, "cm", false); ClientInfo[iClientID].bAutoBuyReload = IniGetB(scUserFile, scSection, "reload", false); CALL_PLUGINS(PLUGIN_LoadUserCharSettings,(iClientID)); }
/// Set the move char code for all characters in the account void Rename::AdminCmd_SetAccMoveCode(CCmds* cmds, const wstring &wscCharname, const wstring &wscCode) { // Don't indicate an error if moving is disabled. if (!set_bEnableMoveChar) return; if (!(cmds->rights & RIGHT_SUPERADMIN)) { cmds->Print(L"ERR No permission\n"); return; } wstring wscDir; if (HkGetAccountDirName(wscCharname, wscDir)!=HKE_OK) { cmds->Print(L"ERR Charname not found\n"); return; } if (wscCode.length()==0) { cmds->Print(L"ERR Code too small, set to none to clear.\n"); return; } // Get the account path. char szDataPath[MAX_PATH]; GetUserDataPath(szDataPath); string scPath = string(szDataPath) + "\\Accts\\MultiPlayer\\" + wstos(wscDir) + "\\*.fl"; // Open the directory iterator. WIN32_FIND_DATA FindFileData; HANDLE hFileFind = FindFirstFile(scPath.c_str(), &FindFileData); if (hFileFind==INVALID_HANDLE_VALUE) { cmds->Print(L"ERR Account directory not found\n"); return; } // Iterate it do { string scCharfile = FindFileData.cFileName; string scMoveCodeFile = string(szDataPath) + "\\Accts\\MultiPlayer\\" + wstos(wscDir) + "\\" + scCharfile.substr(0,scCharfile.size()-3) + "-movechar.ini"; if (wscCode==L"none") { IniWriteW(scMoveCodeFile, "Settings", "Code", L""); cmds->Print(L"OK Movechar code cleared on "+stows(scCharfile)+L"\n"); } else { IniWriteW(scMoveCodeFile, "Settings", "Code", wscCode); cmds->Print(L"OK Movechar code set to "+wscCode +L" on "+stows(scCharfile)+L"\n"); } } while (FindNextFile(hFileFind, &FindFileData)); FindClose(hFileFind); cmds->Print(L"OK\n"); }
/** Move a character from a remote account into this one. */ bool Rename::UserCmd_MoveChar(uint iClientID, const wstring &wscCmd, const wstring &wscParam, const wchar_t *usage) { HK_ERROR err; // Don't indicate an error if moving is disabled. if (!set_bEnableMoveChar) return false; // Indicate an error if the command does not appear to be formatted correctly // and stop processing but tell FLHook that we processed the command. if (wscParam.size()==0) { PrintUserCmdText(iClientID, L"ERR Invalid parameters"); PrintUserCmdText(iClientID, usage); return true; } uint iBaseID; pub::Player::GetBase(iClientID, iBaseID); if (!iBaseID) { PrintUserCmdText(iClientID, L"ERR Not in base"); return true; } // Get the target account directory. string scFile; wstring wscMovingCharname = Trim(GetParam(wscParam, L' ', 0)); if (!GetUserFilePath(scFile, wscMovingCharname, "-movechar.ini")) { PrintUserCmdText(iClientID, L"ERR Character does not exist"); return true; } // Check the move char code. wstring wscCode = Trim(GetParam(wscParam, L' ', 1)); wstring wscTargetCode = IniGetWS(scFile, "Settings", "Code", L""); if (!wscTargetCode.length() || wscTargetCode!=wscCode) { PrintUserCmdText(iClientID, L"ERR Move character access denied"); return true; } // Get the character name for this connection. wstring wscCharname = (const wchar_t*)Players.GetActiveCharacterName(iClientID); for (map<wstring, LockedShipsStruct>::iterator i = MapLockedShips.begin(); i != MapLockedShips.end(); ++i) { if ((i->first == wscMovingCharname) && (i->second.LockLevel > 0)) { PrintUserCmdText(iClientID, L"ERR This ship is locked. The FBI has been notified."); wstring spurdoip; HkGetPlayerIP(iClientID, spurdoip); AddLog("SHIPLOCK: Attempt to movechar locked ship %s from IP %s", wstos(wscMovingCharname).c_str(), wstos(spurdoip).c_str()); ConPrint(L"SHIPLOCK: Attempt to movechar locked ship %s from IP %s\n", wscMovingCharname.c_str(), spurdoip.c_str()); return true; } } // Prevent ships from banned accounts from being moved. if (IsBanned(wscMovingCharname)) { PrintUserCmdText(iClientID, L"ERR not permitted"); return true; } // Saving the characters forces an anti-cheat checks and fixes // up a multitude of other problems. HkSaveChar(wscCharname); HkSaveChar(wscMovingCharname); // Read the current number of credits for the player // and check that the character has enough cash. int iCash = 0; if ((err = HkGetCash(wscCharname, iCash)) != HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } if (set_iMoveCost>0 && iCash<set_iMoveCost) { PrintUserCmdText(iClientID, L"ERR Insufficient credits"); return true; } // Check there is room in this account. CAccount *acc=Players.FindAccountFromClientID(iClientID); if (acc->iNumberOfCharacters >= 7) { PrintUserCmdText(iClientID, L"ERR Too many characters in account"); return true; } // Copy character file into this account with a temp name. char szDataPath[MAX_PATH]; GetUserDataPath(szDataPath); string scAcctPath = string(szDataPath) + "\\Accts\\MultiPlayer\\"; wstring wscDir; wstring wscSourceDir; wstring wscSourceFile; if ((err = HkGetAccountDirName(wscCharname, wscDir))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } if ((err = HkGetAccountDirName(wscMovingCharname, wscSourceDir))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } if ((err = HkGetCharFileName(wscMovingCharname, wscSourceFile))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } // Remove cash if we're charging for it. if (set_iMoveCost>0) HkAddCash(wscCharname, 0-set_iMoveCost); HkSaveChar(wscCharname); // Schedule the move MOVE o; o.wscDestinationCharname = wscCharname; o.wscMovingCharname = wscMovingCharname; o.scSourceFile = scAcctPath + wstos(wscSourceDir) + "\\" + wstos(wscSourceFile) + ".fl"; o.scDestFile = scAcctPath + wstos(wscDir) + "\\" + wstos(wscSourceFile) + ".fl"; o.scDestFileTemp = scAcctPath + wstos(wscDir) + "\\" + wstos(wscSourceFile) + ".fl.moving"; pendingMoves.push_back(o); // Delete the move code ::DeleteFileA(scFile.c_str()); // Kick HkKickReason(o.wscDestinationCharname, L"Moving character, please wait 10 seconds before reconnecting"); HkKickReason(o.wscMovingCharname, L"Moving character, please wait 10 seconds before reconnecting"); return true; }
bool UserCmd_RenameMe(uint iClientID, const wstring &wscCmd, const wstring &wscParam, const wchar_t *usage) { HK_ERROR err; // Don't indicate an error if moving is disabled. if (!set_bEnableRenameMe) return false; // Indicate an error if the command does not appear to be formatted correctly // and stop processing but tell FLHook that we processed the command. if (wscParam.size()==0) { PrintUserCmdText(iClientID, L"ERR Invalid parameters"); PrintUserCmdText(iClientID, usage); return true; } uint iBaseID; pub::Player::GetBase(iClientID, iBaseID); if (!iBaseID) { PrintUserCmdText(iClientID, L"ERR Not in base"); return true; } // If the new name contains spaces then flag this as an // error. wstring wscNewCharname = Trim(GetParam(wscParam, L' ', 0)); // Get the character name for this connection. wstring wscCharname = (const wchar_t*)Players.GetActiveCharacterName(iClientID); for (map<wstring, LockedShipsStruct>::iterator i = MapLockedShips.begin(); i != MapLockedShips.end(); ++i) { if ((i->first == wscCharname) && (i->second.LockLevel > 0)) { PrintUserCmdText(iClientID, L"ERR This ship is locked. The FBI has been notified."); wstring spurdoip; HkGetPlayerIP(iClientID, spurdoip); AddLog("SHIPLOCK: Attempt to rename locked ship %s from IP %s", wstos(wscCharname).c_str(), wstos(spurdoip).c_str()); ConPrint(L"SHIPLOCK: Attempt to rename locked ship %s from IP %s\n", wscCharname.c_str(), spurdoip.c_str()); return true; } } if (wscNewCharname.find(L" ")!=-1) { PrintUserCmdText(iClientID, L"ERR Space characters not allowed in name"); return true; } if (HkGetAccountByCharname(wscNewCharname)) { PrintUserCmdText(iClientID, L"ERR Name already exists"); return true; } if (wscNewCharname.length() > 23) { PrintUserCmdText(iClientID, L"ERR Name to long"); return true; } if (wscNewCharname.length() < MIN_CHAR_TAG_LEN) { PrintUserCmdText(iClientID, L"ERR Name to short"); return true; } if (set_bCharnameTags) { wstring wscPassword = Trim(GetParam(wscParam, L' ', 1)); for (std::map<wstring, TAG_DATA>::iterator i = mapTagToPassword.begin(); i != mapTagToPassword.end(); ++i) { if (wscNewCharname.find(i->first)==0 && i->second.rename_password.size() != 0) { if (!wscPassword.length()) { PrintUserCmdText(iClientID, L"ERR Name starts with an owned tag. Password is required."); return true; } else if (wscPassword != i->second.master_password && wscPassword != i->second.rename_password) { PrintUserCmdText(iClientID, L"ERR Name starts with an owned tag. Password is wrong."); return true; } // Password is valid for owned tag. break; } } } // Saving the characters forces an anti-cheat checks and fixes // up a multitude of other problems. HkSaveChar(wscCharname); if (!HkIsValidClientID(iClientID)) return true; // Read the current number of credits for the player // and check that the character has enough cash. int iCash = 0; if ((err = HkGetCash(wscCharname, iCash)) != HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } if (set_iRenameCost>0 && iCash<set_iRenameCost) { PrintUserCmdText(iClientID, L"ERR Insufficient credits"); return true; } // Read the last time a rename was done on this character wstring wscDir; if ((err = HkGetAccountDirName(wscCharname, wscDir))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } string scRenameFile = scAcctPath + wstos(wscDir) + "\\" + "rename.ini"; int lastRenameTime = IniGetI(scRenameFile, "General", wstos(wscCharname), 0); // If a rename was done recently by this player then reject the request. // I know that time() returns time_t...shouldn't matter for a few years // yet. if ((lastRenameTime + 300) < (int)time(0)) { if ((lastRenameTime + set_iRenameTimeLimit) > (int)time(0)) { PrintUserCmdText(iClientID, L"ERR Rename time limit"); return true; } } char szDataPath[MAX_PATH]; GetUserDataPath(szDataPath); string scAcctPath = string(szDataPath) + "\\Accts\\MultiPlayer\\"; wstring wscSourceFile; if ((err = HkGetCharFileName(wscCharname, wscSourceFile))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } wstring wscDestFile; if ((err = HkGetCharFileName(wscNewCharname, wscDestFile))!=HKE_OK) { PrintUserCmdText(iClientID, L"ERR "+HkErrGetText(err)); return true; } // Remove cash if we're charging for it. if (set_iRenameCost>0) HkAddCash(wscCharname, 0-set_iRenameCost); RENAME o; o.wscCharname = wscCharname; o.wscNewCharname = wscNewCharname; o.scSourceFile = scAcctPath + wstos(wscDir) + "\\" + wstos(wscSourceFile) + ".fl"; o.scDestFile = scAcctPath + wstos(wscDir) + "\\" + wstos(wscDestFile) + ".fl"; o.scDestFileTemp = scAcctPath + wstos(wscDir) + "\\" + wstos(wscSourceFile) + ".fl.renaming"; pendingRenames.push_back(o); HkKickReason(o.wscCharname, L"Updating character, please wait 10 seconds before reconnecting"); IniWrite(scRenameFile, "General", wstos(o.wscNewCharname), itos((int)time(0))); return true; }