2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "AccountMgr.h"
20 #include "Database/DatabaseEnv.h"
21 #include "ObjectAccessor.h"
23 #include "Policies/SingletonImp.h"
27 extern DatabasePostgre loginDatabase
;
29 extern DatabaseMysql loginDatabase
;
32 INSTANTIATE_SINGLETON_1(AccountMgr
);
34 AccountMgr::AccountMgr()
37 AccountMgr::~AccountMgr()
40 AccountOpResult
AccountMgr::CreateAccount(std::string username
, std::string password
)
42 if(utf8length(username
) > MAX_ACCOUNT_STR
)
43 return AOR_NAME_TOO_LONG
; // username's too long
45 normilizeString(username
);
46 normilizeString(password
);
48 loginDatabase
.escape_string(username
);
49 loginDatabase
.escape_string(password
);
51 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE username = '%s'", username
.c_str());
55 return AOR_NAME_ALREDY_EXIST
; // username does already exist
58 if(!loginDatabase
.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%s',':','%s')),NOW())", username
.c_str(), username
.c_str(), password
.c_str()))
59 return AOR_DB_INTERNAL_ERROR
; // unexpected error
60 loginDatabase
.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
62 return AOR_OK
; // everything's fine
65 AccountOpResult
AccountMgr::DeleteAccount(uint32 accid
)
67 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
69 return AOR_NAME_NOT_EXIST
; // account doesn't exist
72 result
= CharacterDatabase
.PQuery("SELECT guid FROM characters WHERE account='%d'",accid
);
77 Field
*fields
= result
->Fetch();
78 uint32 guidlo
= fields
[0].GetUInt32();
79 uint64 guid
= MAKE_NEW_GUID(guidlo
, 0, HIGHGUID_PLAYER
);
81 // kick if player currently
82 if(Player
* p
= ObjectAccessor::FindPlayer(guid
))
84 WorldSession
* s
= p
->GetSession();
85 s
->KickPlayer(); // mark session to remove at next session list update
86 s
->LogoutPlayer(false); // logout player without waiting next session list update
89 Player::DeleteFromDB(guid
, accid
, false); // no need to update realm characters
90 } while (result
->NextRow());
95 // table realm specific but common for all characters of account for realm
96 CharacterDatabase
.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid
);
98 loginDatabase
.BeginTransaction();
101 loginDatabase
.PExecute("DELETE FROM account WHERE id='%d'", accid
) &&
102 loginDatabase
.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid
);
104 loginDatabase
.CommitTransaction();
107 return AOR_DB_INTERNAL_ERROR
; // unexpected error;
112 AccountOpResult
AccountMgr::ChangeUsername(uint32 accid
, std::string new_uname
, std::string new_passwd
)
114 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
116 return AOR_NAME_NOT_EXIST
; // account doesn't exist
119 if(utf8length(new_uname
) > MAX_ACCOUNT_STR
)
120 return AOR_NAME_TOO_LONG
;
122 if(utf8length(new_passwd
) > MAX_ACCOUNT_STR
)
123 return AOR_PASS_TOO_LONG
;
125 normilizeString(new_uname
);
126 normilizeString(new_passwd
);
128 loginDatabase
.escape_string(new_uname
);
129 loginDatabase
.escape_string(new_passwd
);
130 if(!loginDatabase
.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname
.c_str(), new_uname
.c_str(), new_passwd
.c_str(), accid
))
131 return AOR_DB_INTERNAL_ERROR
; // unexpected error
136 AccountOpResult
AccountMgr::ChangePassword(uint32 accid
, std::string new_passwd
)
138 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
140 return AOR_NAME_NOT_EXIST
; // account doesn't exist
143 if (utf8length(new_passwd
) > MAX_ACCOUNT_STR
)
144 return AOR_PASS_TOO_LONG
;
146 normilizeString(new_passwd
);
148 loginDatabase
.escape_string(new_passwd
);
149 if(!loginDatabase
.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd
.c_str(), accid
))
150 return AOR_DB_INTERNAL_ERROR
; // unexpected error
155 uint32
AccountMgr::GetId(std::string username
)
157 loginDatabase
.escape_string(username
);
158 QueryResult
*result
= loginDatabase
.PQuery("SELECT id FROM account WHERE username = '%s'", username
.c_str());
163 uint32 id
= (*result
)[0].GetUInt32();
169 uint32
AccountMgr::GetSecurity(uint32 acc_id
)
171 QueryResult
*result
= loginDatabase
.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id
);
174 uint32 sec
= (*result
)[0].GetUInt32();
182 bool AccountMgr::GetName(uint32 acc_id
, std::string
&name
)
184 QueryResult
*result
= loginDatabase
.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id
);
187 name
= (*result
)[0].GetCppString();
195 bool AccountMgr::CheckPassword(uint32 accid
, std::string passwd
)
197 normilizeString(passwd
);
198 loginDatabase
.escape_string(passwd
);
200 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid
, passwd
.c_str());
210 bool AccountMgr::normilizeString(std::string
& utf8str
)
212 wchar_t wstr_buf
[MAX_ACCOUNT_STR
+1];
214 size_t wstr_len
= MAX_ACCOUNT_STR
;
215 if(!Utf8toWStr(utf8str
,wstr_buf
,wstr_len
))
218 std::transform( &wstr_buf
[0], wstr_buf
+wstr_len
, &wstr_buf
[0], wcharToUpperOnlyLatin
);
220 return WStrToUtf8(wstr_buf
,wstr_len
,utf8str
);