EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
util.cpp
Go to the documentation of this file.
1 /*
2  * Ascent MMORPG Server
3  * Copyright (C) 2005-2008 Ascent Team <http://www.ascentemu.com/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * 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 Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include "eve-common.h" // I don't want to include this here..
21 
22 using namespace std;
23 
25 {
26  float int_part = floorf(v);
27  float float_part = v - int_part;
28  if( float_part > 0.5f )
29  return float2int32(int_part + 1.0f);
30  else
31  return float2int32(int_part);
32 }
33 
35 {
36  double int_part = floor(v);
37  double float_part = v - int_part;
38  if( float_part > 0.5f )
39  return int32(int_part + 1.0f);
40  else
41  return int32(int_part);
42 }
43 
44 vector<string> StrSplit(const string &src, const string &sep)
45 {
46  vector<string> r;
47  string s;
48  for (string::const_iterator i = src.begin(); i != src.end(); i++) {
49  if (sep.find(*i) != string::npos) {
50  if (s.length()) r.push_back(s);
51  s = "";
52  } else {
53  s += *i;
54  }
55  }
56  if (s.length()) r.push_back(s);
57  return r;
58 }
59 
60 // for debug purposes... we can set the name of the thread.
61 #if 0
62 void SetThreadName(const char* format, ...)
63 {
64 #ifdef HAVE_WINDOWS_H
65  // This isn't supported on nix?
66  va_list ap;
67  va_start(ap, format);
68 
69  char thread_name[200];
70  vsnprintf(thread_name, 200, format, ap);
71 
72  THREADNAME_INFO info;
73  info.dwType = 0x1000;
74  info.dwThreadID = GetCurrentThreadId();
75  info.dwFlags = 0;
76  info.szName = thread_name;
77 
78  __try
79  {
80 #ifdef _WIN64
81  RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
82 #else /* !_WIN64 */
83  RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info);
84 #endif /* !_WIN64 */
85  }
86  __except(EXCEPTION_CONTINUE_EXECUTION)
87  {
88 
89  }
90 
91  va_end(ap);
92 #endif /* HAVE_WINDOWS_H */
93 }
94 #endif /* 0 */
95 
96 time_t convTimePeriod ( uint32 dLength, char dType )
97 {
98  time_t rawtime = 0;
99  if (dLength == 0)
100  return rawtime;
101  struct tm * ti = localtime( &rawtime );
102  switch(dType)
103  {
104  case 'h': // hours
105  ti->tm_hour += dLength;
106  break;
107  case 'd': // days
108  ti->tm_mday += dLength;
109  break;
110  case 'w': // weeks
111  ti->tm_mday += 7 * dLength;
112  break;
113  case 'm': // months
114  ti->tm_mon += dLength;
115  break;
116  case 'y': // years
117  // are leap years considered ? do we care ?
118  ti->tm_year += dLength;
119  break;
120  default: // minutes
121  ti->tm_min += dLength;
122  break;
123  }
124  return mktime(ti);
125 }
126 #if 0
127 int32 GetTimePeriodFromString(const char * str)
128 {
129  uint32 time_to_ban = 0;
130  char * p = (char*)str;
131  uint32 multiplier;
132  string number_temp;
133  uint32 multipliee;
134  number_temp.reserve(10);
135 
136  while(*p != 0)
137  {
138  // always starts with a number.
139  if(!isdigit(*p))
140  break;
141 
142  number_temp.clear();
143  while(isdigit(*p) && *p != 0)
144  {
145  number_temp += *p;
146  ++p;
147  }
148 
149  // try and find a letter
150  if(*p == 0)
151  break;
152 
153  // check the type
154  switch(tolower(*p))
155  {
156  case 'y':
157  multiplier = TIME_YEAR; // eek!
158  break;
159 
160  case 'm':
161  multiplier = TIME_MONTH;
162  break;
163 
164  case 'd':
165  multiplier = TIME_DAY;
166  break;
167 
168  case 'h':
169  multiplier = TIME_HOUR;
170  break;
171 
172  default:
173  return -1;
174  break;
175  }
176 
177  ++p;
178  multipliee = atoi(number_temp.c_str());
179  time_to_ban += (multiplier * multipliee);
180  }
181 
182  return time_to_ban;
183 }
184 #endif
185 
186 const char * szDayNames[7] = {
187  "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
188 };
189 
190 const char * szMonthNames[12] = {
191  "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
192 };
193 
194 void MakeIntString(char * buf, int num)
195 {
196  if(num<10) {
197  buf[0] = '0';
198  sprintf(&buf[1], "%u", num);
199  } else {
200  sprintf(buf,"%u",num);
201  }
202 }
203 
204 void MakeIntStringNoZero(char * buf, int num)
205 {
206  sprintf(buf,"%u",num);
207 }
208 
210 {
211  int seconds = (int)timestamp;
212  int mins=0;
213  int hours=0;
214  int days=0;
215  int months=0;
216  int years=0;
217  if(seconds >= 60)
218  {
219  mins = seconds / 60;
220  if(mins)
221  {
222  seconds -= mins*60;
223  if(mins >= 60)
224  {
225  hours = mins / 60;
226  if(hours)
227  {
228  mins -= hours*60;
229  if(hours >= 24)
230  {
231  days = hours/24;
232  if(days)
233  {
234  hours -= days*24;
235  if(days >= 30)
236  {
237  months = days / 30;
238  if(months)
239  {
240  days -= months*30;
241  if(months >= 12)
242  {
243  years = months / 12;
244  if(years)
245  {
246  months -= years*12;
247  }
248  }
249  }
250  }
251  }
252  }
253  }
254  }
255  }
256  }
257 
258  char szTempBuf[100];
259  string szResult;
260 
261  if(years) {
262  MakeIntStringNoZero(szTempBuf, years);
263  szResult += szTempBuf;
264  szResult += " years, ";
265  }
266 
267  if(months) {
268  MakeIntStringNoZero(szTempBuf, months);
269  szResult += szTempBuf;
270  szResult += " months, ";
271  }
272 
273  if(days) {
274  MakeIntStringNoZero(szTempBuf, days);
275  szResult += szTempBuf;
276  szResult += " days, ";
277  }
278 
279  if(hours) {
280  MakeIntStringNoZero(szTempBuf, hours);
281  szResult += szTempBuf;
282  szResult += " hours, ";
283  }
284 
285  if(mins) {
286  MakeIntStringNoZero(szTempBuf, mins);
287  szResult += szTempBuf;
288  szResult += " minutes, ";
289  }
290 
291  if(seconds) {
292  MakeIntStringNoZero(szTempBuf, seconds);
293  szResult += szTempBuf;
294  szResult += " seconds";
295  }
296 
297  return szResult;
298 }
299 
301 {
302  int seconds = (int)timestamp;
303  int mins=0;
304  int hours=0;
305  int days=0;
306  int months=0;
307  int years=0;
308  if(seconds >= 60)
309  {
310  mins = seconds / 60;
311  if(mins)
312  {
313  seconds -= mins*60;
314  if(mins >= 60)
315  {
316  hours = mins / 60;
317  if(hours)
318  {
319  mins -= hours*60;
320  if(hours >= 24)
321  {
322  days = hours/24;
323  if(days)
324  {
325  hours -= days*24;
326  if(days >= 30)
327  {
328  months = days / 30;
329  if(months)
330  {
331  days -= months*30;
332  if(months >= 12)
333  {
334  years = months / 12;
335  if(years)
336  {
337  months -= years*12;
338  }
339  }
340  }
341  }
342  }
343  }
344  }
345  }
346  }
347  }
348 
349  char szTempBuf[100];
350  string szResult;
351 
352  if(years) {
353  MakeIntStringNoZero(szTempBuf, years);
354  szResult += szTempBuf;
355  szResult += " yrs ";
356  }
357 
358  if(months) {
359  MakeIntStringNoZero(szTempBuf, months);
360  szResult += szTempBuf;
361  szResult += " months ";
362  }
363 
364  if(days) {
365  MakeIntStringNoZero(szTempBuf, days);
366  szResult += szTempBuf;
367  szResult += " days ";
368  }
369 
370  if(hours) {
371  MakeIntStringNoZero(szTempBuf, hours);
372  szResult += szTempBuf;
373  szResult += " hrs ";
374  }
375 
376  if(mins) {
377  MakeIntStringNoZero(szTempBuf, mins);
378  szResult += szTempBuf;
379  szResult += " mins ";
380  }
381 
382  if(seconds) {
383  MakeIntStringNoZero(szTempBuf, seconds);
384  szResult += szTempBuf;
385  szResult += " secs";
386  }
387 
388  return szResult;
389 }
390 
392 {
393  char szTempBuf[100];
394  time_t t = (time_t)timestamp;
395  tm * pTM = localtime(&t);
396 
397  string szResult;
398  szResult += szDayNames[pTM->tm_wday];
399  szResult += ", ";
400 
401  MakeIntString(szTempBuf, pTM->tm_mday);
402  szResult += szTempBuf;
403  szResult += " ";
404 
405  szResult += szMonthNames[pTM->tm_mon];
406  szResult += " ";
407 
408  MakeIntString(szTempBuf, pTM->tm_year+1900);
409  szResult += szTempBuf;
410  szResult += ", ";
411  MakeIntString(szTempBuf, pTM->tm_hour);
412  szResult += szTempBuf;
413  szResult += ":";
414  MakeIntString(szTempBuf, pTM->tm_min);
415  szResult += szTempBuf;
416  szResult += ":";
417  MakeIntString(szTempBuf, pTM->tm_sec);
418  szResult += szTempBuf;
419 
420  return szResult;
421 }
422 
423 // returns true if the ip hits the mask, otherwise false
424 bool ParseCIDRBan(unsigned int IP, unsigned int Mask, unsigned int MaskBits)
425 {
426  // CIDR bans are a compacted form of IP / Submask
427  // So 192.168.1.0/255.255.255.0 would be 192.168.1.0/24
428  // IP's in the 192.168l.1.x range would be hit, others not.
429  unsigned char * source_ip = (unsigned char*)&IP;
430  unsigned char * mask = (unsigned char*)&Mask;
431  int full_bytes = MaskBits / 8;
432  int leftover_bits = MaskBits % 8;
433  //int byte;
434 
435  // sanity checks for the data first
436  if( MaskBits > 32 )
437  {
438  return false;
439  }
440 
441  // this is the table for comparing leftover bits
442  static const unsigned char leftover_bits_compare[9] = {
443  0x00, // 00000000
444  0x80, // 10000000
445  0xC0, // 11000000
446  0xE0, // 11100000
447  0xF0, // 11110000
448  0xF8, // 11111000
449  0xFC, // 11111100
450  0xFE, // 11111110
451  0xFF, // 11111111 - This one isn't used
452  };
453 
454  // if we have any full bytes, compare them with memcpy
455  if( full_bytes > 0 )
456  {
457  if( memcmp( source_ip, mask, full_bytes ) != 0 )
458  {
459  return false;
460  }
461  }
462 
463  // compare the left over bits
464  if( leftover_bits > 0 )
465  {
466  if( ( source_ip[full_bytes] & leftover_bits_compare[leftover_bits] ) !=
467  ( mask[full_bytes] & leftover_bits_compare[leftover_bits] ) )
468  {
469  // one of the bits does not match
470  return false;
471  }
472  }
473 
474  // all of the bits match that were testable
475  return true;
476 }
477 
478 unsigned int MakeIP(const char * str)
479 {
480  unsigned int bytes[4];
481  unsigned int res;
482  if( sscanf(str, "%u.%u.%u.%u", &bytes[0], &bytes[1], &bytes[2], &bytes[3]) != 4 )
483  {
484  return 0;
485  }
486 
487  res = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
488  return res;
489 }
490 
491 int get_tokens(const char* szInput, char** pOutput, int iMaxCount, char cSeperator)
492 {
493  char* p;
494  char* q;
495  int count = 0;
496 
497  p = (char*)szInput;
498  q = p;
499 
500  for(;;)
501  {
502  // get some tokenz!
503  while(*p != '\0' && *p != cSeperator)
504  {
505  ++p;
506  }
507 
508  // add token
509  if( *p == 0 )
510  {
511  // end of string.
512  // do we have data?
513  if( p != q )
514  pOutput[count++] = q;
515 
516  // bai.
517  break;
518  }
519 
520  *p = 0;
521  ++p;
522 
523  // set output pointer
524  pOutput[count++] = q;
525 
526  // skip while bytes are the same as the seperator
527  while(*p == cSeperator)
528  ++p;
529 
530  // reset q pointer
531  q = p;
532 
533  // make sure we're not at EOL
534  if( *p == '\0' )
535  break;
536 
537  // make sure we don't overflow
538  if( count == iMaxCount )
539  break;
540  }
541 
542  return count;
543 }
544 
545 bool CheckIPs(const char* szIPList)
546 {
547 #ifdef HAVE_WINDOWS_H
548  char* ip_string = strdup(szIPList);
549 
550  char* tokens[30];
551  int count = get_tokens(ip_string, (char**)tokens, 30, ':');
552 
553  unsigned int ips[30];
554  int masks[30];
555  for(int i = 0; i < count; ++i)
556  {
557  char* t = strchr(tokens[i], '/');
558  if( t != NULL )
559  {
560  *t = 0;
561  masks[i] = atoi(t+1);
562  }
563  else
564  masks[i] = 32;
565 
566  ips[i] = inet_addr(tokens[i]);
567  }
568 
569  char computer_name[100] = {0};
570  DWORD computer_name_len = 100;
571  GetComputerNameA(computer_name, &computer_name_len);
572 
573  hostent* ent = gethostbyname(computer_name);
574  if( ent == NULL )
575  {
576  free(ip_string);
577  return false;
578  }
579 
580  for( int i = 0; ent->h_addr_list[i] != NULL; ++i )
581  {
582  bool pass = false;
583 
584  for( int j = 0; j < count; ++j )
585  {
586  if( ParseCIDRBan(*(unsigned int*)ent->h_addr_list[i], ips[j], masks[j]) )
587  {
588  pass = true;
589  break;
590  }
591  }
592 
593  if( !pass )
594  {
595  free(ip_string);
596  return false;
597  }
598  }
599 
600  free(ip_string);
601 #endif /* HAVE_WINDOWS_H */
602 
603  return true;
604 }
605 
606 /************************************************************************/
607 /* Start of OpenFrag borrowed code */
608 /************************************************************************/
609 namespace Utils
610 {
611 std::string Strings::trim(const std::string& str, bool left, bool right)
612 {
613  size_t lspaces, rspaces, len = str.length(), i;
614 
615  lspaces = rspaces = 0;
616 
617  if(left == true)
618  {
619  for(i = 0;
620  i < len && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
621  ++lspaces, ++i);
622  }
623 
624  if(right == true && lspaces < len)
625  {
626  for(i = len - 1;
627  i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
628  rspaces++, i--);
629  }
630 
631  return str.substr(lspaces, len-lspaces-rspaces);
632 }
633 
634 void Strings::trim(std::string& str, bool left, bool right)
635 {
636  size_t lspaces, rspaces, len = str.length(), i;
637 
638  lspaces = rspaces = 0;
639 
640  if(left == true)
641  {
642  for(i = 0;
643  i < len && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
644  ++lspaces, ++i);
645  }
646 
647  if(right == true && lspaces < len)
648  {
649  for(i = len - 1;
650  i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
651  rspaces++, i--);
652  }
653 
654  // TODO fit for improvement.
655  str = str.substr(lspaces, len-lspaces-rspaces);
656 }
657 
658 std::wstring Strings::trim(const std::wstring& str, bool left, bool right)
659 {
660  size_t lspaces, rspaces, len = str.length(), i;
661 
662  lspaces = rspaces = 0;
663 
664  if(left == true)
665  {
666  for(i = 0;
667  i < len && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
668  ++lspaces, ++i);
669  }
670 
671  if(right == true && lspaces < len)
672  {
673  for(i = len - 1;
674  i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
675  rspaces++, i--);
676  }
677 
678  return str.substr(lspaces, len-lspaces-rspaces);
679 }
680 
681 void Strings::trim(std::wstring& str, bool left, bool right)
682 {
683  size_t lspaces, rspaces, len = str.length(), i;
684 
685  lspaces = rspaces = 0;
686 
687  if(left == true)
688  {
689  for(i = 0;
690  i < len && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
691  ++lspaces, ++i);
692  }
693 
694  if(right == true && lspaces < len)
695  {
696  for(i = len - 1;
697  i >= 0 && (str[i] == ' ' || str[i] == '\t' || str[i] == '\r');
698  rspaces++, i--);
699  }
700 
701  // TODO fit for improvement.
702  str = str.substr(lspaces, len-lspaces-rspaces);
703 }
704 
705 std::string Strings::toUpperCase(const std::string& TString)
706 {
707  std::string retval(TString);
708  std::transform(retval.begin(), retval.end(), retval.begin(), static_cast<int(*)(int)>(::toupper));
709  return retval;
710 }
711 
712 void Strings::toUpperCase(std::string& TString)
713 {
714  std::transform(TString.begin(), TString.end(), TString.begin(), static_cast<int(*)(int)>(::toupper));
715 }
716 
717 std::wstring Strings::toUpperCase(const std::wstring& TString)
718 {
719  std::wstring retval(TString);
720  std::transform(retval.begin(), retval.end(), retval.begin(), static_cast<int(*)(int)>(::toupper));
721  return retval;
722 }
723 
724 void Strings::toUpperCase(std::wstring& TString)
725 {
726  std::transform(TString.begin(), TString.end(), TString.begin(), static_cast<int(*)(int)>(::toupper));
727 }
728 
729 std::string Strings::toLowerCase(const std::string& TString)
730 {
731  std::string retval(TString);
732  std::transform(retval.begin(), retval.end(), retval.begin(), static_cast<int(*)(int)>(::tolower));
733  return retval;
734 }
735 
736 void Strings::toLowerCase(std::string& TString)
737 {
738  std::transform(TString.begin(), TString.end(), TString.begin(), static_cast<int(*)(int)>(::tolower));
739 }
740 
741 std::wstring Strings::toLowerCase(const std::wstring& TString)
742 {
743  std::wstring retval(TString);
744  std::transform(retval.begin(), retval.end(), retval.begin(), static_cast<int(*)(int)>(::tolower));
745  return retval;
746 }
747 
748 void Strings::toLowerCase(std::wstring& TString)
749 {
750  std::transform(TString.begin(), TString.end(), TString.begin(), static_cast<int(*)(int)>(::tolower));
751 }
752 
753 /************************************************************************/
754 /* End of OpenFrag borrowed code */
755 /************************************************************************/
756 
757 std::string Strings::CaseFold( std::string & str )
758 {
759  std::string s2 = str;
762  if (s2 != str)
763  return CaseFold(s2);
764  return s2;
765 }
766 
767 std::wstring Strings::CaseFold( std::wstring & str )
768 {
769  std::wstring s2 = str;
772  if (s2 != str)
773  return CaseFold(s2);
774  return s2;
775 }
776 
777 std::wstring Strings::StringToWString( std::string & str )
778 {
779  /* convert from multi byte strings to wide character strings */
780  std::wstring wstr;
781  wstr.resize( str.size() );
782  size_t ret_len = mbstowcs( &wstr[0], str.c_str(), str.size() );
783 
784  if (ret_len != str.size()) {
785 
786  sLog.Error("Utils::Strings::StringToWString", "unable to convert std::string to std::wstring, wide character string");
787  }
788  return wstr;
789 }
790 
791 }//namespace Utils
#define vsnprintf
Definition: eve-compat.h:188
int get_tokens(const char *szInput, char **pOutput, int iMaxCount, char cSeperator)
Definition: util.cpp:491
int32 ascent_roundf(float v)
Definition: util.cpp:24
bool CheckIPs(const char *szIPList)
Definition: util.cpp:545
string ConvertTimeStampToString(uint32 timestamp)
Definition: util.cpp:209
const char * szMonthNames[12]
Definition: util.cpp:190
void MakeIntString(char *buf, int num)
Definition: util.cpp:194
static std::string toUpperCase(const std::string &TString)
Definition: util.cpp:705
STL namespace.
#define strdup
Definition: eve-compat.h:258
int32 GetTimePeriodFromString(const char *str)
void MakeIntStringNoZero(char *buf, int num)
Definition: util.cpp:204
std::string sprintf(const char *fmt,...)
sprintf for std::string.
Definition: eve-compat.cpp:106
int32 ascent_roundd(double v)
Definition: util.cpp:34
signed __int32 int32
Definition: eve-compat.h:49
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
string ConvertTimeStampToStringNC(uint32 timestamp)
Definition: util.cpp:300
static std::string toLowerCase(const std::string &TString)
Definition: util.cpp:729
unsigned int MakeIP(const char *str)
Definition: util.cpp:478
void SetThreadName(const char *format,...)
unsigned __int32 uint32
Definition: eve-compat.h:50
int32 float2int32(const float value)
Fastest Method of float2int32.
Definition: FastInt.h:42
Definition: util.cpp:609
time_t convTimePeriod(uint32 dLength, char dType)
Definition: util.cpp:96
string ConvertTimeStampToDataTime(uint32 timestamp)
Definition: util.cpp:391
bool ParseCIDRBan(unsigned int IP, unsigned int Mask, unsigned int MaskBits)
Definition: util.cpp:424
vector< string > StrSplit(const string &src, const string &sep)
Definition: util.cpp:44
const char * szDayNames[7]
Definition: util.cpp:186