root/trunk/src/game/AccountMgr.cpp @ 22

Revision 22, 6.6 kB (checked in by yumileroy, 17 years ago)

[svn] * Updated character create query to use proper LEFT JOIN instead of NOT IN (SELECT...

Original author: Neo2003
Date: 2008-10-06 13:49:41-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
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.
8 *
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.
13 *
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
17 */
18
19#include "AccountMgr.h"
20#include "Database/DatabaseEnv.h"
21#include "ObjectMgr.h"
22#include "Player.h"
23#include "Policies/SingletonImp.h"
24#include "Util.h"
25
26#ifdef DO_POSTGRESQL
27extern DatabasePostgre loginDatabase;
28#else
29extern DatabaseMysql loginDatabase;
30#endif
31
32INSTANTIATE_SINGLETON_1(AccountMgr);
33
34AccountMgr::AccountMgr()
35{}
36
37AccountMgr::~AccountMgr()
38{}
39
40AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password)
41{
42    if(utf8length(username) > MAX_ACCOUNT_STR)
43        return AOR_NAME_TOO_LONG;                           // username's too long
44
45    normilizeString(username);
46    normilizeString(password);
47
48    loginDatabase.escape_string(username);
49    loginDatabase.escape_string(password);
50
51    QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
52    if(result)
53    {
54        delete result;
55        return AOR_NAME_ALREDY_EXIST;                       // username does already exist
56    }
57
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");
61
62    return AOR_OK;                                          // everything's fine
63}
64
65AccountOpResult AccountMgr::DeleteAccount(uint32 accid)
66{
67    QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
68    if(!result)
69        return AOR_NAME_NOT_EXIST;                          // account doesn't exist
70    delete result;
71
72    result = CharacterDatabase.PQuery("SELECT guid FROM characters WHERE account='%d'",accid);
73    if (result)
74    {
75        do
76        {
77            Field *fields = result->Fetch();
78            uint32 guidlo = fields[0].GetUInt32();
79            uint64 guid = MAKE_NEW_GUID(guidlo, 0, HIGHGUID_PLAYER);
80
81            // kick if player currently
82            if(Player* p = objmgr.GetPlayer(guid))
83            {
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
87            }
88
89            Player::DeleteFromDB(guid, accid, false);       // no need to update realm characters
90        } while (result->NextRow());
91
92        delete result;
93    }
94
95    // table realm specific but common for all characters of account for realm
96    CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid);
97
98    loginDatabase.BeginTransaction();
99
100    bool res = 
101        loginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) &&
102        loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid);
103
104    loginDatabase.CommitTransaction();
105
106    if(!res)
107        return AOR_DB_INTERNAL_ERROR;                       // unexpected error;
108
109    return AOR_OK;
110}
111
112AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd)
113{
114    QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
115    if(!result)
116        return AOR_NAME_NOT_EXIST;                          // account doesn't exist
117    delete result;
118
119    if(utf8length(new_uname) > MAX_ACCOUNT_STR)
120        return AOR_NAME_TOO_LONG;
121
122    if(utf8length(new_passwd) > MAX_ACCOUNT_STR)
123        return AOR_PASS_TOO_LONG;
124
125    normilizeString(new_uname);
126    normilizeString(new_passwd);
127
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
132
133    return AOR_OK;
134}
135
136AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
137{
138    QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
139    if(!result)
140        return AOR_NAME_NOT_EXIST;                          // account doesn't exist
141    delete result;
142
143    if (utf8length(new_passwd) > MAX_ACCOUNT_STR)
144        return AOR_PASS_TOO_LONG;
145
146    normilizeString(new_passwd);
147
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
151
152    return AOR_OK;
153}
154
155uint32 AccountMgr::GetId(std::string username)
156{
157    loginDatabase.escape_string(username);
158    QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str());
159    if(!result)
160        return 0;
161    else
162    {
163        uint32 id = (*result)[0].GetUInt32();
164        delete result;
165        return id;
166    }
167}
168
169bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
170{
171    normilizeString(passwd);
172    loginDatabase.escape_string(passwd);
173
174    QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str());
175    if (result)
176    {
177        delete result;
178        return true;
179    }
180
181    return false;
182}
183
184bool AccountMgr::normilizeString(std::string& utf8str)
185{
186    wchar_t wstr_buf[MAX_ACCOUNT_STR+1];
187
188    size_t wstr_len = MAX_ACCOUNT_STR;
189    if(!Utf8toWStr(utf8str,wstr_buf,wstr_len))
190        return false;
191
192    std::transform( &wstr_buf[0], wstr_buf+wstr_len, &wstr_buf[0], wcharToUpperOnlyLatin );
193
194    return WStrToUtf8(wstr_buf,wstr_len,utf8str);
195}
Note: See TracBrowser for help on using the browser.