utility.h: Change Buffer's interface to be more compatible with SharedBuffer's interf...
[oweals/minetest.git] / src / servercommand.cpp
1 /*
2 Part of Minetest-c55
3 Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include "servercommand.h"
20 #include "utility.h"
21 #include "settings.h"
22
23 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
24
25 void cmd_status(std::wostringstream &os,
26         ServerCommandContext *ctx)
27 {
28         os<<ctx->server->getStatusString();
29 }
30
31 void cmd_me(std::wostringstream &os,
32         ServerCommandContext *ctx)
33 {
34         std::wstring name = narrow_to_wide(ctx->player->getName());
35         os << L"* " << name << L" " << ctx->paramstring;
36         ctx->flags |= SEND_TO_OTHERS | SEND_NO_PREFIX;
37 }
38
39 void cmd_privs(std::wostringstream &os,
40         ServerCommandContext *ctx)
41 {
42         if(ctx->parms.size() == 1)
43         {
44                 // Show our own real privs, without any adjustments
45                 // made for admin status
46                 os<<L"-!- " + narrow_to_wide(privsToString(
47                                 ctx->server->getPlayerAuthPrivs(ctx->player->getName())));
48                 return;
49         }
50
51         if((ctx->privs & PRIV_PRIVS) == 0)
52         {
53                 os<<L"-!- You don't have permission to do that";
54                 return;
55         }
56                 
57         Player *tp = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
58         if(tp == NULL)
59         {
60                 os<<L"-!- No such player";
61                 return;
62         }
63         
64         os<<L"-!- " + narrow_to_wide(privsToString(ctx->server->getPlayerAuthPrivs(tp->getName())));
65 }
66
67 void cmd_grantrevoke(std::wostringstream &os,
68         ServerCommandContext *ctx)
69 {
70         if(ctx->parms.size() != 3)
71         {
72                 os<<L"-!- Missing parameter";
73                 return;
74         }
75
76         if((ctx->privs & PRIV_PRIVS) == 0)
77         {
78                 os<<L"-!- You don't have permission to do that";
79                 return;
80         }
81
82         u64 newprivs = stringToPrivs(wide_to_narrow(ctx->parms[2]));
83         if(newprivs == PRIV_INVALID)
84         {
85                 os<<L"-!- Invalid privileges specified";
86                 return;
87         }
88
89         Player *tp = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
90         if(tp == NULL)
91         {
92                 os<<L"-!- No such player";
93                 return;
94         }
95         
96         std::string playername = wide_to_narrow(ctx->parms[1]);
97         u64 privs = ctx->server->getPlayerAuthPrivs(playername);
98
99         if(ctx->parms[0] == L"grant"){
100                 privs |= newprivs;
101                 actionstream<<ctx->player->getName()<<" grants "
102                                 <<wide_to_narrow(ctx->parms[2])<<" to "
103                                 <<playername<<std::endl;
104
105                 std::wstring msg;
106                 msg += narrow_to_wide(ctx->player->getName());
107                 msg += L" granted you the privilege \"";
108                 msg += ctx->parms[2];
109                 msg += L"\"";
110                 ctx->server->notifyPlayer(playername.c_str(), msg);
111         } else {
112                 privs &= ~newprivs;
113                 actionstream<<ctx->player->getName()<<" revokes "
114                                 <<wide_to_narrow(ctx->parms[2])<<" from "
115                                 <<playername<<std::endl;
116
117                 std::wstring msg;
118                 msg += narrow_to_wide(ctx->player->getName());
119                 msg += L" revoked from you the privilege \"";
120                 msg += ctx->parms[2];
121                 msg += L"\"";
122                 ctx->server->notifyPlayer(playername.c_str(), msg);
123         }
124         
125         ctx->server->setPlayerAuthPrivs(playername, privs);
126         
127         os<<L"-!- Privileges change to ";
128         os<<narrow_to_wide(privsToString(privs));
129 }
130
131 void cmd_time(std::wostringstream &os,
132         ServerCommandContext *ctx)
133 {
134         if(ctx->parms.size() != 2)
135         {
136                 os<<L"-!- Missing parameter";
137                 return;
138         }
139
140         if((ctx->privs & PRIV_SETTIME) ==0)
141         {
142                 os<<L"-!- You don't have permission to do that";
143                 return;
144         }
145
146         u32 time = stoi(wide_to_narrow(ctx->parms[1]));
147         ctx->server->setTimeOfDay(time);
148         os<<L"-!- time_of_day changed.";
149
150         actionstream<<ctx->player->getName()<<" sets time "
151                         <<time<<std::endl;
152 }
153
154 void cmd_shutdown(std::wostringstream &os,
155         ServerCommandContext *ctx)
156 {
157         if((ctx->privs & PRIV_SERVER) ==0)
158         {
159                 os<<L"-!- You don't have permission to do that";
160                 return;
161         }
162
163         actionstream<<ctx->player->getName()
164                         <<" shuts down server"<<std::endl;
165
166         ctx->server->requestShutdown();
167                                         
168         os<<L"*** Server shutting down (operator request)";
169         ctx->flags |= SEND_TO_OTHERS;
170 }
171
172 void cmd_setting(std::wostringstream &os,
173         ServerCommandContext *ctx)
174 {
175         if((ctx->privs & PRIV_SERVER) ==0)
176         {
177                 os<<L"-!- You don't have permission to do that";
178                 return;
179         }
180
181         /*std::string confline = wide_to_narrow(
182                         ctx->parms[1] + L" = " + ctx->params[2]);*/
183
184         std::string confline = wide_to_narrow(ctx->paramstring);
185         
186         actionstream<<ctx->player->getName()
187                         <<" sets: "<<confline<<std::endl;
188
189         g_settings->parseConfigLine(confline);
190         
191         ctx->server->saveConfig();
192
193         os<< L"-!- Setting changed and configuration saved.";
194 }
195
196 void cmd_teleport(std::wostringstream &os,
197         ServerCommandContext *ctx)
198 {
199         if((ctx->privs & PRIV_TELEPORT) ==0)
200         {
201                 os<<L"-!- You don't have permission to do that";
202                 return;
203         }
204
205         if(ctx->parms.size() != 2)
206         {
207                 os<<L"-!- Missing parameter";
208                 return;
209         }
210
211         std::vector<std::wstring> coords = str_split(ctx->parms[1], L',');
212         if(coords.size() != 3)
213         {
214                 os<<L"-!- You can only specify coordinates currently";
215                 return;
216         }
217
218         v3f dest(stoi(coords[0])*10, stoi(coords[1])*10, stoi(coords[2])*10);
219
220         actionstream<<ctx->player->getName()<<" teleports from "
221                         <<PP(ctx->player->getPosition()/BS)<<" to "
222                         <<PP(dest/BS)<<std::endl;
223
224         ctx->player->setPosition(dest);
225         ctx->server->SendMovePlayer(ctx->player);
226
227         os<< L"-!- Teleported.";
228 }
229
230 void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
231 {
232         if((ctx->privs & PRIV_BAN) == 0)
233         {
234                 os<<L"-!- You don't have permission to do that";
235                 return;
236         }
237
238         if(ctx->parms.size() < 2)
239         {
240                 std::string desc = ctx->server->getBanDescription("");
241                 os<<L"-!- Ban list: "<<narrow_to_wide(desc);
242                 return;
243         }
244         if(ctx->parms[0] == L"ban")
245         {
246                 Player *player = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
247
248                 if(player == NULL)
249                 {
250                         os<<L"-!- No such player";
251                         return;
252                 }
253                 
254                 try{
255                         Address address = ctx->server->getPeerAddress(player->peer_id);
256                         std::string ip_string = address.serializeString();
257                         ctx->server->setIpBanned(ip_string, player->getName());
258                         os<<L"-!- Banned "<<narrow_to_wide(ip_string)<<L"|"
259                                         <<narrow_to_wide(player->getName());
260
261                         actionstream<<ctx->player->getName()<<" bans "
262                                         <<player->getName()<<" / "<<ip_string<<std::endl;
263                 } catch(con::PeerNotFoundException){
264                         dstream<<__FUNCTION_NAME<<": peer was not found"<<std::endl;
265                 }
266         }
267         else
268         {
269                 std::string ip_or_name = wide_to_narrow(ctx->parms[1]);
270                 std::string desc = ctx->server->getBanDescription(ip_or_name);
271                 ctx->server->unsetIpBanned(ip_or_name);
272                 os<<L"-!- Unbanned "<<narrow_to_wide(desc);
273
274                 actionstream<<ctx->player->getName()<<" unbans "
275                                 <<ip_or_name<<std::endl;
276         }
277 }
278
279 void cmd_clearobjects(std::wostringstream &os,
280         ServerCommandContext *ctx)
281 {
282         if((ctx->privs & PRIV_SERVER) ==0)
283         {
284                 os<<L"-!- You don't have permission to do that";
285                 return;
286         }
287
288         actionstream<<ctx->player->getName()
289                         <<" clears all objects"<<std::endl;
290         
291         {
292                 std::wstring msg;
293                 msg += L"Clearing all objects. This may take long.";
294                 msg += L" You may experience a timeout. (by ";
295                 msg += narrow_to_wide(ctx->player->getName());
296                 msg += L")";
297                 ctx->server->notifyPlayers(msg);
298         }
299
300         ctx->env->clearAllObjects();
301                                         
302         actionstream<<"object clearing done"<<std::endl;
303         
304         os<<L"*** cleared all objects";
305         ctx->flags |= SEND_TO_OTHERS;
306 }
307
308
309 std::wstring processServerCommand(ServerCommandContext *ctx)
310 {
311
312         std::wostringstream os(std::ios_base::binary);
313         ctx->flags = SEND_TO_SENDER;    // Default, unless we change it.
314
315         u64 privs = ctx->privs;
316
317         if(ctx->parms.size() == 0 || ctx->parms[0] == L"help")
318         {
319                 os<<L"-!- Available commands: ";
320                 os<<L"status privs ";
321                 if(privs & PRIV_SERVER)
322                         os<<L"shutdown setting ";
323                 if(privs & PRIV_SETTIME)
324                         os<<L" time";
325                 if(privs & PRIV_TELEPORT)
326                         os<<L" teleport";
327                 if(privs & PRIV_PRIVS)
328                         os<<L" grant revoke";
329                 if(privs & PRIV_BAN)
330                         os<<L" ban unban";
331         }
332         else if(ctx->parms[0] == L"status")
333                 cmd_status(os, ctx);
334         else if(ctx->parms[0] == L"privs")
335                 cmd_privs(os, ctx);
336         else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
337                 cmd_grantrevoke(os, ctx);
338         else if(ctx->parms[0] == L"time")
339                 cmd_time(os, ctx);
340         else if(ctx->parms[0] == L"shutdown")
341                 cmd_shutdown(os, ctx);
342         else if(ctx->parms[0] == L"setting")
343                 cmd_setting(os, ctx);
344         else if(ctx->parms[0] == L"teleport")
345                 cmd_teleport(os, ctx);
346         else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
347                 cmd_banunban(os, ctx);
348         else if(ctx->parms[0] == L"me")
349                 cmd_me(os, ctx);
350         else if(ctx->parms[0] == L"clearobjects")
351                 cmd_clearobjects(os, ctx);
352         else
353                 os<<L"-!- Invalid command: " + ctx->parms[0];
354         
355         return os.str();
356 }
357
358