1 /* bzflag
2 * Copyright (c) 1993-2021 Tim Riker
3 *
4 * This package is free software; you can redistribute it and/or
5 * modify it under the terms of the license found in the file
6 * named COPYING that should have accompanied this file.
7 *
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <sstream>
16 #include "plugin_utils.h"
17
bzu_GetTeamName(bz_eTeamType team)18 const char* bzu_GetTeamName(bz_eTeamType team)
19 {
20 switch (team)
21 {
22
23 case eRedTeam:
24 return "Red";
25
26 case eGreenTeam:
27 return "Green";
28
29 case eBlueTeam:
30 return "Blue";
31
32 case ePurpleTeam:
33 return "Purple";
34
35 case eRogueTeam:
36 return "Rogue";
37
38 case eObservers:
39 return "Observer";
40
41 case eRabbitTeam:
42 return "Rabbit";
43
44 case eHunterTeam:
45 return "Hunter";
46
47 default:
48 break;
49 }
50
51 return "Unknown";
52 }
53
bzu_getTeamFromFlag(const char * flagCode)54 bz_eTeamType bzu_getTeamFromFlag(const char* flagCode)
55 {
56 if (!flagCode)
57 return eNoTeam;
58
59 if (strcmp(flagCode, "R*") == 0)
60 return eRedTeam;
61 else if (strcmp(flagCode, "G*") == 0)
62 return eGreenTeam;
63 else if (strcmp(flagCode, "B*") == 0)
64 return eBlueTeam;
65 else if (strcmp(flagCode, "P*") == 0)
66 return ePurpleTeam;
67
68 return eNoTeam;
69 }
70
printTime(bz_Time * ts,const char * _timezone)71 std::string printTime(bz_Time *ts, const char* _timezone)
72 {
73 std::string time;
74 appendTime(time,ts,_timezone);
75 return time;
76 }
77
78 //Date: Mon, 23 Jun 2008 17:50:22 GMT
79
appendTime(std::string & text,bz_Time * ts,const char * _timezone)80 void appendTime(std::string & text, bz_Time *ts, const char* _timezone)
81 {
82 switch (ts->dayofweek)
83 {
84 case 1:
85 text += "Mon";
86 break;
87 case 2:
88 text += "Tue";
89 break;
90 case 3:
91 text += "Wed";
92 break;
93 case 4:
94 text += "Thu";
95 break;
96 case 5:
97 text += "Fri";
98 break;
99 case 6:
100 text += "Sat";
101 break;
102 case 0:
103 text += "Sun";
104 break;
105 }
106
107 text += format(", %d ",ts->day);
108
109 switch (ts->month)
110 {
111 case 0:
112 text += "Jan";
113 break;
114 case 1:
115 text += "Feb";
116 break;
117 case 2:
118 text += "Mar";
119 break;
120 case 3:
121 text += "Apr";
122 break;
123 case 4:
124 text += "May";
125 break;
126 case 5:
127 text += "Jun";
128 break;
129 case 6:
130 text += "Jul";
131 break;
132 case 7:
133 text += "Aug";
134 break;
135 case 8:
136 text += "Sep";
137 break;
138 case 9:
139 text += "Oct";
140 break;
141 case 10:
142 text += "Nov";
143 break;
144 case 11:
145 text += "Dec";
146 break;
147 }
148
149 text += format(" %d %d:%d:%d ",ts->year,ts->hour,ts->minute,ts->second);
150 if (_timezone)
151 text += _timezone;
152 else
153 text += "GMT";
154 }
155
no_whitespace(const std::string & s)156 std::string no_whitespace(const std::string &s)
157 {
158 const int sourcesize = (int)s.size();
159
160 int count = 0, i = 0, j = 0;
161 for (i = 0; i < sourcesize; i++)
162 if (!isWhitespace(s[i]))
163 count++;
164
165 // create result string of correct size
166 std::string result(count, ' ');
167
168 for (i = 0, j = 0; i < sourcesize; i++)
169 if (!isWhitespace(s[i]))
170 result[j++] = s[i];
171
172 return result;
173 }
174
tolower(const std::string & s,std::string & dest)175 const std::string& tolower(const std::string& s, std::string& dest)
176 {
177 for (std::string::const_iterator i=s.begin(), end=s.end(); i!=end; ++i)
178 dest += ::tolower(*i);
179
180 return dest;
181 }
182
toupper(const std::string & s,std::string & dest)183 const std::string& toupper(const std::string& s, std::string& dest)
184 {
185 for (std::string::const_iterator i=s.begin(), end=s.end(); i!=end; ++i)
186 dest += ::toupper(*i);
187
188 return dest;
189 }
190
tolower(const char * s,std::string & dest)191 const std::string& tolower(const char* s, std::string& dest)
192 {
193 if (!s)
194 return dest;
195
196 for (size_t i =0,end = strlen(s); i < end; i++)
197 dest += ::tolower(s[i]);
198
199 return dest;
200 }
201
toupper(const char * s,std::string & dest)202 const std::string& toupper(const char* s, std::string& dest)
203 {
204 if (!s)
205 return dest;
206
207 for (size_t i =0,end = strlen(s); i < end; i++)
208 dest += ::toupper(s[i]);
209
210 return dest;
211 }
212
makelower(std::string & s)213 const std::string& makelower(std::string& s)
214 {
215 for (std::string::iterator i=s.begin(), end=s.end(); i!=end; ++i)
216 *i = ::tolower(*i);
217
218 return s;
219 }
220
makeupper(std::string & s)221 const std::string& makeupper(std::string& s)
222 {
223 for (std::string::iterator i=s.begin(), end=s.end(); i!=end; ++i)
224 *i = ::toupper(*i);
225
226 return s;
227 }
228
format(const char * fmt,...)229 std::string format(const char* fmt, ...)
230 {
231 va_list args;
232 va_start(args, fmt);
233 char temp[2048];
234 vsprintf(temp,fmt, args);
235 std::string result = temp;
236 va_end(args);
237 return result;
238 }
239
tokenize(const std::string & in,const std::string & delims,const int maxTokens,const bool useQuotes,size_t offset)240 std::vector<std::string> tokenize(const std::string& in, const std::string &delims,
241 const int maxTokens, const bool useQuotes, size_t offset)
242 {
243 std::vector<std::string> tokens;
244 int numTokens = 0;
245 bool inQuote = false;
246
247 std::ostringstream currentToken;
248
249 std::string::size_type pos = in.find_first_not_of(delims,offset);
250 int currentChar = (pos == std::string::npos) ? -1 : in[pos];
251 bool enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
252
253 while (pos != std::string::npos && !enoughTokens)
254 {
255
256 // get next token
257 bool tokenDone = false;
258 bool foundSlash = false;
259
260 currentChar = (pos < in.size()) ? in[pos] : -1;
261 while ((currentChar != -1) && !tokenDone)
262 {
263
264 tokenDone = false;
265
266 if (delims.find(currentChar) != std::string::npos && !inQuote) // currentChar is a delim
267 {
268 pos ++;
269 break; // breaks out of while loop
270 }
271
272 if (!useQuotes)
273 currentToken << char(currentChar);
274
275 else
276 {
277
278 switch (currentChar)
279 {
280 case '\\' : // found a backslash
281 if (foundSlash)
282 {
283 currentToken << char(currentChar);
284 foundSlash = false;
285 }
286 else
287 foundSlash = true;
288 break;
289 case '\"' : // found a quote
290 if (foundSlash) // found \"
291 {
292 currentToken << char(currentChar);
293 foundSlash = false;
294 }
295 else // found unescaped "
296 {
297 if (inQuote) // exiting a quote
298 {
299 // finish off current token
300 tokenDone = true;
301 inQuote = false;
302 //slurp off one additional delimeter if possible
303 if (pos+1 < in.size() &&
304 delims.find(in[pos+1]) != std::string::npos)
305 pos++;
306
307 }
308 else // entering a quote
309 {
310 // finish off current token
311 tokenDone = true;
312 inQuote = true;
313 }
314 }
315 break;
316 default:
317 if (foundSlash) // don't care about slashes except for above cases
318 {
319 currentToken << '\\';
320 foundSlash = false;
321 }
322 currentToken << char(currentChar);
323 break;
324 }
325 }
326
327 pos++;
328 currentChar = (pos < in.size()) ? in[pos] : -1;
329 } // end of getting a Token
330
331 if (currentToken.str().size() > 0) // if the token is something add to list
332 {
333 tokens.push_back(currentToken.str());
334 currentToken.str("");
335 numTokens ++;
336 }
337
338 enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
339 if (enoughTokens)
340 break;
341 else
342 pos = in.find_first_not_of(delims,pos);
343
344 } // end of getting all tokens -- either EOL or max tokens reached
345
346 if (enoughTokens && pos != std::string::npos)
347 {
348 std::string lastToken = in.substr(pos);
349 if (lastToken.size() > 0)
350 tokens.push_back(lastToken);
351 }
352
353 return tokens;
354 }
355
replace_all(const std::string & in,const std::string & replaceMe,const std::string & withMe)356 std::string replace_all(const std::string& in, const std::string& replaceMe, const std::string& withMe)
357 {
358 std::string::size_type beginPos = 0;
359 std::string::size_type endPos = 0;
360 std::ostringstream tempStream;
361
362 endPos = in.find(replaceMe);
363 if (endPos == std::string::npos)
364 return in; // can't find anything to replace
365 if (replaceMe.empty()) return in; // can't replace nothing with something -- can do reverse
366
367 while (endPos != std::string::npos)
368 {
369 // push the part up to
370 tempStream << in.substr(beginPos,endPos-beginPos);
371 tempStream << withMe;
372 beginPos = endPos + replaceMe.size();
373 endPos = in.find(replaceMe,beginPos);
374 }
375 tempStream << in.substr(beginPos);
376 return tempStream.str();
377 }
378
url_encode(const std::string & text)379 std::string url_encode(const std::string &text)
380 {
381 char hex[5];
382 std::string destination;
383 for (int i=0; i < (int) text.size(); i++)
384 {
385 char c = text[i];
386 if (isAlphanumeric(c))
387 destination+=c;
388
389 else if (isWhitespace(c))
390 destination+='+';
391
392 else
393 {
394 destination+='%';
395 sprintf(hex, "%-2.2X", c);
396 destination.append(hex);
397 }
398 }
399 return destination;
400 }
401
url_decode(const std::string & text)402 std::string url_decode(const std::string &text)
403 {
404 std::string destination;
405
406 std::string::const_iterator itr = text.begin();
407 while (itr != text.end())
408 {
409 if (*itr != '%' && *itr != '+')
410 destination += *itr++;
411 else if (*itr == '+')
412 {
413 destination += " ";
414 itr++;
415 }
416 else
417 {
418 char hex[5] = "0x00";
419
420 itr++;
421 if (itr == text.end())
422 return destination;
423
424 hex[2] = *itr;
425
426 itr++;
427 if (itr == text.end())
428 return destination;
429
430 hex[3] = *itr;
431
432 unsigned int val = 0;
433 sscanf(hex,"%x",&val);
434 if (val != 0)
435 destination += (char)val;
436 itr++;
437 }
438 }
439 return destination;
440 }
441
find_first_substr(const std::string & findin,const std::string findwhat,size_t offset)442 size_t find_first_substr(const std::string &findin, const std::string findwhat, size_t offset)
443 {
444 if (findwhat.size())
445 {
446 for (size_t f = offset; f < findin.size(); f++)
447 {
448 if (findin[f] == findwhat[0])
449 {
450 size_t start = f;
451 for (size_t w = 1; w < findwhat.size(); w++)
452 {
453 if (f+w > findin.size())
454 return std::string::npos;
455 if (findin[f+w] != findwhat[w])
456 {
457 f+=w;
458 w = findwhat.size();
459 }
460 }
461 if (start == f)
462 return f;
463 }
464 }
465 }
466 return std::string::npos;
467 }
468
getStringRange(const std::string & find,size_t start,size_t end)469 std::string getStringRange ( const std::string &find, size_t start, size_t end )
470 {
471 std::string ret;
472
473 if (end <= start || start > find.size() || end > find.size())
474 return ret;
475
476 for ( size_t p = start; p <= end; p++)
477 ret += find[p];
478
479 return ret;
480 }
481
482
trimLeadingWhitespace(std::string & text)483 void trimLeadingWhitespace(std::string &text)
484 {
485 for (size_t s = 0; s < text.size(); s++)
486 {
487 if (!isWhitespace(text[s]))
488 {
489 if (s)
490 text.erase(text.begin()+s-1);
491 return;
492 }
493 }
494 }
495
trimLeadingWhitespace(const std::string & text)496 std::string trimLeadingWhitespace(const std::string &text)
497 {
498 std::string s = text;
499 trimLeadingWhitespace(s);
500 return s;
501 }
502
503 std::vector<std::string> perms;
504
bzu_standardPerms(void)505 const std::vector<std::string> bzu_standardPerms (void)
506 {
507 if (perms.empty())
508 {
509 perms.push_back("actionMessage");
510 perms.push_back("adminMessageReceive");
511 perms.push_back("adminMessageSend");
512 perms.push_back("antiban");
513 perms.push_back("antikick");
514 perms.push_back("antikill");
515 perms.push_back("antipoll");
516 perms.push_back("antipollban");
517 perms.push_back("antipollkick");
518 perms.push_back("antipollkill");
519 perms.push_back("ban");
520 perms.push_back("banlist");
521 perms.push_back("countdown");
522 perms.push_back("date");
523 perms.push_back("endGame");
524 perms.push_back("flagHistory");
525 perms.push_back("flagMaster");
526 perms.push_back("flagMod");
527 perms.push_back("hideAdmin");
528 perms.push_back("idleStats");
529 perms.push_back("info");
530 perms.push_back("jitter_warn");
531 perms.push_back("kick");
532 perms.push_back("kill");
533 perms.push_back("lagStats");
534 perms.push_back("lagwarn");
535 perms.push_back("listPlugins");
536 perms.push_back("listPerms");
537 perms.push_back("masterBan");
538 perms.push_back("modCount");
539 perms.push_back("mute");
540 perms.push_back("packetlosswarn");
541 perms.push_back("playerList");
542 perms.push_back("plugins");
543 perms.push_back("poll");
544 perms.push_back("pollBan");
545 perms.push_back("pollKick");
546 perms.push_back("pollKill");
547 perms.push_back("pollSet");
548 perms.push_back("pollFlagReset");
549 perms.push_back("privateMessage");
550 perms.push_back("record");
551 perms.push_back("rejoin");
552 perms.push_back("removePerms");
553 perms.push_back("replay");
554 perms.push_back("report");
555 perms.push_back("say");
556 perms.push_back("sendHelp");
557 perms.push_back("setAll");
558 perms.push_back("setPerms");
559 perms.push_back("setVar");
560 perms.push_back("showAdmin");
561 perms.push_back("showMotto");
562 perms.push_back("showOthers");
563 perms.push_back("shortBan");
564 perms.push_back("shutdownServer");
565 perms.push_back("spawn");
566 perms.push_back("superKill");
567 perms.push_back("talk");
568 perms.push_back("unban");
569 perms.push_back("unmute");
570 perms.push_back("veto");
571 perms.push_back("viewReports");
572 perms.push_back("vote");
573 }
574 return perms;
575 }
576
577
578 // Local Variables: ***
579 // mode: C++ ***
580 // tab-width: 4 ***
581 // c-basic-offset: 4 ***
582 // indent-tabs-mode: nil ***
583 // End: ***
584 // ex: shiftwidth=4 tabstop=4
585