From c229c6693b3dd55f02fe3a81403870044c0786b2 Mon Sep 17 00:00:00 2001
From: HarpyWar <harpywar@gmail.com>
Date: Tue, 25 Mar 2014 22:57:35 +0400
Subject: [PATCH] Command /find <substr to search for inside username>
 http://developer.berlios.de/patch/?func=detailpatch&patch_id=1526&group_id=2291

---
 conf/bnhelp.conf.in         |  7 ++++++
 conf/command_groups.conf.in |  2 +-
 src/bnetd/account.cpp       | 32 ++++++++++++++++++++++++++
 src/bnetd/account.h         |  1 +
 src/bnetd/command.cpp       | 45 +++++++++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/conf/bnhelp.conf.in b/conf/bnhelp.conf.in
index 5fce973..95fb216 100644
--- a/conf/bnhelp.conf.in
+++ b/conf/bnhelp.conf.in
@@ -202,5 +202,12 @@ Disband your clan
 /clearstats - used to clear game statistics of a given user/clienttag
 Syntax: /clearstats <user> <clienttag>
   <clienttag> can be one of DSHR,DRTL,SSHR,STAR,SEXP,W2BNE,WAR3,W3XP,ALL
+%find
+/find - used to find users with similar name  
+Syntax: /find <substring to find>
+    <substring to find> needs to be in lower case
+%save
+/save - used to force save accounts changes from a cache into database 
+Syntax: /save
 #                                                                            #
 ##############################################################################
diff --git a/conf/command_groups.conf.in b/conf/command_groups.conf.in
index b094d03..42efdf7 100644
--- a/conf/command_groups.conf.in
+++ b/conf/command_groups.conf.in
@@ -160,7 +160,7 @@
 
 7	/set /commandgroups /cg /clearstats
 
-8	/shutdown /rehash /save
+8	/shutdown /rehash /find /save
 
 #	//////////////////////////////////////
 #	///// End of Command Groups File /////
diff --git a/src/bnetd/account.cpp b/src/bnetd/account.cpp
index 8a84a98..43d0a93 100644
--- a/src/bnetd/account.cpp
+++ b/src/bnetd/account.cpp
@@ -545,6 +545,38 @@ namespace pvpgn
 		}
 
 
+		extern char const *accountlist_find_vague_account(t_account * account, char const *vague_username)
+		{
+			char const *tname;
+			int i;
+
+			if (!vague_username) {
+				eventlog(eventlog_level_error, __FUNCTION__, "got NULL vague_username");
+				return NULL;
+			}
+			if (!account) {
+				eventlog(eventlog_level_error, __FUNCTION__, "got NULL account");
+				return NULL;
+			}
+
+
+			if (tname = account_get_name(account)) {
+				char temp[MAX_USERNAME_LEN];
+				for (i = 0; i < std::strlen(tname); i++) {
+					temp[i] = tname[i];
+					if (isupper((int)temp[i])) {
+						temp[i] = tolower((int)temp[i]);
+					}
+				}
+				if (strstr(temp, vague_username)) {
+					return tname;
+				}
+				return NULL;
+			}
+			return NULL;
+		}
+
+
 		extern int accountlist_allow_add(void)
 		{
 			if (force_account_add)
diff --git a/src/bnetd/account.h b/src/bnetd/account.h
index 67230b1..e0b4395 100644
--- a/src/bnetd/account.h
+++ b/src/bnetd/account.h
@@ -106,6 +106,7 @@ namespace pvpgn
 		extern int accountlist_flush(unsigned flags);
 		extern t_account * accountlist_find_account(char const * username);
 		extern t_account * accountlist_find_account_by_uid(unsigned int uid);
+		extern char const *accountlist_find_vague_account(t_account * account, char const *vague_username);
 		extern int accountlist_allow_add(void);
 		extern t_account * accountlist_create_account(const char *username, const char *passhash1);
 		extern void accounts_get_attr(char const *);
diff --git a/src/bnetd/command.cpp b/src/bnetd/command.cpp
index c649231..db47f31 100644
--- a/src/bnetd/command.cpp
+++ b/src/bnetd/command.cpp
@@ -50,6 +50,7 @@
 #include "common/xstr.h"
 #include "common/trans.h"
 #include "common/lstr.h"
+#include "common/hashtable.h"
 
 #include "connection.h"
 #include "message.h"
@@ -333,6 +334,7 @@ namespace pvpgn
 		static int _handle_gameinfo_command(t_connection * c, char const * text);
 		static int _handle_ladderactivate_command(t_connection * c, char const * text);
 		static int _handle_rehash_command(t_connection * c, char const * text);
+		static int _handle_find_command(t_connection * c, char const *text);
 		static int _handle_save_command(t_connection * c, char const * text);
 
 		//static int _handle_rank_all_accounts_command(t_connection * c, char const * text);
@@ -445,6 +447,7 @@ namespace pvpgn
 			{ "/gameinfo", _handle_gameinfo_command },
 			{ "/ladderactivate", _handle_ladderactivate_command },
 			{ "/rehash", _handle_rehash_command },
+			{ "/find", _handle_find_command },
 			{ "/save", _handle_save_command },
 			//	{ "/rank_all_accounts"  , _handle_rank_all_accounts_command },
 			{ "/shutdown", _handle_shutdown_command },
@@ -3877,6 +3880,48 @@ namespace pvpgn
 			return 0;
 		}
 
+		/**
+		* /find <substr to search for inside username>
+		*/
+		static int _handle_find_command(t_connection * c, char const *text)
+		{
+			unsigned int  i = 0;
+			t_account *account;
+			char const *tname;
+			t_entry *curr;
+			t_hashtable *accountlist_head = accountlist();
+
+			text = skip_command(text);
+
+			if (text[0] == '\0') {
+				/* In need of a better description */
+				message_send_text(c, message_type_info, c, "Usage: /find <substring to search in acct name>");
+				message_send_text(c, message_type_info, c, "  <substring> has to be in lower case");
+				return -1;
+			}
+
+			std::sprintf(msgtemp, " -- name -- similar to %s", text);
+			message_send_text(c, message_type_info, c, msgtemp);
+
+
+			HASHTABLE_TRAVERSE(accountlist_head, curr)
+			{
+				if (!curr)
+				{
+					eventlog(eventlog_level_error, __FUNCTION__, "found NULL account in list");
+				}
+				else
+				{
+					account = (t_account *)entry_get_data(curr);
+					if ((tname = accountlist_find_vague_account(account, text)) != NULL) {
+						message_send_text(c, message_type_info, c, tname);
+						return 0;
+					}
+				}
+			}
+			return 0;
+		}
+
 		/**
 		* Save changes of accounts and clans from the cache to a storage
 		*/