2 * Copyright (C) 2005-2009 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"
26 extern DatabaseType loginDatabase
;
28 INSTANTIATE_SINGLETON_1(AccountMgr
);
30 AccountMgr::AccountMgr()
33 AccountMgr::~AccountMgr()
36 AccountOpResult
AccountMgr::CreateAccount(std::string username
, std::string password
)
38 if(utf8length(username
) > MAX_ACCOUNT_STR
)
39 return AOR_NAME_TOO_LONG
; // username's too long
41 normilizeString(username
);
42 normilizeString(password
);
44 loginDatabase
.escape_string(username
);
45 loginDatabase
.escape_string(password
);
47 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE username = '%s'", username
.c_str());
51 return AOR_NAME_ALREDY_EXIST
; // username does already exist
54 if(!loginDatabase
.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1("_CONCAT3_("'%s'","':'","'%s'")"),NOW())", username
.c_str(), username
.c_str(), password
.c_str()))
55 return AOR_DB_INTERNAL_ERROR
; // unexpected error
56 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");
58 return AOR_OK
; // everything's fine
61 AccountOpResult
AccountMgr::DeleteAccount(uint32 accid
)
63 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
65 return AOR_NAME_NOT_EXIST
; // account doesn't exist
68 result
= CharacterDatabase
.PQuery("SELECT guid FROM characters WHERE account='%d'",accid
);
73 Field
*fields
= result
->Fetch();
74 uint32 guidlo
= fields
[0].GetUInt32();
75 uint64 guid
= MAKE_NEW_GUID(guidlo
, 0, HIGHGUID_PLAYER
);
77 // kick if player currently
78 if(Player
* p
= ObjectAccessor::FindPlayer(guid
))
80 WorldSession
* s
= p
->GetSession();
81 s
->KickPlayer(); // mark session to remove at next session list update
82 s
->LogoutPlayer(false); // logout player without waiting next session list update
85 Player::DeleteFromDB(guid
, accid
, false); // no need to update realm characters
86 } while (result
->NextRow());
91 // table realm specific but common for all characters of account for realm
92 CharacterDatabase
.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid
);
94 loginDatabase
.BeginTransaction();
97 loginDatabase
.PExecute("DELETE FROM account WHERE id='%d'", accid
) &&
98 loginDatabase
.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid
);
100 loginDatabase
.CommitTransaction();
103 return AOR_DB_INTERNAL_ERROR
; // unexpected error;
108 AccountOpResult
AccountMgr::ChangeUsername(uint32 accid
, std::string new_uname
, std::string new_passwd
)
110 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
112 return AOR_NAME_NOT_EXIST
; // account doesn't exist
115 if(utf8length(new_uname
) > MAX_ACCOUNT_STR
)
116 return AOR_NAME_TOO_LONG
;
118 if(utf8length(new_passwd
) > MAX_ACCOUNT_STR
)
119 return AOR_PASS_TOO_LONG
;
121 normilizeString(new_uname
);
122 normilizeString(new_passwd
);
124 loginDatabase
.escape_string(new_uname
);
125 loginDatabase
.escape_string(new_passwd
);
126 if(!loginDatabase
.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1("_CONCAT3_("'%s'","':'","'%s'")") WHERE id='%d'", new_uname
.c_str(), new_uname
.c_str(), new_passwd
.c_str(), accid
))
127 return AOR_DB_INTERNAL_ERROR
; // unexpected error
132 AccountOpResult
AccountMgr::ChangePassword(uint32 accid
, std::string new_passwd
)
134 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d'", accid
);
136 return AOR_NAME_NOT_EXIST
; // account doesn't exist
139 if (utf8length(new_passwd
) > MAX_ACCOUNT_STR
)
140 return AOR_PASS_TOO_LONG
;
142 normilizeString(new_passwd
);
144 loginDatabase
.escape_string(new_passwd
);
145 if(!loginDatabase
.PExecute("UPDATE account SET sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd
.c_str(), accid
))
146 return AOR_DB_INTERNAL_ERROR
; // unexpected error
151 uint32
AccountMgr::GetId(std::string username
)
153 loginDatabase
.escape_string(username
);
154 QueryResult
*result
= loginDatabase
.PQuery("SELECT id FROM account WHERE username = '%s'", username
.c_str());
159 uint32 id
= (*result
)[0].GetUInt32();
165 uint32
AccountMgr::GetSecurity(uint32 acc_id
)
167 QueryResult
*result
= loginDatabase
.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id
);
170 uint32 sec
= (*result
)[0].GetUInt32();
178 bool AccountMgr::GetName(uint32 acc_id
, std::string
&name
)
180 QueryResult
*result
= loginDatabase
.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id
);
183 name
= (*result
)[0].GetCppString();
191 bool AccountMgr::CheckPassword(uint32 accid
, std::string passwd
)
193 normilizeString(passwd
);
194 loginDatabase
.escape_string(passwd
);
196 QueryResult
*result
= loginDatabase
.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")")", accid
, passwd
.c_str());
206 bool AccountMgr::normilizeString(std::string
& utf8str
)
208 wchar_t wstr_buf
[MAX_ACCOUNT_STR
+1];
210 size_t wstr_len
= MAX_ACCOUNT_STR
;
211 if(!Utf8toWStr(utf8str
,wstr_buf
,wstr_len
))
214 std::transform( &wstr_buf
[0], wstr_buf
+wstr_len
, &wstr_buf
[0], wcharToUpperOnlyLatin
);
216 return WStrToUtf8(wstr_buf
,wstr_len
,utf8str
);