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