Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include <stdio.h>
  8. #include "BanPanel.h"
  9. #include "PlayerContextMenu.h"
  10. #include "DialogAddBan.h"
  11. #include <vgui/Cursor.h>
  12. #include <vgui/ISystem.h>
  13. #include <vgui/ISurface.h>
  14. #include <vgui/ILocalize.h>
  15. #include <vgui/IVGui.h>
  16. #include <KeyValues.h>
  17. #include <vgui_controls/Label.h>
  18. #include <vgui_controls/Button.h>
  19. #include <vgui_controls/QueryBox.h>
  20. #include <vgui_controls/ListPanel.h>
  21. #include <vgui_controls/FileOpenDialog.h>
  22. #include "filesystem.h"
  23. #include "DialogCvarChange.h"
  24. #include "tokenline.h"
  25. using namespace vgui;
  26. //-----------------------------------------------------------------------------
  27. // Purpose: Constructor
  28. //-----------------------------------------------------------------------------
  29. CBanPanel::CBanPanel(vgui::Panel *parent, const char *name) : PropertyPage(parent, name)
  30. {
  31. m_pBanListPanel = new ListPanel(this, "BanList");
  32. m_pBanListPanel->AddColumnHeader(0, "type", "#Ban_List_Type", 150 );
  33. m_pBanListPanel->AddColumnHeader(1, "id", "#Ban_List_ID", 200 );
  34. m_pBanListPanel->AddColumnHeader(2, "time", "#Ban_List_Time", 200 );
  35. m_pBanListPanel->SetSortColumn(2);
  36. m_pBanListPanel->SetEmptyListText("#Ban_List_Empty");
  37. m_pAddButton = new Button(this, "Add", "#Ban_List_Add");
  38. m_pRemoveButton = new Button(this, "Remove", "#Ban_List_Remove");
  39. m_pChangeButton = new Button(this, "Change", "#Ban_List_Edit");
  40. m_pImportButton = new Button(this, "Import", "#Ban_List_Import");
  41. m_pAddButton->SetCommand(new KeyValues("addban"));
  42. m_pRemoveButton->SetCommand(new KeyValues("removeban"));
  43. m_pChangeButton->SetCommand(new KeyValues("changeban"));
  44. m_pImportButton->SetCommand(new KeyValues("importban"));
  45. m_pBanContextMenu = new CBanContextMenu(this);
  46. m_pBanContextMenu->SetVisible(false);
  47. m_flUpdateTime = 0.0f;
  48. m_bPageViewed = false;
  49. LoadControlSettings("Admin/BanPanel.res", "PLATFORM");
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose: Destructor
  53. //-----------------------------------------------------------------------------
  54. CBanPanel::~CBanPanel()
  55. {
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Activates the page
  59. //-----------------------------------------------------------------------------
  60. void CBanPanel::OnPageShow()
  61. {
  62. BaseClass::OnPageShow();
  63. OnItemSelected();
  64. if (!m_bPageViewed)
  65. {
  66. m_bPageViewed = true;
  67. // force update on first page view
  68. m_flUpdateTime = 0.0f;
  69. }
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose: Requests new data set from server
  73. //-----------------------------------------------------------------------------
  74. void CBanPanel::OnResetData()
  75. {
  76. RemoteServer().RequestValue(this, "banlist");
  77. // update once every 5 minutes
  78. m_flUpdateTime = (float)system()->GetFrameTime() + (60 * 5.0f);
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Purpose: Checks to see if the page data should be refreshed
  82. //-----------------------------------------------------------------------------
  83. void CBanPanel::OnThink()
  84. {
  85. if (m_flUpdateTime < system()->GetFrameTime())
  86. {
  87. OnResetData();
  88. }
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose: Wrap g_pVGuiLocalize->Find() and not return NULL
  92. //-----------------------------------------------------------------------------
  93. static const wchar_t * LocalizeFind( const char *identifier, const wchar_t *defaultText )
  94. {
  95. const wchar_t *str = g_pVGuiLocalize->Find(identifier);
  96. if ( !str )
  97. str = defaultText;
  98. return str;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose: Received response from server containing data
  102. //-----------------------------------------------------------------------------
  103. void CBanPanel::OnServerDataResponse(const char *value, const char *response)
  104. {
  105. // build the list
  106. if (!stricmp(value, "banlist"))
  107. {
  108. // clear current list
  109. m_pBanListPanel->DeleteAllItems();
  110. // scan through response for all items
  111. int item = 0;
  112. float banTime = 0.0f;
  113. char id[64] = { 0 };
  114. while (3 == sscanf(response, "%i %s : %f min\n", &item, id, &banTime))
  115. {
  116. KeyValues *ban = new KeyValues("ban");
  117. // determine type
  118. if (IsIPAddress(id))
  119. {
  120. // ip address
  121. ban->SetWString("type", LocalizeFind("#Ban_IP", L"IP Address"));
  122. }
  123. else
  124. {
  125. // must be a userID
  126. ban->SetWString("type", LocalizeFind("#Ban_Auth_ID", L"AuthID"));
  127. }
  128. ban->SetString("id", id);
  129. if (banTime > 0.0f)
  130. {
  131. ban->SetFloat("time", banTime);
  132. }
  133. else
  134. {
  135. ban->SetWString("time", LocalizeFind("#Ban_Permanent", L"permanent"));
  136. }
  137. // add to list
  138. m_pBanListPanel->AddItem(ban, 0, false, false);
  139. // move to the next item
  140. response = (const char *)strchr(response, '\n');
  141. if (!response)
  142. break;
  143. response++;
  144. }
  145. }
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose: Refreshes the list on the user hitting F5
  149. //-----------------------------------------------------------------------------
  150. void CBanPanel::OnKeyCodeTyped(vgui::KeyCode code)
  151. {
  152. if (code == KEY_F5)
  153. {
  154. OnResetData();
  155. }
  156. else
  157. {
  158. BaseClass::OnKeyCodeTyped(code);
  159. }
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose: opens context menu (user right clicked on a server)
  163. //-----------------------------------------------------------------------------
  164. void CBanPanel::OnOpenContextMenu(int row)
  165. {
  166. /* CONTEXT MENU CODE TEMPORARILY DISABLED UNTIL VERIFIED AS WORKING
  167. if (m_pBanListPanel->IsVisible() && m_pBanListPanel->IsCursorOver()
  168. && m_pBanListPanel->GetNumSelectedRows())
  169. // show the ban changing menu IF its the visible panel and the cursor is
  170. // over it
  171. {
  172. unsigned int banID =m_pBanListPanel->GetSelectedRow(0);
  173. // activate context menu
  174. m_pBanContextMenu->ShowMenu(this, banID);
  175. }
  176. else
  177. {
  178. m_pBanContextMenu->ShowMenu(this, -1);
  179. }
  180. */
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose: Manually adds a new ban
  184. //-----------------------------------------------------------------------------
  185. void CBanPanel::AddBan()
  186. {
  187. CDialogAddBan *box = new CDialogAddBan(this);
  188. box->AddActionSignalTarget(this);
  189. box->Activate("addban", "", "");
  190. }
  191. //-----------------------------------------------------------------------------
  192. // Purpose: prompts the user to remove an existing ban
  193. //-----------------------------------------------------------------------------
  194. void CBanPanel::RemoveBan()
  195. {
  196. int itemID = m_pBanListPanel->GetSelectedItem(0);
  197. if ( itemID == -1 )
  198. return;
  199. // ask the user whether or not they want to remove the ban
  200. KeyValues *kv = m_pBanListPanel->GetItem(itemID);
  201. if (kv != NULL)
  202. {
  203. // build the message
  204. wchar_t id[256];
  205. g_pVGuiLocalize->ConvertANSIToUnicode(kv->GetString("id"), id, sizeof(id));
  206. wchar_t message[256];
  207. g_pVGuiLocalize->ConstructString(message, sizeof(message), g_pVGuiLocalize->Find("#Ban_Remove_Msg"), 1, id);
  208. // activate the confirmation dialog
  209. QueryBox *box = new QueryBox(g_pVGuiLocalize->Find("#Ban_Title_Remove"), message);
  210. box->SetOKCommand(new KeyValues("removebanbyid", "id", kv->GetString("id")));
  211. box->AddActionSignalTarget(this);
  212. box->DoModal();
  213. }
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Purpose: change the time length of a ban
  217. //-----------------------------------------------------------------------------
  218. void CBanPanel::ChangeBan()
  219. {
  220. int itemID = m_pBanListPanel->GetSelectedItem(0);
  221. if (itemID == -1)
  222. return;
  223. KeyValues *kv = m_pBanListPanel->GetItem(itemID);
  224. if (kv != NULL)
  225. {
  226. char timeText[20];
  227. float time = kv->GetFloat("time");
  228. _snprintf(timeText, sizeof(timeText), "%0.2f", time);
  229. // open a dialog asking them what time to change the ban lenght to
  230. CDialogCvarChange *box = new CDialogCvarChange(this);
  231. box->AddActionSignalTarget(this);
  232. box->SetTitle("#Ban_Title_Change", true);
  233. box->Activate(kv->GetString("id"), timeText, "changeban", "#Ban_Change_Time");
  234. }
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Purpose: Removes the specified ban
  238. //-----------------------------------------------------------------------------
  239. void CBanPanel::RemoveBanByID(const char *id)
  240. {
  241. Assert(id && *id);
  242. if (!id || !*id)
  243. return;
  244. // send down the command
  245. char cmd[512];
  246. _snprintf(cmd, sizeof(cmd) -1, "%s %s\n", IsIPAddress(id) ? "removeip" : "removeid", id);
  247. RemoteServer().SendCommand(cmd);
  248. // force the file to be written
  249. if (IsIPAddress(id))
  250. {
  251. RemoteServer().SendCommand("writeip");
  252. }
  253. else
  254. {
  255. RemoteServer().SendCommand("writeid");
  256. }
  257. // refresh
  258. OnResetData();
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Purpose: Changes a ban
  262. //-----------------------------------------------------------------------------
  263. void CBanPanel::ChangeBanTimeByID(const char *id, const char *newtime)
  264. {
  265. Assert(id && *id);
  266. if (!id || !*id)
  267. return;
  268. // if the newtime string is not valid, then set it to 0 (permanent ban)
  269. if (!newtime || atof(newtime) < 0.001)
  270. {
  271. newtime = "0";
  272. }
  273. // send down the command
  274. char cmd[512];
  275. _snprintf(cmd, sizeof(cmd) -1, "%s %s %s\n", IsIPAddress(id) ? "addip" : "banid", newtime, id);
  276. RemoteServer().SendCommand(cmd);
  277. if (IsIPAddress(id))
  278. {
  279. RemoteServer().SendCommand("writeip");
  280. }
  281. else
  282. {
  283. RemoteServer().SendCommand("writeid");
  284. }
  285. // refresh
  286. OnResetData();
  287. }
  288. //-----------------------------------------------------------------------------
  289. // Purpose: Changes a ban
  290. //-----------------------------------------------------------------------------
  291. void CBanPanel::OnCvarChangeValue( KeyValues *kv )
  292. {
  293. const char *idText = kv->GetString( "player", "" );
  294. const char *durationText = kv->GetString( "value", "0" );
  295. ChangeBanTimeByID( idText, durationText );
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Purpose: called when a row on the list panel is selected.
  299. //-----------------------------------------------------------------------------
  300. void CBanPanel::OnItemSelected()
  301. {
  302. int itemID = m_pBanListPanel->GetSelectedItem(0);
  303. if (itemID == -1)
  304. {
  305. m_pRemoveButton->SetEnabled(false);
  306. m_pChangeButton->SetEnabled(false);
  307. }
  308. else
  309. {
  310. m_pRemoveButton->SetEnabled(true);
  311. m_pChangeButton->SetEnabled(true);
  312. }
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Purpose: Asks the user for the ban file to import
  316. //-----------------------------------------------------------------------------
  317. void CBanPanel::ImportBanList()
  318. {
  319. // Pop up the dialog
  320. FileOpenDialog *pFileDialog = new FileOpenDialog(this, "#Ban_Find_Ban_File", true);
  321. pFileDialog->AddFilter( "*.cfg", "#Config_files", true );
  322. pFileDialog->AddFilter( "*.*", "#All_files", false );
  323. pFileDialog->DoModal(true);
  324. pFileDialog->Activate();
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose: When a file is selected print out its full path in the debugger
  328. //-----------------------------------------------------------------------------
  329. void CBanPanel::OnFileSelected(const char *fullpath)
  330. {
  331. char line[255];
  332. TokenLine tok;
  333. // this can take a while, put up a waiting cursor
  334. surface()->SetCursor(dc_hourglass);
  335. // we don't use filesystem() here becuase we want to let the user pick
  336. // a file from anywhere on their filesystem... so we use stdio
  337. FILE *f = fopen(fullpath,"rb");
  338. while (!feof(f) && fgets(line, 255, f))
  339. {
  340. // parse each line of the config file adding the ban
  341. tok.SetLine(line);
  342. if (tok.CountToken() == 3)
  343. {
  344. // add the ban
  345. const char *id = tok.GetToken(2);
  346. ChangeBanTimeByID(id, "0");
  347. }
  348. }
  349. // change the cursor back to normal and shutdown file
  350. surface()->SetCursor(dc_user);
  351. if (f)
  352. {
  353. fclose(f);
  354. }
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose: returns true if the id string is an IP address, false if it's a WON or STEAM ID
  358. //-----------------------------------------------------------------------------
  359. bool CBanPanel::IsIPAddress(const char *id)
  360. {
  361. int s1, s2, s3, s4;
  362. return (4 == sscanf(id, "%d.%d.%d.%d", &s1, &s2, &s3, &s4));
  363. }