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