]> git.stg.codes - stg.git/blob - stglibs/common.lib/common.cpp
Fix stglibs order in sgauth (for --as-needed)
[stg.git] / stglibs / common.lib / common.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25  /*
26  $Revision: 1.42 $
27  $Date: 2010/11/08 10:11:19 $
28  $Author: faust $
29  */
30
31 // For old and dub systems
32 // Like FreeBSD4
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36
37 #include <sys/select.h>
38
39 #ifdef WIN32
40 #include <winsock2.h>
41 #else
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <sys/select.h>
46 #endif
47
48 #include <iconv.h>
49
50 #include <cstdlib>
51 #include <cstdarg>
52 #include <cstdio>
53 #include <cstring>
54 #include <cerrno>
55 #include <cassert>
56
57 #include "stg/common.h"
58
59 #ifndef INET_ADDRSTRLEN
60 #   define INET_ADDRSTRLEN 16
61 #endif
62
63 using namespace std;
64
65 #ifdef WIN32
66 //-----------------------------------------------------------------------------
67 const char * inet_ntop(int af, const void * src, char * dst, unsigned long length)
68 {
69 struct sockaddr_in addr;
70 addr.sin_family = af;
71 addr.sin_port = 0;
72 memcpy(&addr.sin_addr.s_addr, src, sizeof(addr.sin_addr.s_addr));
73 if (WSAAddressToStringA(reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr), 0, dst, &length))
74     {
75     return NULL;
76     }
77 return dst;
78 }
79 //-----------------------------------------------------------------------------
80 int inet_pton(int af, const char * src, void * dst)
81 {
82 // Fuck you Microsoft!
83 // Why the hell not to use const char *?
84 size_t slen = strlen(src);
85 char * buf = new char[slen + 1];
86 strncpy(buf, src, slen + 1);
87 buf[slen] = 0;
88 struct sockaddr_in addr;
89 addr.sin_family = af;
90 addr.sin_port = 0;
91 addr.sin_addr.s_addr = 0;
92 int length = sizeof(addr);
93 if (WSAStringToAddressA(buf, af, 0, reinterpret_cast<struct sockaddr *>(&addr), &length))
94     {
95     delete[] buf;
96     return -1;
97     }
98 memcpy(dst, &addr, sizeof(addr));
99 delete[] buf;
100 return 1;
101 }
102 #endif
103 //-----------------------------------------------------------------------------
104 int strtodouble2(const char * s, double &a)
105 {
106 char *res;
107
108 a = strtod(s, &res);
109
110 if (*res != 0)
111     return EINVAL;
112
113 return 0;
114 }
115 //-----------------------------------------------------------------------------
116 #ifdef DEBUG
117 int printfd(const char * __file__, const char * fmt, ...)
118 #else
119 int printfd(const char *, const char *, ...)
120 #endif
121 {
122 #ifdef DEBUG
123 char buff[1024];
124
125 time_t t = time(NULL);
126
127 va_list vl;
128 va_start(vl, fmt);
129 vsnprintf(buff, sizeof(buff), fmt, vl);
130 va_end(vl);
131
132 printf("%18s > %s > ", __file__, LogDate(t)+11);
133 printf("%s", buff);
134
135 #endif
136 return 0;
137 }
138 //-----------------------------------------------------------------------------
139 int strprintf(string * str, const char * fmt, ...)
140 {
141 char buff[1024];
142
143 va_list vl;
144 va_start(vl, fmt);
145 int n = vsnprintf(buff, sizeof(buff), fmt, vl);
146 va_end(vl);
147 buff[1023] = 0;
148 *str = buff;
149
150 return n;
151 }
152 //-----------------------------------------------------------------------------
153 const char *IntToKMG(long long a, int stat)
154 {
155 static int64_t M = 1024*1024;
156 static int64_t G = 1024*1024*1024;
157 static char str[30];
158
159 switch (stat)
160     {
161     case ST_B:
162         #ifdef __WIN32__
163         sprintf(str, "%Ld", a);
164         #else
165         sprintf(str, "%lld", a);
166         #endif
167         break;
168     case ST_KB:
169         sprintf(str, "%.2f kb", double(a)/1024.0);
170         break;
171     case ST_MB:
172         sprintf(str, "%.2f Mb", double(a)/(1024.0*1024.0));
173         break;
174     default:
175         if (a > G)
176             {
177             sprintf(str, "%.2f Gb", double(a)/double(G));
178             return &str[0];
179             }
180         if (a < -G)
181             {
182             sprintf(str, "%.2f Gb", double(a)/double(G));
183             return &str[0];
184             }
185         if (a > M)
186             {
187             sprintf(str, "%.2f Mb", double(a)/double(M));
188             return &str[0];
189             }
190         if (a < -M)
191             {
192             sprintf(str, "%.2f Mb", double(a)/double(M));
193             return &str[0];
194             }
195
196         sprintf(str, "%.2f kb", double(a)/1024.0);
197         break;
198     }
199 return str;
200 }
201 //---------------------------------------------------------------------------
202 unsigned char koi2win[] = {
203         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
204         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
205         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
206         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
207         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
208         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
209         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
210         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
211         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
212         0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
213         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
214         0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
215         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
216         0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
217         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
218         0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
219         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
220         0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
221         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
222         0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
223         0xA0, 0xA1, 0xA2, 0xB8, 0xBA, 0xA5, 0xB3, 0xBF,
224         0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB4, 0xAE, 0xAF,
225         0xB0, 0xB1, 0xB2, 0xA8, 0xAA, 0xB5, 0xB2, 0xAF,
226         0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xA5, 0xBE, 0xBF,
227         0xFE, 0xE0, 0xE1, 0xF6, 0xE4, 0xE5, 0xF4, 0xE3,
228         0xF5, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
229         0xEF, 0xFF, 0xF0, 0xF1, 0xF2, 0xF3, 0xE6, 0xE2,
230         0xFC, 0xFB, 0xE7, 0xF8, 0xFD, 0xF9, 0xF7, 0xFA,
231         0xDE, 0xC0, 0xC1, 0xD6, 0xC4, 0xC5, 0xD4, 0xC3,
232         0xD5, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
233         0xCF, 0xDF, 0xD0, 0xD1, 0xD2, 0xD3, 0xC6, 0xC2,
234         0xDC, 0xDB, 0xC7, 0xD8, 0xDD, 0xD9, 0xD7, 0xDA};
235
236
237 unsigned char win2koi[] = {
238         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
239         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
240         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
241         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
242         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
243         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
244         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
245         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
246         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
247         0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
248         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
249         0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
250         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
251         0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
252         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
253         0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
254         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
255         0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
256         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
257         0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
258         0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xBD, 0xA6, 0xA7,
259         0xB3, 0xA9, 0xB4, 0xAB, 0xAC, 0xAD, 0xAE, 0xB7,
260         0xB0, 0xB1, 0xB6, 0xA6, 0xAD, 0xB5, 0xB6, 0xB7,
261         0xA3, 0xB9, 0xA4, 0xBB, 0xBC, 0xBD, 0xBE, 0xA7,
262         0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
263         0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
264         0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
265         0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
266         0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
267         0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
268         0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
269         0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1};
270 //---------------------------------------------------------------------------
271 void KOIToWin(const char * s1, char * s2, int l)
272 {
273 unsigned char t;
274 for (int j = 0; j < l; j++)
275     {
276     t = s1[j];
277     s2[j] = koi2win[t];
278
279     if (s1[j] == 0)
280         break;
281     }
282 }
283 //---------------------------------------------------------------------------
284 void WinToKOI(const char * s1, char * s2, int l)
285 {
286 unsigned char t;
287 for (int j = 0; j < l; j++)
288     {
289     t = s1[j];
290     s2[j] = win2koi[t];
291
292     if (s1[j] == 0)
293         break;
294     }
295 }
296 //---------------------------------------------------------------------------
297 void KOIToWin(const string & s1, string * s2)
298 {
299 s2->erase(s2->begin(), s2->end());
300 unsigned char t;
301 s2->reserve(s1.length());
302 for (int j = 0; j < (int)s1.length(); j++)
303     {
304     t = s1[j];
305     s2->push_back(koi2win[t]);
306     }
307 }
308 //---------------------------------------------------------------------------
309 void WinToKOI(const string & s1, string * s2)
310 {
311 s2->erase(s2->begin(), s2->end());
312 unsigned char t;
313 s2->reserve(s1.length());
314 for (int j = 0; j < (int)s1.length(); j++)
315     {
316     t = s1[j];
317     s2->push_back(win2koi[t]);
318     }
319 }
320 //---------------------------------------------------------------------------
321 void Encode12str(string & dst, const string & src)
322 {
323 dst.erase(dst.begin(), dst.end());
324 for (size_t i = 0; i < src.length(); i++)
325     {
326     dst.push_back('a' + (src[i] & 0x0f));
327     dst.push_back('a' + ((src[i] & 0xf0) >> 4));
328     }
329 }
330 //---------------------------------------------------------------------------
331 void Decode21str(std::string & dst, const std::string & src)
332 {
333 dst.erase(dst.begin(), dst.end());
334 for (size_t i = 0; i < src.length() / 2; i++)
335     {
336     char c1 = src[i * 2];
337     char c2 = src[i * 2 + 1];
338
339     c1 -= 'a';
340     c2 -= 'a';
341
342     dst.push_back(c1 + (c2 << 4));
343     }
344 }
345 //---------------------------------------------------------------------------
346 void Encode12(char * dst, const char * src, size_t srcLen)
347 {
348 for (size_t i = 0; i <= srcLen; i++)
349     {
350     char c1 = src[i] & 0x0f;
351     char c2 = (src[i] & 0xf0) >> 4;
352
353     c1 += 'a';
354     c2 += 'a';
355
356     dst[i * 2] = c1;
357     dst[i * 2 + 1] = c2;
358     }
359 dst[srcLen * 2] = 0;
360 }
361 //---------------------------------------------------------------------------
362 void Decode21(char * dst, const char * src)
363 {
364 for (size_t i = 0; ; i++)
365     {
366     if (src[i * 2] == 0)
367         break;
368
369     char c1 = src[i * 2];
370     char c2 = src[i * 2 + 1];
371
372     c1 -= 'a';
373     c2 -= 'a';
374
375     dst[i] = c1 + (c2 << 4);
376     }
377 dst[strlen(src) / 2] = 0;
378 }
379 //---------------------------------------------------------------------------
380 int ParseIPString(const char * str, uint32_t * ips, int maxIP)
381 {
382 /*
383  *Function Name:ParseIPString
384  *
385  *Parameters:
386  ÓÔÒÏËÁ ÄÌÑ ÒÁÚÂÏÒÁ É ÍÁÓÓÉ× ËÕÄÁ ÚÁÎÏÓÉÔØ ÐÏÌÕÞÅÎÎÙÅ ÁÄÒÅÓÁ
387  *
388  *Description:
389  îÁ ×ÈÏÄÅ ÄÏÌÖÎÁ ÂÙÔØ ÓÔÒÏËÁ ×ÉÄÁ "ip1,ip2,ip3" ÉÌÉ "*"
390  ÷ ÐÅÒ×ÏÍ ÓÌÕÞÁÅ × ÍÁÓÓÉ× ÚÁÎÏÓÑÔÓÑ ÒÁÚÏÂÒÁÎÎÙÅ ÁÄÒÅÓÁ.
391  åÓÌÉ ÉÈ ÍÅÎØÛÅ MAX_IP?, ÔÏ ÐÏÓÌÅÄÎÉÊ ÁÄÒÅÓ ÂÕÄÅÔ 255.255.255.255
392  åÓÌÉ ÓÔÒÏËÁ * , ÔÏ ÐÅÒ×ÁÙÊ ÁÄÒÅÓ ÂÕÄÅÔ 0.0.0.0, Ô.Å. ÌÀÂÏÊ
393  *
394  *Returns: 0 ÅÓÌÉ ×ÓÅ ïë
395  *
396  */
397
398 char p[255];
399 char * p1, *pp;
400 int n = 0;
401
402 strncpy(p, str, 254);
403 pp = p;
404
405 memset(ips, 0xFF, sizeof(unsigned long) * maxIP);
406
407 if (str[0] == '*' && strlen(str) == 1)
408     {
409     ips[0] = 0;
410     return 0;
411     }
412
413 for (int i = 0; i < maxIP; i++)
414     {
415     p1 = strtok(pp, ",\n ");
416     pp = NULL;
417
418     if (p1 == NULL && n == 0)// ÕËÁÚÁÔÅÌØ ÎÕÌØ É ÐÒÏÞÉÔÁÎÏ ÁÄÒÅÓÏ× ÔÏÖÅ ÎÏÌØ
419         {
420         return EINVAL;
421         }
422
423     if (p1 == NULL && n)
424         {
425         return 0;
426         }
427
428     struct in_addr in;
429     if (inet_pton(AF_INET, p1, &in) != 1)
430         {
431         //printf("INADDR_NONE\n");
432         return EINVAL;
433         }
434
435     ips[n] = in.s_addr;
436
437     /*if (ips[n] == INADDR_NONE)
438         return EINVAL;*/
439
440     n++;
441
442     if (n >= maxIP)
443         return 0;
444
445     }
446
447 return 0;
448 }
449 //-----------------------------------------------------------------------------
450 int DaysInCurrentMonth()
451 {
452 time_t t = time(NULL);
453
454 struct tm * lt = localtime(&t);
455
456 return DaysInMonth(lt->tm_year, lt->tm_mon);
457 }
458 //-----------------------------------------------------------------------------
459 int DaysInMonth(unsigned year, unsigned mon)
460 {
461 assert(mon < 12 && "Month number should be 0 - 11");
462 switch (mon)
463     {
464     case 0: return 31;  //jan
465     case 1:
466         if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
467             return 29;
468         return 28;      //feb
469     case 2: return 31;  //mar
470     case 3: return 30;  //apr
471     case 4: return 31;  //may
472     case 5: return 30;  //june
473     case 6: return 31;  //jule
474     case 7: return 31;  //aug
475     case 8: return 30;  //sep
476     case 9: return 31;  //oct
477     case 10: return 30; //nov
478     case 11: return 31; //dec
479     }
480 return -1; // We will never reach here
481 }
482 //-----------------------------------------------------------------------------
483 int Min8(int a)
484 {
485 /*
486 æÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ ÎÁÉÍÅÎØÛÅÅ ÞÉÓÌÏ ËÒÁÔÎÏÅ 8-ÍÉ ÂÏÌØÛÅÅ ÉÌÉ ÒÁ×ÎÏÅ ÚÁÄÁÎÎÏÍÕ
487  * */
488 if (a % 8 == 0)
489     return a;
490
491 return a + (8 - a % 8);
492 }
493 //-----------------------------------------------------------------------------
494 /*char * inet_ntostr(unsigned long ip)
495 {
496 struct in_addr addr = {ip};
497 return inet_ntoa(addr);
498 }*/
499 //-----------------------------------------------------------------------------
500 std::string inet_ntostring(uint32_t ip)
501 {
502     char buf[INET_ADDRSTRLEN + 1];
503     return inet_ntop(AF_INET, &ip, buf, INET_ADDRSTRLEN);
504 }
505 //-----------------------------------------------------------------------------
506 uint32_t inet_strington(const std::string & value)
507 {
508     uint32_t result;
509
510     if (inet_pton(AF_INET, value.c_str(), &result) <= 0)
511         return 0;
512
513     return result;
514 }
515 //-----------------------------------------------------------------------------
516 int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2)
517 {
518 char hs1[10], ms1[10], hs2[10], ms2[10];
519 char s1[25], s2[25];
520 char ss[49];
521 char *p1, *p2;
522
523 strncpy(ss, str, 48);
524
525 p1 = strtok(ss, "-");
526 if (!p1)
527     return -1;
528
529 strncpy(s1, p1, 24);
530
531 p2 = strtok(NULL, "-");
532 if (!p2)
533     return -1;
534
535 strncpy(s2, p2, 24);
536
537 p1 = strtok(s1, ":");
538 if (!p1)
539     return -1;
540
541 strncpy(hs1, p1, 9);
542
543 p2 = strtok(NULL, ":");
544 if (!p2)
545     return -1;
546
547 strncpy(ms1, p2, 9);
548
549 p1 = strtok(s2, ":");
550 if (!p1)
551     return -1;
552
553 strncpy(hs2, p1, 9);
554
555 p2 = strtok(NULL, ":");
556 if (!p2)
557     return -1;
558
559 strncpy(ms2, p2, 9);
560
561 if (str2x(hs1, h1) != 0)
562     return -1;
563
564 if (str2x(ms1, m1) != 0)
565     return -1;
566
567 if (str2x(hs2, h2) != 0)
568     return -1;
569
570 if (str2x(ms2, m2) != 0)
571     return -1;
572
573 return 0;
574 }
575 /*//---------------------------------------------------------------------------
576 bool IsDigit(char c)
577 {
578 if (c >= '0' && c <= '9')
579     return true;
580 return false;
581 }
582 //-----------------------------------------------------------------------------
583 bool IsAlpha(char c)
584 {
585 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
586     return true;
587 return false;
588 }*/
589 //-----------------------------------------------------------------------------
590 const char * LogDate(time_t t)
591 {
592 static char s[32];
593 struct tm * tt = localtime(&t);
594
595 snprintf(s, 20, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
596          tt->tm_year + 1900,
597          tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1,
598          tt->tm_mday    < 10 ? "0" : "", tt->tm_mday,
599          tt->tm_hour    < 10 ? "0" : "", tt->tm_hour,
600          tt->tm_min     < 10 ? "0" : "", tt->tm_min,
601          tt->tm_sec     < 10 ? "0" : "", tt->tm_sec);
602
603 return s;
604 }
605 //-----------------------------------------------------------------------------
606 uint32_t CalcMask(uint32_t msk)
607 {
608 if (msk >= 32) return 0xFFffFFff;
609 if (msk == 0) return 0;
610 return htonl(0xFFffFFff << (32 - msk));
611 }
612 //---------------------------------------------------------------------------
613 void TouchFile(const string & fileName)
614 {
615 FILE * f = fopen(fileName.c_str(), "w");
616 if (f)
617     fclose(f);
618 }
619 //---------------------------------------------------------------------------
620 #ifdef WIN32
621 void EncodeStr(char * str, unsigned long serial, int useHDD)
622 {
623 int len = strlen(str);
624 char stren[100];
625 int i, j = 0;
626 char c1, c2;
627 char serial_c[sizeof(serial)];
628 memcpy(serial_c, &serial, sizeof(serial));
629
630 for (i = 0; i < len; i++)
631     {
632     if (!useHDD)
633         str[i] = str[i]^49;
634     else
635         {
636         str[i] = str[i]^serial_c[j%sizeof(serial)];
637         j++;
638         }
639     }
640
641 for (i = 0; i < 2*len; i++)
642     {
643     if (i%2)
644         {
645         c1 = (str[i/2] >> 4);
646         c1 = c1 + 50;
647         stren[i] = c1;
648         }
649     else
650         {
651         c2 = (str[i/2] & 0x0f);
652         c2 += 50;
653         stren[i] = c2;
654         }
655     }
656 stren[i] = 0;
657 strcpy(str, stren);
658 }
659 //---------------------------------------------------------------------------
660 void DecodeStr(char * str, unsigned long serial, int useHDD)
661 {
662 int len = strlen(str);
663 char strdc[100];
664 int i, j = 0;
665 char c1, c2;
666 char serial_c[sizeof(serial)];
667 memcpy(serial_c, &serial, sizeof(serial));
668
669 for (i = 0; i < len; i += 2)
670     {
671     c1 = (str[i] - 50);
672     c2 = (str[i+1] - 50)<<4;
673     strdc[i/2] = c1+c2;
674     }
675 for (i = 0; i < len/2; i++)
676     {
677     if (!useHDD)
678         strdc[i] = strdc[i]^49;
679     else
680         {
681         strdc[i] = strdc[i]^serial_c[j%sizeof(serial)];
682         j++;
683         }
684     }
685 strdc[i] = 0;
686 strcpy(str, strdc);
687 }
688 //---------------------------------------------------------------------------
689 #endif //WIN32
690 void SwapBytes(uint16_t & value)
691 {
692     value = (value >> 8) |
693             (value << 8);
694 }
695 //---------------------------------------------------------------------------
696 void SwapBytes(uint32_t & value)
697 {
698     value = (value >> 24) |
699             ((value << 8) &  0x00FF0000L)|
700             ((value >> 8) &  0x0000FF00L)|
701             (value << 24);
702 }
703 //---------------------------------------------------------------------------
704 void SwapBytes(uint64_t & value)
705 {
706     value = (value >> 56) |
707             ((value << 40) & 0x00FF000000000000LL) |
708             ((value << 24) & 0x0000FF0000000000LL) |
709             ((value << 8)  & 0x000000FF00000000LL) |
710             ((value >> 8)  & 0x00000000FF000000LL) |
711             ((value >> 24) & 0x0000000000FF0000LL) |
712             ((value >> 40) & 0x000000000000FF00LL) |
713             (value << 56);
714 }
715 //---------------------------------------------------------------------------
716 void SwapBytes(int16_t & value)
717 {
718     uint16_t temp = value;
719     SwapBytes(temp);
720     value = temp;
721 }
722 //---------------------------------------------------------------------------
723 void SwapBytes(int32_t & value)
724 {
725     uint32_t temp = value;
726     SwapBytes(temp);
727     value = temp;
728 }
729 //---------------------------------------------------------------------------
730 void SwapBytes(int64_t & value)
731 {
732     uint64_t temp = value;
733     SwapBytes(temp);
734     value = temp;
735 }
736 //---------------------------------------------------------------------------
737 int str2x(const std::string & str, int & x)
738 {
739 x = strtol(str.c_str(), NULL, 10);
740
741 if (errno == ERANGE)
742     return -1;
743
744 return 0;
745 }
746 //---------------------------------------------------------------------------
747 int str2x(const std::string & str, unsigned & x)
748 {
749 x = strtoul(str.c_str(), NULL, 10);
750
751 if (errno == ERANGE)
752     return -1;
753
754 return 0;
755 }
756 //---------------------------------------------------------------------------
757 int str2x(const std::string & str, long & x)
758 {
759 x = strtol(str.c_str(), NULL, 10);
760
761 if (errno == ERANGE)
762     return -1;
763
764 return 0;
765 }
766 //---------------------------------------------------------------------------
767 int str2x(const std::string & str, unsigned long & x)
768 {
769 x = strtoul(str.c_str(), NULL, 10);
770
771 if (errno == ERANGE)
772     return -1;
773
774 return 0;
775 }
776 #ifndef WIN32
777 //---------------------------------------------------------------------------
778 int str2x(const std::string & str, long long & x)
779 {
780 x = strtoll(str.c_str(), NULL, 10);
781
782 if (errno == ERANGE)
783     return -1;
784
785 return 0;
786 }
787 //---------------------------------------------------------------------------
788 int str2x(const std::string & str, unsigned long long & x)
789 {
790 x = strtoull(str.c_str(), NULL, 10);
791
792 if (errno == ERANGE)
793     return -1;
794
795 return 0;
796 }
797 #endif
798 //---------------------------------------------------------------------------
799 const std::string & x2str(unsigned x, std::string & s)
800 {
801 return unsigned2str(x, s);
802 }
803 //---------------------------------------------------------------------------
804 const std::string & x2str(unsigned long x, std::string & s)
805 {
806 return unsigned2str(x, s);
807 }
808 //---------------------------------------------------------------------------
809 const std::string & x2str(unsigned long long x, std::string & s)
810 {
811 return unsigned2str(x, s);
812 }
813 //---------------------------------------------------------------------------
814 std::string & TrimL(std::string & val)
815 {
816 size_t pos = val.find_first_not_of(" \t");
817 if (pos == std::string::npos)
818     {
819     val.erase(val.begin(), val.end());
820     }
821 else
822     {
823     val.erase(0, pos);
824     }
825 return val;
826 }
827 //---------------------------------------------------------------------------
828 std::string & TrimR(std::string & val)
829 {
830 size_t pos = val.find_last_not_of(" \t");
831 if (pos != std::string::npos)
832     {
833     val.erase(pos + 1);
834     }
835 return val;
836 }
837 //---------------------------------------------------------------------------
838 std::string & Trim(std::string & val)
839 {
840 return TrimR(TrimL(val));
841 }
842 //---------------------------------------------------------------------------
843 #ifdef WIN32
844 static int is_leap(unsigned y)
845 {
846     y += 1900;
847     return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
848 }
849 #endif
850 //---------------------------------------------------------------------------
851
852 time_t stg_timegm(struct tm * brokenTime)
853 {
854 #ifdef WIN32
855 static const unsigned ndays[2][12] ={
856     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
857     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
858 time_t res = 0;
859 for (int i = 70; i < brokenTime->tm_year; ++i)
860     res += is_leap(i) ? 366 : 365;
861 for (int i = 0; i < brokenTime->tm_mon; ++i)
862     res += ndays[is_leap(brokenTime->tm_year)][i];
863 res += brokenTime->tm_mday - 1;
864 res *= 24;
865 res += brokenTime->tm_hour;
866 res *= 60;
867 res += brokenTime->tm_min;
868 res *= 60;
869 res += brokenTime->tm_sec;
870 return res;
871 #else
872 #ifdef HAVE_TIMEGM
873 return timegm(brokenTime);
874 #else
875 time_t ret;
876 char *tz;
877 tz = getenv("TZ");
878 setenv("TZ", "", 1);
879 tzset();
880 ret = mktime(brokenTime);
881 if (tz)
882     setenv("TZ", tz, 1);
883 else
884     unsetenv("TZ");
885 tzset();
886 return ret;
887 #endif // HAVE_TIMEGM
888 #endif // WIN32
889 }
890 //---------------------------------------------------------------------------
891 std::string IconvString(const std::string & source,
892                         const std::string & from,
893                         const std::string & to)
894 {
895 if (source.empty())
896     return std::string();
897
898 size_t inBytesLeft = source.length() + 1;
899 size_t outBytesLeft = source.length() * 2 + 1;
900
901 char * inBuf = new char[inBytesLeft];
902 char * outBuf = new char[outBytesLeft];
903
904 strncpy(inBuf, source.c_str(), source.length());
905
906 inBuf[source.length()] = 0;
907
908 #if defined(FREE_BSD) || defined(FREE_BSD5) || defined(WIN32)
909 const char * srcPos = inBuf;
910 #else
911 char * srcPos = inBuf;
912 #endif
913 char * dstPos = outBuf;
914
915 iconv_t handle = iconv_open(to.c_str(),
916                             from.c_str());
917
918 if (handle == iconv_t(-1))
919     {
920     if (errno == EINVAL)
921         {
922         printfd(__FILE__, "IconvString(): iconv from %s to %s failed\n", from.c_str(), to.c_str());
923         delete[] outBuf;
924         delete[] inBuf;
925         return source;
926         }
927     else
928         printfd(__FILE__, "IconvString(): iconv_open error\n");
929
930     delete[] outBuf;
931     delete[] inBuf;
932     return source;
933     }
934
935 size_t res = iconv(handle,
936                    &srcPos, &inBytesLeft,
937                    &dstPos, &outBytesLeft);
938
939 if (res == size_t(-1))
940     {
941     printfd(__FILE__, "IconvString(): '%s'\n", strerror(errno));
942
943     iconv_close(handle);
944     delete[] outBuf;
945     delete[] inBuf;
946     return source;
947     }
948
949 dstPos = 0;
950
951 std::string dst(outBuf);
952
953 iconv_close(handle);
954
955 delete[] outBuf;
956 delete[] inBuf;
957
958 return dst;
959 }
960
961 int ParseYesNo(const std::string & str, bool * val)
962 {
963 if (0 == strncasecmp(str.c_str(), "yes", 3))
964     {
965     *val = true;
966     return 0;
967     }
968
969 if (0 == strncasecmp(str.c_str(), "no", 2))
970     {
971     *val = false;
972     return 0;
973     }
974
975 return -1;
976 }
977
978 int ParseInt(const std::string & str, int * val)
979 {
980 if (str2x<int>(str, *val))
981     return -1;
982 return 0;
983 }
984
985 int ParseUnsigned(const string & str, unsigned * val)
986 {
987 if (str2x<unsigned>(str, *val))
988     return -1;
989 return 0;
990 }
991
992 int ParseIntInRange(const string & str, int min, int max, int * val)
993 {
994 if (ParseInt(str, val) != 0)
995     return -1;
996
997 if (*val < min || *val > max)
998     return -1;
999
1000 return 0;
1001 }
1002
1003 int ParseUnsignedInRange(const string & str, unsigned min,
1004                          unsigned max, unsigned * val)
1005 {
1006 if (ParseUnsigned(str, val) != 0)
1007     return -1;
1008
1009 if (*val < min || *val > max)
1010     return -1;
1011
1012 return 0;
1013 }
1014
1015 bool WaitPackets(int sd)
1016 {
1017 fd_set rfds;
1018 FD_ZERO(&rfds);
1019 FD_SET(sd, &rfds);
1020
1021 struct timeval tv;
1022 tv.tv_sec = 0;
1023 tv.tv_usec = 500000;
1024
1025 int res = select(sd + 1, &rfds, NULL, NULL, &tv);
1026 if (res == -1) // Error
1027     {
1028     if (errno != EINTR)
1029         printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
1030     return false;
1031     }
1032
1033 if (res == 0) // Timeout
1034     return false;
1035
1036 return true;
1037 }