MiscFunctions.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator 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 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "../common/debug.h"
  17. #include "../common/Log.h"
  18. #include "MiscFunctions.h"
  19. #include <string.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #ifndef WIN32
  23. #include <netinet/in.h>
  24. #include <sys/socket.h>
  25. #endif
  26. #include <iostream>
  27. #include <iomanip>
  28. #ifdef WIN32
  29. #include <io.h>
  30. #endif
  31. #include "../common/timer.h"
  32. #include "../common/seperator.h"
  33. #include "../common/packet_dump.h"
  34. #include <algorithm>
  35. using namespace std;
  36. #ifndef PATCHER
  37. extern map<int16, int16> EQOpcodeVersions;
  38. #endif
  39. #ifdef WIN32
  40. #include <WinSock2.h>
  41. #include <windows.h>
  42. #define snprintf _snprintf
  43. #define vsnprintf _vsnprintf
  44. #define strncasecmp _strnicmp
  45. #define strcasecmp _stricmp
  46. #else
  47. #include <stdlib.h>
  48. #include <ctype.h>
  49. #include <stdarg.h>
  50. #include <sys/types.h>
  51. #include <sys/time.h>
  52. #ifdef FREEBSD //Timothy Whitman - January 7, 2003
  53. #include <sys/socket.h>
  54. #include <netinet/in.h>
  55. #endif
  56. #include <sys/stat.h>
  57. #include <unistd.h>
  58. #include <netdb.h>
  59. #include <errno.h>
  60. #endif
  61. void CoutTimestamp(bool ms) {
  62. time_t rawtime;
  63. struct tm* gmt_t;
  64. time(&rawtime);
  65. gmt_t = gmtime(&rawtime);
  66. struct timeval read_time;
  67. gettimeofday(&read_time,0);
  68. cout << (gmt_t->tm_year + 1900) << "/" << setw(2) << setfill('0') << (gmt_t->tm_mon + 1) << "/" << setw(2) << setfill('0') << gmt_t->tm_mday << " " << setw(2) << setfill('0') << gmt_t->tm_hour << ":" << setw(2) << setfill('0') << gmt_t->tm_min << ":" << setw(2) << setfill('0') << gmt_t->tm_sec;
  69. if (ms)
  70. cout << "." << setw(3) << setfill('0') << (read_time.tv_usec / 1000);
  71. cout << " GMT";
  72. }
  73. // normal strncpy doesnt put a null term on copied strings, this one does
  74. // ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
  75. char* strn0cpy(char* dest, const char* source, int32 size) {
  76. if (!dest)
  77. return 0;
  78. if (size == 0 || source == 0) {
  79. dest[0] = 0;
  80. return dest;
  81. }
  82. strncpy(dest, source, size);
  83. dest[size - 1] = 0;
  84. return dest;
  85. }
  86. string loadInt32String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_32BitString* eq_string){
  87. buffer += *pos;
  88. int32 size = *(int32*)buffer;
  89. if((size + *pos + sizeof(int16)) > buffer_size){
  90. cout << "Error in loadInt32String: Corrupt packet.\n";
  91. return string("");
  92. }
  93. buffer += sizeof(int32);
  94. string ret((char*)buffer, 0, size);
  95. if(eq_string){
  96. eq_string->size = size;
  97. eq_string->data = ret;
  98. }
  99. *pos += (size + sizeof(int32));
  100. return ret;
  101. }
  102. string loadInt16String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_16BitString* eq_string){
  103. buffer += *pos;
  104. int16 size = *(int16*)buffer;
  105. if((size + *pos + sizeof(int16))> buffer_size){
  106. cout << "Error in loadInt16String: Corrupt packet.\n";
  107. return string("");
  108. }
  109. buffer += sizeof(int16);
  110. string ret((char*)buffer, 0, size);
  111. if(eq_string){
  112. eq_string->size = size;
  113. eq_string->data = ret;
  114. }
  115. *pos += (size + sizeof(int16));
  116. return ret;
  117. }
  118. string loadInt8String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_8BitString* eq_string){
  119. buffer += *pos;
  120. int8 size = *(int8*)buffer;
  121. if((size + *pos + sizeof(int16)) > buffer_size){
  122. cout << "Error in loadInt8String: Corrupt packet.\n";
  123. return string("");
  124. }
  125. buffer += sizeof(int8);
  126. string ret((char*)buffer, 0, size);
  127. if(eq_string){
  128. eq_string->size = size;
  129. eq_string->data = ret;
  130. }
  131. *pos += (size + sizeof(int8));
  132. return ret;
  133. }
  134. sint16 storeInt32String(uchar* buffer, int16 buffer_size, string in_str){
  135. sint16 string_size = in_str.length();
  136. if((string_size + sizeof(int32)) > buffer_size)
  137. return -1;
  138. memcpy(buffer, &string_size, sizeof(int32));
  139. buffer += sizeof(int32);
  140. memcpy(buffer, in_str.c_str(), string_size);
  141. buffer += string_size;
  142. return (buffer_size - (string_size + sizeof(int32)));
  143. }
  144. sint16 storeInt16String(uchar* buffer, int16 buffer_size, string in_str){
  145. sint16 string_size = in_str.length();
  146. if((string_size + sizeof(int16)) > buffer_size)
  147. return -1;
  148. memcpy(buffer, &string_size, sizeof(int16));
  149. buffer += sizeof(int16);
  150. memcpy(buffer, in_str.c_str(), string_size);
  151. buffer += string_size;
  152. return (buffer_size - (string_size + sizeof(int16)));
  153. }
  154. sint16 storeInt8String(uchar* buffer, int16 buffer_size, string in_str){
  155. sint16 string_size = in_str.length();
  156. if((string_size + sizeof(int8)) > buffer_size)
  157. return -1;
  158. memcpy(buffer, &string_size, sizeof(int8));
  159. buffer += sizeof(int8);
  160. memcpy(buffer, in_str.c_str(), string_size);
  161. buffer += string_size;
  162. return (buffer_size - (string_size + sizeof(int8)));
  163. }
  164. // String N w/null Copy Truncated?
  165. // return value =true if entire string(source) fit, false if it was truncated
  166. bool strn0cpyt(char* dest, const char* source, int32 size) {
  167. if (!dest)
  168. return 0;
  169. if (size == 0 || source == 0) {
  170. dest[0] = 0;
  171. return dest;
  172. }
  173. strncpy(dest, source, size);
  174. dest[size - 1] = 0;
  175. return (bool) (source[strlen(dest)] == 0);
  176. }
  177. int MakeAnyLenString(char** ret, const char* format, ...) {
  178. int buf_len = 128;
  179. int chars = -1;
  180. va_list argptr;
  181. va_start(argptr, format);
  182. while (chars == -1 || chars >= buf_len) {
  183. safe_delete_array(*ret);
  184. if (chars == -1)
  185. buf_len *= 2;
  186. else
  187. buf_len = chars + 1;
  188. *ret = new char[buf_len];
  189. chars = vsnprintf(*ret, buf_len, format, argptr);
  190. }
  191. va_end(argptr);
  192. return chars;
  193. }
  194. void MakeAnyLenString(string &ret, const char* format, ...) {
  195. va_list args;
  196. va_start( args, format );
  197. #ifdef WIN32
  198. char * buffer;
  199. int buf_len = _vscprintf( format, args ) + 1;
  200. buffer = new char[buf_len];
  201. vsprintf( buffer, format, args );
  202. #else
  203. char buffer[4000];
  204. vsnprintf(buffer, 4000, format, args);
  205. #endif
  206. va_end(args);
  207. ret = string(buffer);
  208. #ifdef WIN32
  209. safe_delete_array( buffer );
  210. #endif
  211. }
  212. sint32 filesize(FILE* fp) {
  213. #ifdef WIN32
  214. return _filelength(_fileno(fp));
  215. #else
  216. struct stat file_stat;
  217. fstat(fileno(fp), &file_stat);
  218. return (sint32) file_stat.st_size;
  219. #endif
  220. }
  221. int32 ResolveIP(const char* hostname, char* errbuf) {
  222. #ifdef WIN32
  223. static InitWinsock ws;
  224. #endif
  225. if (errbuf)
  226. errbuf[0] = 0;
  227. if (hostname == 0) {
  228. if (errbuf)
  229. snprintf(errbuf, ERRBUF_SIZE, "ResolveIP(): hostname == 0");
  230. return 0;
  231. }
  232. struct sockaddr_in server_sin;
  233. #ifdef WIN32
  234. PHOSTENT phostent = NULL;
  235. #else
  236. struct hostent *phostent = NULL;
  237. #endif
  238. server_sin.sin_family = AF_INET;
  239. if ((phostent = gethostbyname(hostname)) == NULL) {
  240. #ifdef WIN32
  241. if (errbuf)
  242. snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %i", WSAGetLastError());
  243. #else
  244. if (errbuf)
  245. snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %s", strerror(errno));
  246. #endif
  247. return 0;
  248. }
  249. #ifdef WIN32
  250. memcpy ((char FAR *)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
  251. #else
  252. memcpy ((char*)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
  253. #endif
  254. return server_sin.sin_addr.s_addr;
  255. }
  256. #ifdef WIN32
  257. InitWinsock::InitWinsock() {
  258. WORD version = MAKEWORD (1,1);
  259. WSADATA wsadata;
  260. WSAStartup (version, &wsadata);
  261. }
  262. InitWinsock::~InitWinsock() {
  263. WSACleanup();
  264. }
  265. #endif
  266. #ifndef WIN32
  267. const char * itoa(int value) {
  268. static char temp[_ITOA_BUFLEN];
  269. memset(temp, 0, _ITOA_BUFLEN);
  270. snprintf(temp, _ITOA_BUFLEN,"%d", value);
  271. return temp;
  272. }
  273. char * itoa(int value, char *result, int base) {
  274. char *ptr1, *ptr2;
  275. char c;
  276. int tmp_value;
  277. //need a valid base
  278. if (base < 2 || base > 36) {
  279. *result = '\0';
  280. return result;
  281. }
  282. ptr1 = ptr2 = result;
  283. do {
  284. tmp_value = value;
  285. value /= base;
  286. *ptr1++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
  287. }
  288. while (value > 0);
  289. //apply a negative sign if need be
  290. if (tmp_value < 0)
  291. *ptr1++ = '-';
  292. *ptr1-- = '\0';
  293. while (ptr2 < ptr1) {
  294. c = *ptr1;
  295. *ptr1-- = *ptr2;
  296. *ptr2++ = c;
  297. }
  298. return result;
  299. }
  300. #endif
  301. /*
  302. * solar: generate a random integer in the range low-high
  303. * this should be used instead of the rand()%limit method
  304. */
  305. int MakeRandomInt(int low, int high)
  306. {
  307. return (int)MakeRandomFloat((double)low, (double)high + 0.999);
  308. }
  309. int32 hextoi(char* num) {
  310. int len = strlen(num);
  311. if (len < 3)
  312. return 0;
  313. if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
  314. return 0;
  315. int32 ret = 0;
  316. int mul = 1;
  317. for (int i=len-1; i>=2; i--) {
  318. if (num[i] >= 'A' && num[i] <= 'F')
  319. ret += ((num[i] - 'A') + 10) * mul;
  320. else if (num[i] >= 'a' && num[i] <= 'f')
  321. ret += ((num[i] - 'a') + 10) * mul;
  322. else if (num[i] >= '0' && num[i] <= '9')
  323. ret += (num[i] - '0') * mul;
  324. else
  325. return 0;
  326. mul *= 16;
  327. }
  328. return ret;
  329. }
  330. int64 hextoi64(char* num) {
  331. int len = strlen(num);
  332. if (len < 3)
  333. return 0;
  334. if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
  335. return 0;
  336. int64 ret = 0;
  337. int mul = 1;
  338. for (int i=len-1; i>=2; i--) {
  339. if (num[i] >= 'A' && num[i] <= 'F')
  340. ret += ((num[i] - 'A') + 10) * mul;
  341. else if (num[i] >= 'a' && num[i] <= 'f')
  342. ret += ((num[i] - 'a') + 10) * mul;
  343. else if (num[i] >= '0' && num[i] <= '9')
  344. ret += (num[i] - '0') * mul;
  345. else
  346. return 0;
  347. mul *= 16;
  348. }
  349. return ret;
  350. }
  351. float MakeRandomFloat(float low, float high)
  352. {
  353. #ifdef _WIN32
  354. thread_local bool seeded = false;
  355. #else
  356. static bool seeded = false;
  357. #endif
  358. float diff = high - low;
  359. if(!diff) return low;
  360. if(diff < 0)
  361. diff = 0 - diff;
  362. if(!seeded)
  363. {
  364. srand(time(0) * (time(0) % (int)diff));
  365. seeded = true;
  366. }
  367. return (rand() / (float)RAND_MAX * diff + (low > high ? high : low));
  368. }
  369. int32 GenerateEQ2Color(float* r, float* g, float* b){
  370. int8 rgb[4] = {0};
  371. rgb[0] = (int8)((*r)*255);
  372. rgb[1] = (int8)((*b)*255);
  373. rgb[2] = (int8)((*g)*255);
  374. int32 color = 0;
  375. memcpy(&color, rgb, sizeof(int32));
  376. return color;
  377. }
  378. int32 GenerateEQ2Color(float* rgb[3]){
  379. return GenerateEQ2Color(rgb[0], rgb[1], rgb[2]);
  380. }
  381. int8 MakeInt8(float* input){
  382. float input2 = *input;
  383. if(input2 < 0)
  384. input2 *= -1;
  385. return (int8)(input2*255);
  386. }
  387. vector<string>* SplitString(string str, char delim){
  388. vector<string>* results = new vector<string>;
  389. int32 pos;
  390. while((pos = str.find_first_of(delim))!= str.npos){
  391. if(pos > 0){
  392. results->push_back(str.substr(0,pos));
  393. }
  394. if(str.length() > pos)
  395. str = str.substr(pos+1);
  396. else
  397. break;
  398. }
  399. if(str.length() > 0)
  400. results->push_back(str);
  401. return results;
  402. }
  403. bool Unpack(uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse){
  404. int32 srcLen = 0;
  405. memcpy(&srcLen, data, sizeof(int32));
  406. return Unpack(srcLen, data + 4, dst, dstLen, version, reverse);
  407. }
  408. bool Unpack(int32 srcLen, uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse) {
  409. // int32 srcLen = 0;
  410. // memcpy(&srcLen, data, sizeof(int32));
  411. // data+=4;
  412. if(reverse)
  413. Reverse(data, srcLen);
  414. int16 pos = 0;
  415. int16 real_pos = 0;
  416. while(srcLen && pos < dstLen) {
  417. if(srcLen >= 0 && !srcLen--)
  418. return false;
  419. int8 code = data[real_pos++];
  420. if(code >= 128) {
  421. for(int8 index=0; index<7; index++) {
  422. if(code & 1) {
  423. if(pos >= dstLen)
  424. return false;
  425. if(srcLen >= 0 && !srcLen--)
  426. return false;
  427. dst[pos++] = data[real_pos++];
  428. } else {
  429. if(pos < dstLen) dst[pos++] = 0;
  430. }
  431. code >>= 1;
  432. }
  433. } else {
  434. if(pos + code > dstLen)
  435. return false;
  436. memset(dst+pos, 0, code);
  437. pos+=code;
  438. }
  439. }
  440. return srcLen <= 0;
  441. }
  442. int32 Pack(uchar* data, uchar* src, int16 srcLen, int16 dstLen, int16 version) {
  443. int16 real_pos = 4;
  444. int32 pos = 0;
  445. int32 code = 0;
  446. int codePos = 0;
  447. int codeLen = 0;
  448. int8 zeroLen = 0;
  449. memset(data,0,dstLen);
  450. while(pos < srcLen) {
  451. if(src[pos] || codeLen) {
  452. if(!codeLen) {
  453. if(zeroLen > 5) {
  454. data[real_pos++] = zeroLen;
  455. zeroLen = 0;
  456. }
  457. else if(zeroLen >= 1 && zeroLen<=5){
  458. for(;zeroLen>0;zeroLen--)
  459. codeLen++;
  460. }
  461. codePos = real_pos;
  462. code = 0;
  463. data[real_pos++] = 0;
  464. }
  465. if(src[pos]) {
  466. data[real_pos++] = src[pos];
  467. code |= 0x80;
  468. }
  469. code >>= 1;
  470. codeLen++;
  471. if(codeLen == 7) {
  472. data[codePos] = int8(0x80 | code);
  473. codeLen = 0;
  474. }
  475. } else {
  476. if(zeroLen == 0x7F) {
  477. data[real_pos++] = zeroLen;
  478. zeroLen = 0;
  479. }
  480. zeroLen++;
  481. }
  482. pos++;
  483. }
  484. if(codeLen) {
  485. code >>= (7 - codeLen);
  486. data[codePos] = int8(0x80 | code);
  487. } else if(zeroLen) {
  488. data[real_pos++] = zeroLen;
  489. }
  490. Reverse(data + 4, real_pos - 4);
  491. int32 dataLen = real_pos - 4;
  492. memcpy(&data[0], &dataLen, sizeof(int32));
  493. return dataLen + 4;
  494. }
  495. void Reverse(uchar* input, int32 srcLen){
  496. int16 real_pos = 0;
  497. int16 orig_pos = 0;
  498. int8 reverse_count = 0;
  499. while(srcLen > 0 && srcLen < 0xFFFFFFFF){ // XXX it was >=0 before. but i think it was a bug
  500. int8 code = input[real_pos++];
  501. srcLen--;
  502. if(code >= 128) {
  503. for(int8 index=0; index<7; index++) {
  504. if(code & 1) {
  505. if(srcLen >= 0 && !srcLen--)
  506. return;
  507. real_pos++;
  508. reverse_count++;
  509. }
  510. code >>= 1;
  511. }
  512. }
  513. if(reverse_count > 0){
  514. int8 tmp_data[8] = {0};
  515. for(int8 i=0;i<reverse_count;i++){
  516. tmp_data[i] = input[orig_pos + reverse_count-i];
  517. }
  518. memcpy(input + orig_pos + 1, tmp_data, reverse_count);
  519. reverse_count = 0;
  520. }
  521. orig_pos = real_pos;
  522. }
  523. }
  524. void MovementDecode(uchar* dst, uchar* newval, uchar* orig, int16 len){
  525. int16 pos = len;
  526. while(pos--)
  527. dst[pos] = newval[pos] ^ orig[pos];
  528. }
  529. void Decode(uchar* dst, uchar* src, int16 len) {
  530. int16 pos = len;
  531. while(pos--)
  532. dst[pos] ^= src[pos];
  533. memcpy(src, dst, len);
  534. }
  535. void Encode(uchar* dst, uchar* src, int16 len) {
  536. uchar* data = new uchar[len];
  537. int16 pos = len;
  538. while(pos--)
  539. data[pos] = int8(src[pos] ^ dst[pos]);
  540. memcpy(src, dst, len);
  541. memcpy(dst, data, len);
  542. safe_delete_array(data);
  543. }
  544. void SetColor(EQ2_Color* color, long data){
  545. memcpy(color, &data, sizeof(EQ2_Color));
  546. }
  547. string ToUpper(string input){
  548. string ret = input;
  549. transform(input.begin(), input.end(), ret.begin(), ::toupper);
  550. return ret;
  551. }
  552. string ToLower(string input){
  553. string ret = input;
  554. transform(input.begin(), input.end(), ret.begin(), ::tolower);
  555. return ret;
  556. }
  557. int32 ParseIntValue(string input){
  558. int32 ret = 0xFFFFFFFF;
  559. try{
  560. if(input.length() > 0){
  561. ret = atoul(input.c_str());
  562. }
  563. }
  564. catch(...){}
  565. return ret;
  566. }
  567. map<string, string> TranslateBrokerRequest(string request){
  568. map<string, string> ret;
  569. string key;
  570. string value;
  571. int32 start_pos = 0;
  572. int32 end_pos = 0;
  573. int32 pos = request.find("=");
  574. bool str_val = false;
  575. while(pos < 0xFFFFFFFF){
  576. str_val = false;
  577. key = request.substr(start_pos, pos-start_pos);
  578. if(request.find("|", pos) == pos+1){
  579. pos++;
  580. end_pos = request.find("|", pos+1);
  581. str_val = true;
  582. }
  583. else
  584. end_pos = request.find(" ", pos);
  585. if(end_pos < 0xFFFFFFFF){
  586. value = request.substr(pos+1, end_pos-pos-1);
  587. start_pos = end_pos+1;
  588. if(str_val){
  589. start_pos++;
  590. ret[key] = ToLower(value);
  591. }
  592. else
  593. ret[key] = value;
  594. pos = request.find("=", start_pos);
  595. }
  596. else{
  597. value = request.substr(pos+1);
  598. if(str_val){
  599. start_pos++;
  600. ret[key] = ToLower(value);
  601. }
  602. else
  603. ret[key] = value;
  604. break;
  605. }
  606. }
  607. return ret;
  608. }
  609. int8 CheckOverLoadSize(int32 val){
  610. int8 ret = 1;
  611. if(val >= 0xFFFF) //int32
  612. ret = sizeof(int16) + sizeof(int32);
  613. else if(val >= 0xFF)
  614. ret = sizeof(int8) + sizeof(int16);
  615. return ret;
  616. }
  617. int8 DoOverLoad(int32 val, uchar* data){
  618. int8 ret = 1;
  619. if(val >= 0xFFFF){ //int32
  620. memset(data, 0xFF, sizeof(int16));
  621. memcpy(data + sizeof(int16), &val, sizeof(int32));
  622. ret = sizeof(int16) + sizeof(int32);
  623. }
  624. else if(val >= 0xFF){ //int16
  625. memset(data, 0xFF, sizeof(int8));
  626. memcpy(data + sizeof(int8), &val, sizeof(int16));
  627. ret = sizeof(int8) + sizeof(int16);
  628. }
  629. else
  630. memcpy(data, &val, sizeof(int8));
  631. return ret;
  632. }
  633. /* Treats contiguous spaces as one space. */
  634. int32 CountWordsInString(const char* text) {
  635. int32 words = 0;
  636. if (text && strlen(text) > 0) {
  637. bool on_word = false;
  638. for (int32 i = 0; i < strlen(text); i++) {
  639. char letter = text[i];
  640. if (on_word && !((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122)))
  641. on_word = false;
  642. else if (!on_word && ((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122))){
  643. on_word = true;
  644. words++;
  645. }
  646. }
  647. }
  648. return words;
  649. }
  650. bool IsNumber(const char *num) {
  651. size_t len, i;
  652. if (!num)
  653. return false;
  654. len = strlen(num);
  655. if (len == 0)
  656. return false;
  657. for (i = 0; i < len; i++) {
  658. if (!isdigit(num[i]))
  659. return false;
  660. }
  661. return true;
  662. }
  663. void PrintSep(Seperator *sep, const char *name) {
  664. #ifdef _DEBUG
  665. int32 i = 0;
  666. LogWrite(MISC__WARNING, 0, "Misc", "Printing sep %s", name ? name : "No Name");
  667. if (!sep)
  668. LogWrite(MISC__WARNING, 0, "Misc", "\tSep is null");
  669. else {
  670. while (sep->arg[i] && strlen(sep->arg[i]) > 0) {
  671. LogWrite(MISC__WARNING, 0, "Misc", "\t%i => %s", i, sep->arg[i]);
  672. i++;
  673. }
  674. }
  675. #endif
  676. }
  677. #define INI_IGNORE(c) (c == '\n' || c == '\r' || c == '#')
  678. static bool INIGoToSection(FILE *f, const char *section) {
  679. size_t size = strlen(section) + 3;
  680. char line[256], *buf, *tmp;
  681. bool found = false;
  682. if ((buf = (char *)malloc(size)) == NULL) {
  683. fprintf(stderr, "%s: %u: Unable to allocate %zu bytes\n", __FUNCTION__, __LINE__, size);
  684. return false;
  685. }
  686. sprintf(buf, "[%s]", section);
  687. while (fgets(line, sizeof(line), f) != NULL) {
  688. if (INI_IGNORE(line[0]))
  689. continue;
  690. if (line[0] == '[') {
  691. if ((tmp = strstr(line, "\n")) != NULL)
  692. *tmp = '\0';
  693. if ((tmp = strstr(line, "\r")) != NULL)
  694. *tmp = '\0';
  695. if (strcasecmp(buf, line) == 0) {
  696. found = true;
  697. break;
  698. }
  699. }
  700. }
  701. free(buf);
  702. return found;
  703. }
  704. static char * INIFindValue(FILE *f, const char *section, const char *property) {
  705. char line[256], *key, *val;
  706. if (section != NULL && !INIGoToSection(f, section))
  707. return NULL;
  708. while (fgets(line, sizeof(line), f) != NULL) {
  709. if (INI_IGNORE(line[0]))
  710. continue;
  711. if (section != NULL && line[0] == '[')
  712. return NULL;
  713. if ((key = strtok(line, "=")) == NULL)
  714. continue;
  715. if (strcasecmp(key, property) == 0) {
  716. val = strtok(NULL, "\n\r");
  717. if (val == NULL)
  718. return NULL;
  719. return strdup(val);
  720. }
  721. }
  722. return NULL;
  723. }
  724. bool INIReadInt(FILE *f, const char *section, const char *property, int *out) {
  725. char *value;
  726. rewind(f);
  727. if ((value = INIFindValue(f, section, property)) == NULL)
  728. return false;
  729. if (!IsNumber(value)) {
  730. free(value);
  731. return false;
  732. }
  733. *out = atoi(value);
  734. free(value);
  735. return true;
  736. }
  737. bool INIReadBool(FILE *f, const char *section, const char *property, bool *out) {
  738. char *value;
  739. rewind(f);
  740. if ((value = INIFindValue(f, section, property)) == NULL)
  741. return false;
  742. *out = (strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "on") == 0 || strcasecmp(value, "yes") == 0);
  743. free(value);
  744. return true;
  745. }
  746. int16 GetItemPacketType(int32 version) {
  747. int16 item_version;
  748. if (version >= 64707)
  749. item_version = 0x5CFE;
  750. else if (version >= 63119)
  751. item_version = 0x56FE;
  752. else if (version >= 60024)
  753. item_version = 0x51FE;
  754. else if (version >= 57107)
  755. item_version = 0x4CFE;
  756. else if (version >= 57048)
  757. item_version = 0x48FE;
  758. else if (version >= 1199)
  759. item_version = 0x44FE;
  760. else if (version >= 1195)
  761. item_version = 0x40FE;
  762. else if (version >= 1193)
  763. item_version = 0x3FFE;
  764. else if (version >= 1190)
  765. item_version = 0x3EFE;
  766. else if (version >= 1188)
  767. item_version = 0x3DFE;
  768. else if(version >= 1096)
  769. item_version = 0x35FE;
  770. else if(version >= 1027)
  771. item_version = 0x31FE;
  772. else if(version >= 1008)
  773. item_version = 0x2CFE;
  774. else if(version >= 927)
  775. item_version = 0x23FE;
  776. else if(version >= 893)
  777. item_version = 0x22FE;
  778. else if(version >= 860)
  779. item_version = 0x20FE;
  780. else
  781. item_version = 0x1CFE;
  782. return item_version;
  783. }
  784. #ifndef PATCHER
  785. int16 GetOpcodeVersion(int16 version) {
  786. int16 ret = version;
  787. int16 version1 = 0;
  788. int16 version2 = 0;
  789. map<int16, int16>::iterator itr;
  790. for (itr = EQOpcodeVersions.begin(); itr != EQOpcodeVersions.end(); itr++) {
  791. version1 = itr->first;
  792. version2 = itr->second;
  793. if (version >= version1 && version <= version2) {
  794. ret = version1;
  795. break;
  796. }
  797. }
  798. return ret;
  799. }
  800. #endif
  801. void SleepMS(int32 milliseconds) {
  802. #if defined(_WIN32)
  803. Sleep(milliseconds);
  804. #else
  805. usleep(milliseconds * 1000);
  806. #endif
  807. }
  808. size_t
  809. strlcpy(char *dst, const char *src, size_t size) {
  810. register char *d = dst;
  811. register const char *s = src;
  812. register size_t n = size;
  813. if (n != 0 && --n != 0) {
  814. do {
  815. if ((*d++ = *s++) == 0)
  816. break;
  817. } while (--n != 0);
  818. }
  819. if (n == 0) {
  820. if (size != 0)
  821. *d = '\0';
  822. while (*s++)
  823. ;
  824. }
  825. return(s - src - 1);
  826. }