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