Send KEY_END when (re)creating a text input
[oweals/minetest.git] / src / auth.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "auth.h"
21 #include <fstream>
22 #include <jmutexautolock.h>
23 //#include "main.h" // for g_settings
24 #include <sstream>
25 #include "strfnd.h"
26 #include "debug.h"
27
28 // Convert a privileges value into a human-readable string,
29 // with each component separated by a comma.
30 std::string privsToString(u64 privs)
31 {
32         std::ostringstream os(std::ios_base::binary);
33         if(privs & PRIV_BUILD)
34                 os<<"build,";
35         if(privs & PRIV_TELEPORT)
36                 os<<"teleport,";
37         if(privs & PRIV_SETTIME)
38                 os<<"settime,";
39         if(privs & PRIV_PRIVS)
40                 os<<"privs,";
41         if(privs & PRIV_SHOUT)
42                 os<<"shout,";
43         if(privs & PRIV_BAN)
44                 os<<"ban,";
45         if(os.tellp())
46         {
47                 // Drop the trailing comma. (Why on earth can't
48                 // you truncate a C++ stream anyway???)
49                 std::string tmp = os.str();
50                 return tmp.substr(0, tmp.length() -1);
51         }
52         return os.str();
53 }
54
55 // Converts a comma-seperated list of privilege values into a
56 // privileges value. The reverse of privsToString(). Returns
57 // PRIV_INVALID if there is anything wrong with the input.
58 u64 stringToPrivs(std::string str)
59 {
60         u64 privs=0;
61         Strfnd f(str);
62         while(f.atend() == false)
63         {
64                 std::string s = trim(f.next(","));
65                 if(s == "build")
66                         privs |= PRIV_BUILD;
67                 else if(s == "teleport")
68                         privs |= PRIV_TELEPORT;
69                 else if(s == "settime")
70                         privs |= PRIV_SETTIME;
71                 else if(s == "privs")
72                         privs |= PRIV_PRIVS;
73                 else if(s == "shout")
74                         privs |= PRIV_SHOUT;
75                 else if(s == "ban")
76                         privs |= PRIV_BAN;
77                 else
78                         return PRIV_INVALID;
79         }
80         return privs;
81 }
82
83 AuthManager::AuthManager(const std::string &authfilepath):
84                 m_authfilepath(authfilepath),
85                 m_modified(false)
86 {
87         m_mutex.Init();
88         
89         try{
90                 load();
91         }
92         catch(SerializationError &e)
93         {
94                 dstream<<"WARNING: AuthManager: creating "
95                                 <<m_authfilepath<<std::endl;
96         }
97 }
98
99 AuthManager::~AuthManager()
100 {
101         save();
102 }
103
104 void AuthManager::load()
105 {
106         JMutexAutoLock lock(m_mutex);
107         
108         dstream<<"AuthManager: loading from "<<m_authfilepath<<std::endl;
109         std::ifstream is(m_authfilepath.c_str(), std::ios::binary);
110         if(is.good() == false)
111         {
112                 dstream<<"AuthManager: failed loading from "<<m_authfilepath<<std::endl;
113                 throw SerializationError("AuthManager::load(): Couldn't open file");
114         }
115
116         for(;;)
117         {
118                 if(is.eof() || is.good() == false)
119                         break;
120
121                 // Read a line
122                 std::string line;
123                 std::getline(is, line, '\n');
124
125                 std::istringstream iss(line);
126                 
127                 // Read name
128                 std::string name;
129                 std::getline(iss, name, ':');
130
131                 // Read password
132                 std::string pwd;
133                 std::getline(iss, pwd, ':');
134
135                 // Read privileges
136                 std::string stringprivs;
137                 std::getline(iss, stringprivs, ':');
138                 u64 privs = stringToPrivs(stringprivs);
139                 
140                 // Store it
141                 AuthData ad;
142                 ad.pwd = pwd;
143                 ad.privs = privs;
144                 m_authdata[name] = ad;
145         }
146
147         m_modified = false;
148 }
149
150 void AuthManager::save()
151 {
152         JMutexAutoLock lock(m_mutex);
153         
154         dstream<<"AuthManager: saving to "<<m_authfilepath<<std::endl;
155         std::ofstream os(m_authfilepath.c_str(), std::ios::binary);
156         if(os.good() == false)
157         {
158                 dstream<<"AuthManager: failed saving to "<<m_authfilepath<<std::endl;
159                 throw SerializationError("AuthManager::save(): Couldn't open file");
160         }
161         
162         for(core::map<std::string, AuthData>::Iterator
163                         i = m_authdata.getIterator();
164                         i.atEnd()==false; i++)
165         {
166                 std::string name = i.getNode()->getKey();
167                 if(name == "")
168                         continue;
169                 AuthData ad = i.getNode()->getValue();
170                 os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
171         }
172
173         m_modified = false;
174 }
175
176 bool AuthManager::exists(const std::string &username)
177 {
178         JMutexAutoLock lock(m_mutex);
179         
180         core::map<std::string, AuthData>::Node *n;
181         n = m_authdata.find(username);
182         if(n == NULL)
183                 return false;
184         return true;
185 }
186
187 void AuthManager::set(const std::string &username, AuthData ad)
188 {
189         JMutexAutoLock lock(m_mutex);
190         
191         m_authdata[username] = ad;
192
193         m_modified = true;
194 }
195
196 void AuthManager::add(const std::string &username)
197 {
198         JMutexAutoLock lock(m_mutex);
199         
200         m_authdata[username] = AuthData();
201
202         m_modified = true;
203 }
204
205 std::string AuthManager::getPassword(const std::string &username)
206 {
207         JMutexAutoLock lock(m_mutex);
208         
209         core::map<std::string, AuthData>::Node *n;
210         n = m_authdata.find(username);
211         if(n == NULL)
212                 throw AuthNotFoundException("");
213         
214         return n->getValue().pwd;
215 }
216
217 void AuthManager::setPassword(const std::string &username,
218                 const std::string &password)
219 {
220         JMutexAutoLock lock(m_mutex);
221         
222         core::map<std::string, AuthData>::Node *n;
223         n = m_authdata.find(username);
224         if(n == NULL)
225                 throw AuthNotFoundException("");
226         
227         AuthData ad = n->getValue();
228         ad.pwd = password;
229         n->setValue(ad);
230
231         m_modified = true;
232 }
233
234 u64 AuthManager::getPrivs(const std::string &username)
235 {
236         JMutexAutoLock lock(m_mutex);
237         
238         core::map<std::string, AuthData>::Node *n;
239         n = m_authdata.find(username);
240         if(n == NULL)
241                 throw AuthNotFoundException("");
242         
243         return n->getValue().privs;
244 }
245
246 void AuthManager::setPrivs(const std::string &username, u64 privs)
247 {
248         JMutexAutoLock lock(m_mutex);
249         
250         core::map<std::string, AuthData>::Node *n;
251         n = m_authdata.find(username);
252         if(n == NULL)
253                 throw AuthNotFoundException("");
254         
255         AuthData ad = n->getValue();
256         ad.privs = privs;
257         n->setValue(ad);
258
259         m_modified = true;
260 }
261
262 bool AuthManager::isModified()
263 {
264         JMutexAutoLock lock(m_mutex);
265         return m_modified;
266 }
267
268